Compare commits
No commits in common. "main" and "1.7.92" have entirely different histories.
|
|
@ -1,15 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
end_of_line = lf
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = 8
|
|
||||||
max_line_length = 80
|
|
||||||
|
|
||||||
[*.xml]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
tab_width = 8
|
|
||||||
89
.gitignore
vendored
|
|
@ -1,13 +1,100 @@
|
||||||
|
*.deps
|
||||||
|
*.jpg
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
*.log
|
||||||
|
*.o
|
||||||
|
*.pc
|
||||||
|
*.so
|
||||||
*.swp
|
*.swp
|
||||||
.*.sw?
|
.*.sw?
|
||||||
.sw?
|
.sw?
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
*.trs
|
||||||
*~
|
*~
|
||||||
ctags
|
ctags
|
||||||
cscope.out
|
cscope.out
|
||||||
|
.libs
|
||||||
|
.dirstamp
|
||||||
|
/aclocal.m4
|
||||||
|
/autom4te.cache
|
||||||
|
/build-aux/
|
||||||
|
/config.guess
|
||||||
|
/config.h
|
||||||
|
/config.h.in
|
||||||
|
/config.log
|
||||||
|
/config.mk
|
||||||
|
/config.status
|
||||||
|
/config.sub
|
||||||
|
/configure
|
||||||
|
/depcomp
|
||||||
|
/install-sh
|
||||||
|
/libtool
|
||||||
|
/ltmain.sh
|
||||||
|
/logs
|
||||||
|
/missing
|
||||||
|
/stamp-h1
|
||||||
|
/test-driver
|
||||||
|
/weston.ini
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
TAGS
|
TAGS
|
||||||
|
protocol/.*.valid
|
||||||
|
protocol/*.[ch]
|
||||||
|
|
||||||
00*.patch
|
00*.patch
|
||||||
|
|
||||||
build/
|
weston-calibrator
|
||||||
|
weston-clickdot
|
||||||
|
weston-cliptest
|
||||||
|
weston-dnd
|
||||||
|
weston-editor
|
||||||
|
weston-eventdemo
|
||||||
|
weston-flower
|
||||||
|
weston-fullscreen
|
||||||
|
weston-gears
|
||||||
|
weston-image
|
||||||
|
weston-nested
|
||||||
|
weston-nested-client
|
||||||
|
weston-presentation-shm
|
||||||
|
weston-resizor
|
||||||
|
weston-scaler
|
||||||
|
weston-simple-egl
|
||||||
|
weston-simple-shm
|
||||||
|
weston-simple-touch
|
||||||
|
weston-simple-damage
|
||||||
|
weston-smoke
|
||||||
|
weston-stacking
|
||||||
|
weston-subsurfaces
|
||||||
|
weston-transformed
|
||||||
|
weston-view
|
||||||
|
|
||||||
|
weston-keyboard
|
||||||
|
libtoytoolkit.a
|
||||||
|
weston-desktop-shell
|
||||||
|
weston-ivi-shell-user-interface
|
||||||
|
weston-info
|
||||||
|
weston-screensaver
|
||||||
|
weston-screenshooter
|
||||||
|
weston-tablet-shell
|
||||||
|
weston-terminal
|
||||||
|
weston-multi-resource
|
||||||
|
weston-simple-im
|
||||||
|
git-version.h
|
||||||
|
version.h
|
||||||
|
weston
|
||||||
|
weston-launch
|
||||||
|
spring-tool
|
||||||
|
|
||||||
|
*.weston
|
||||||
|
*.test
|
||||||
|
*.ivi
|
||||||
|
wcap-decode
|
||||||
|
matrix-test
|
||||||
|
setbacklight
|
||||||
|
weston.1
|
||||||
|
weston-drm.7
|
||||||
|
weston.ini.5
|
||||||
|
|
||||||
|
/tests/weston-ivi.ini
|
||||||
|
|
|
||||||
656
.gitlab-ci.yml
|
|
@ -1,656 +0,0 @@
|
||||||
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
|
|
||||||
|
|
||||||
.templates_sha: &template_sha 32afe5644697e503af18a736587c8619fa036a72 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
|
||||||
# This file uses the freedesktop ci-templates to build Weston and run our
|
|
||||||
# tests in CI.
|
|
||||||
#
|
|
||||||
# ci-templates uses a multi-stage build process. First, the base container
|
|
||||||
# image is built which contains the core distribution, the toolchain, and
|
|
||||||
# all our build dependencies. This container is aggressively cached; if a
|
|
||||||
# container image matching $FDO_DISTRIBUTION_TAG is found in either the
|
|
||||||
# upstream repo (wayland/weston) or the user's downstream repo, it is
|
|
||||||
# reused for the build. This gives us predictability of build and far
|
|
||||||
# quicker runtimes, however it means that any changes to the base container
|
|
||||||
# must also change $FDO_DISTRIBUTION_TAG. When changing this, please use
|
|
||||||
# the current date as well as a unique build identifier.
|
|
||||||
#
|
|
||||||
# After the container is either rebuilt (tag mismatch) or reused (tag
|
|
||||||
# previously used), the build stage executes within this container.
|
|
||||||
#
|
|
||||||
# The final stage is used to expose documentation and coverage information,
|
|
||||||
# including publishing documentation to the public site when built on the
|
|
||||||
# main branch.
|
|
||||||
#
|
|
||||||
# Apart from the 'variables', 'include', and 'stages' top-level anchors,
|
|
||||||
# everything not beginning with a dot ('.') is the name of a job which will
|
|
||||||
# be executed as part of CI, unless the rules specify that it should not be
|
|
||||||
# run.
|
|
||||||
#
|
|
||||||
# Variables prefixed with CI_ are generally provided by GitLab itself;
|
|
||||||
# variables prefixed with FDO_ and templates prefixed by .fdo are provided
|
|
||||||
# by the ci-templates.
|
|
||||||
#
|
|
||||||
# For more information on GitLab CI, including the YAML syntax, see:
|
|
||||||
# https://docs.gitlab.com/ee/ci/yaml/README.html
|
|
||||||
#
|
|
||||||
# Note that freedesktop.org uses the 'Community Edition' of GitLab, so features
|
|
||||||
# marked as 'premium' or 'ultimate' are not available to us.
|
|
||||||
#
|
|
||||||
# For more information on ci-templates, see:
|
|
||||||
# - documentation at https://freedesktop.pages.freedesktop.org/ci-templates/
|
|
||||||
# - repo at https://gitlab.freedesktop.org/freedesktop/ci-templates/
|
|
||||||
|
|
||||||
variables:
|
|
||||||
FDO_UPSTREAM_REPO: wayland/weston
|
|
||||||
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
|
|
||||||
FDO_DISTRIBUTION_TAG: '2026-04-01-mesa-26.0.4'
|
|
||||||
|
|
||||||
|
|
||||||
include:
|
|
||||||
# Here we use a fixed ref in order to isolate ourselves from ci-templates
|
|
||||||
# API changes. If you need new features from ci-templates you must bump
|
|
||||||
# this to the current SHA you require from the ci-templates repo, however
|
|
||||||
# be aware that you may need to account for API changes when doing so.
|
|
||||||
- project: 'freedesktop/ci-templates'
|
|
||||||
ref: *template_sha
|
|
||||||
file: '/templates/debian.yml'
|
|
||||||
- project: 'freedesktop/ci-templates'
|
|
||||||
ref: *template_sha
|
|
||||||
file: '/templates/ci-fairy.yml'
|
|
||||||
|
|
||||||
.default-rules:
|
|
||||||
rules:
|
|
||||||
# do not duplicate pipelines on merge pipelines
|
|
||||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
|
|
||||||
when: never
|
|
||||||
# we need a default case though, so all the rest still run
|
|
||||||
- when: on_success
|
|
||||||
|
|
||||||
default:
|
|
||||||
retry:
|
|
||||||
max: 2
|
|
||||||
when: runner_system_failure
|
|
||||||
|
|
||||||
.merge-rules:
|
|
||||||
rules:
|
|
||||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
||||||
when: always
|
|
||||||
- when: never
|
|
||||||
|
|
||||||
# Define the build stages. These are used for UI grouping as well as
|
|
||||||
# dependencies.
|
|
||||||
stages:
|
|
||||||
- "Merge request checks"
|
|
||||||
- "Pre Base container"
|
|
||||||
- "Base container"
|
|
||||||
- "Full build and test"
|
|
||||||
- "No-GL/Vulkan build and test"
|
|
||||||
- "Other builds"
|
|
||||||
- pages
|
|
||||||
|
|
||||||
|
|
||||||
# Base variables used for anything using a Debian environment
|
|
||||||
.os-debian-lts:
|
|
||||||
variables:
|
|
||||||
BUILD_OS: debian
|
|
||||||
LLVM_VERSION: 15
|
|
||||||
USE_DEBIAN_BACKPORTS: y
|
|
||||||
PACKAGES_SPECIFIC: vulkan-validationlayers-dev
|
|
||||||
FREERDP_VERSION: 2
|
|
||||||
FDO_DISTRIBUTION_VERSION: bookworm
|
|
||||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
|
||||||
|
|
||||||
.os-debian:
|
|
||||||
variables:
|
|
||||||
BUILD_OS: debian
|
|
||||||
LLVM_VERSION: 19
|
|
||||||
FREERDP_VERSION: 3
|
|
||||||
USE_DEBIAN_BACKPORTS: y
|
|
||||||
PACKAGES_SPECIFIC: vulkan-utility-libraries-dev libpolly-19-dev libclang-rt-19-dev python3-standard-imghdr
|
|
||||||
# If you upgrade from trixie, see the use_tls=0 notes in tests/meson.build.
|
|
||||||
FDO_DISTRIBUTION_VERSION: trixie
|
|
||||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
|
||||||
|
|
||||||
# Does not inherit .default-rules as we only want it to run in MR context.
|
|
||||||
check-commit:
|
|
||||||
extends:
|
|
||||||
- .fdo.ci-fairy
|
|
||||||
- .merge-rules
|
|
||||||
stage: "Merge request checks"
|
|
||||||
script:
|
|
||||||
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
|
|
||||||
variables:
|
|
||||||
GIT_DEPTH: 100
|
|
||||||
artifacts:
|
|
||||||
reports:
|
|
||||||
junit: results.xml
|
|
||||||
|
|
||||||
.debian-lts-x86_64:
|
|
||||||
extends:
|
|
||||||
- .os-debian-lts
|
|
||||||
variables:
|
|
||||||
BUILD_ARCH: "x86-64"
|
|
||||||
KERNEL_IMAGE: "bzImage"
|
|
||||||
KERNEL_DEFCONFIG: "x86_64_defconfig"
|
|
||||||
|
|
||||||
.debian-x86_64:
|
|
||||||
extends:
|
|
||||||
- .os-debian
|
|
||||||
variables:
|
|
||||||
BUILD_ARCH: "x86-64"
|
|
||||||
KERNEL_IMAGE: "bzImage"
|
|
||||||
KERNEL_DEFCONFIG: "x86_64_defconfig"
|
|
||||||
|
|
||||||
.debian-lts-armv7:
|
|
||||||
extends:
|
|
||||||
- .os-debian-lts
|
|
||||||
variables:
|
|
||||||
BUILD_ARCH: "armv7"
|
|
||||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
|
||||||
|
|
||||||
.debian-armv7:
|
|
||||||
extends:
|
|
||||||
- .os-debian
|
|
||||||
variables:
|
|
||||||
BUILD_ARCH: "armv7"
|
|
||||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
|
||||||
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
|
|
||||||
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
|
|
||||||
# Inhibit installation of freerdp-dev
|
|
||||||
FREERDP_VERSION: 0
|
|
||||||
|
|
||||||
.debian-lts-aarch64:
|
|
||||||
extends:
|
|
||||||
- .os-debian-lts
|
|
||||||
variables:
|
|
||||||
BUILD_ARCH: "aarch64"
|
|
||||||
KERNEL_IMAGE: "Image"
|
|
||||||
KERNEL_DEFCONFIG: "defconfig"
|
|
||||||
QEMU_SMP: 8 # built-in QEmu limit
|
|
||||||
|
|
||||||
.debian-aarch64:
|
|
||||||
extends:
|
|
||||||
- .os-debian
|
|
||||||
variables:
|
|
||||||
BUILD_ARCH: "aarch64"
|
|
||||||
KERNEL_IMAGE: "Image"
|
|
||||||
KERNEL_DEFCONFIG: "defconfig"
|
|
||||||
QEMU_SMP: 8 # built-in QEmu limit
|
|
||||||
|
|
||||||
base-container-pre:
|
|
||||||
rules:
|
|
||||||
# this run always in merge request
|
|
||||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
||||||
when: always
|
|
||||||
# run always on main to allow docs to publish
|
|
||||||
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_PATH == "wayland/weston" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
|
|
||||||
when: always
|
|
||||||
# allow to run manually in a branch
|
|
||||||
- when: manual
|
|
||||||
stage: "Pre Base container"
|
|
||||||
script: echo "exit 0"
|
|
||||||
|
|
||||||
# Build our base container image, which contains the core distribution, the
|
|
||||||
# toolchain, and all our build dependencies. This will be reused in the build
|
|
||||||
# stage.
|
|
||||||
x86_64-debian-lts-container_prep:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-lts-x86_64
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
timeout: 30m
|
|
||||||
needs:
|
|
||||||
- job: base-container-pre
|
|
||||||
stage: "Base container"
|
|
||||||
|
|
||||||
x86_64-debian-container_prep:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-x86_64
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
needs:
|
|
||||||
- job: base-container-pre
|
|
||||||
timeout: 30m
|
|
||||||
stage: "Base container"
|
|
||||||
|
|
||||||
armv7-debian-lts-container_prep:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-lts-armv7
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
needs:
|
|
||||||
- job: base-container-pre
|
|
||||||
timeout: 30m
|
|
||||||
stage: "Base container"
|
|
||||||
|
|
||||||
armv7-debian-container_prep:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-armv7
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
needs:
|
|
||||||
- job: base-container-pre
|
|
||||||
timeout: 30m
|
|
||||||
stage: "Base container"
|
|
||||||
|
|
||||||
aarch64-debian-lts-container_prep:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-lts-aarch64
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
needs:
|
|
||||||
- job: base-container-pre
|
|
||||||
timeout: 30m
|
|
||||||
stage: "Base container"
|
|
||||||
|
|
||||||
aarch64-debian-container_prep:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-aarch64
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
needs:
|
|
||||||
- job: base-container-pre
|
|
||||||
timeout: 30m
|
|
||||||
stage: "Base container"
|
|
||||||
|
|
||||||
# Core templates for all of our build steps. These are reused by all build jobs
|
|
||||||
# through the `extends` keyword.
|
|
||||||
.build-env:
|
|
||||||
timeout: 15m
|
|
||||||
variables:
|
|
||||||
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
|
|
||||||
BUILDDIR_WESTINY: $CI_PROJECT_DIR/build-westiny-$CI_JOB_NAME
|
|
||||||
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
|
||||||
PREFIX_WESTINY: $CI_PROJECT_DIR/prefix-westiny-$CI_JOB_NAME
|
|
||||||
before_script:
|
|
||||||
- export PATH=~/.local/bin:$PATH
|
|
||||||
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
|
||||||
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
|
|
||||||
- export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
|
|
||||||
- mkdir "$BUILDDIR" "$PREFIX"
|
|
||||||
- mkdir "$BUILDDIR_WESTINY" "$PREFIX_WESTINY"
|
|
||||||
|
|
||||||
.build-with-clang:
|
|
||||||
variables:
|
|
||||||
CC: clang-$LLVM_VERSION
|
|
||||||
CC_LD: lld-$LLVM_VERSION
|
|
||||||
CXX: clang++-$LLVM_VERSION
|
|
||||||
CXX_LD: lld-$LLVM_VERSION
|
|
||||||
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
|
|
||||||
|
|
||||||
# Extends the core build templates to also provide for running our testing. We
|
|
||||||
# run this inside a virtme (qemu wrapper) VM environment so we can test the DRM
|
|
||||||
# backend using the 'vkms' virtual driver under Linux.
|
|
||||||
.build-and-test:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
variables:
|
|
||||||
SANITIZE: "-Db_sanitize=address"
|
|
||||||
script:
|
|
||||||
- "${CI_PROJECT_DIR}/.gitlab-ci/build.sh"
|
|
||||||
- "${CI_PROJECT_DIR}/.gitlab-ci/test.sh"
|
|
||||||
|
|
||||||
artifacts:
|
|
||||||
name: weston-$CI_COMMIT_SHA
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- $BUILDDIR/*.png
|
|
||||||
- $BUILDDIR/meson-logs
|
|
||||||
- $BUILDDIR/dmesg.log
|
|
||||||
- $BUILDDIR/weston-virtme
|
|
||||||
- $PREFIX
|
|
||||||
reports:
|
|
||||||
junit: $BUILDDIR/meson-logs/testlog.junit.xml
|
|
||||||
|
|
||||||
# Same as above, but without running any tests.
|
|
||||||
.build-no-test:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
script:
|
|
||||||
- "${CI_PROJECT_DIR}/.gitlab-ci/build.sh"
|
|
||||||
artifacts:
|
|
||||||
name: weston-$CI_COMMIT_SHA
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- $BUILDDIR/meson-logs
|
|
||||||
- $PREFIX
|
|
||||||
|
|
||||||
# OS/architecture-specific variants
|
|
||||||
.build-env-debian-lts-x86_64:
|
|
||||||
extends:
|
|
||||||
- .debian-lts-x86_64
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
- .build-env
|
|
||||||
needs:
|
|
||||||
- job: x86_64-debian-lts-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.build-env-debian-x86_64:
|
|
||||||
extends:
|
|
||||||
- .debian-x86_64
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
- .build-env
|
|
||||||
needs:
|
|
||||||
- job: x86_64-debian-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.build-env-debian-lts-armv7:
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
extends:
|
|
||||||
- .debian-lts-armv7
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
- .build-env
|
|
||||||
needs:
|
|
||||||
- job: armv7-debian-lts-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.build-env-debian-armv7:
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
extends:
|
|
||||||
- .debian-armv7
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
- .build-env
|
|
||||||
needs:
|
|
||||||
- job: armv7-debian-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.build-env-debian-lts-aarch64:
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
extends:
|
|
||||||
- .debian-lts-aarch64
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
- .build-env
|
|
||||||
needs:
|
|
||||||
- job: aarch64-debian-lts-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.build-env-debian-aarch64:
|
|
||||||
tags:
|
|
||||||
- aarch64
|
|
||||||
extends:
|
|
||||||
- .debian-aarch64
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
- .build-env
|
|
||||||
needs:
|
|
||||||
- job: aarch64-debian-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.test-env-debian-lts-x86_64:
|
|
||||||
tags:
|
|
||||||
- kvm
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-lts-x86_64
|
|
||||||
- .build-and-test
|
|
||||||
needs:
|
|
||||||
- job: x86_64-debian-lts-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.test-env-debian-x86_64:
|
|
||||||
tags:
|
|
||||||
- kvm
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-x86_64
|
|
||||||
- .build-and-test
|
|
||||||
needs:
|
|
||||||
- job: x86_64-debian-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.test-env-debian-lts-aarch64:
|
|
||||||
tags:
|
|
||||||
- kvm-aarch64
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-lts-aarch64
|
|
||||||
- .build-and-test
|
|
||||||
needs:
|
|
||||||
- job: aarch64-debian-lts-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
.test-env-debian-aarch64:
|
|
||||||
tags:
|
|
||||||
- kvm-aarch64
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-aarch64
|
|
||||||
- .build-and-test
|
|
||||||
needs:
|
|
||||||
- job: aarch64-debian-container_prep
|
|
||||||
artifacts: false
|
|
||||||
|
|
||||||
# Full build (gcov + perfetto) used for testing under KVM.
|
|
||||||
.build-options-full:
|
|
||||||
stage: "Full build and test"
|
|
||||||
variables:
|
|
||||||
MESON_OPTIONS: >
|
|
||||||
-Doptimization=0
|
|
||||||
-Db_coverage=true
|
|
||||||
--force-fallback-for=perfetto
|
|
||||||
-Dperfetto=true
|
|
||||||
-Dperfetto:werror=false
|
|
||||||
-Dwerror=true
|
|
||||||
-Dtest-skip-is-failure=true
|
|
||||||
-Ddeprecated-remoting=true
|
|
||||||
-Ddeprecated-pipewire=true
|
|
||||||
after_script:
|
|
||||||
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
|
|
||||||
- ninja -C "$BUILDDIR" coverage-xml
|
|
||||||
|
|
||||||
# Full build, (without gcov and perfetto)
|
|
||||||
.build-options-full-v2:
|
|
||||||
stage: "Full build and test"
|
|
||||||
variables:
|
|
||||||
MESON_OPTIONS: >
|
|
||||||
-Doptimization=0
|
|
||||||
-Dwerror=true
|
|
||||||
-Dtest-skip-is-failure=true
|
|
||||||
|
|
||||||
x86_64-debian-lts-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-x86_64
|
|
||||||
- .build-options-full
|
|
||||||
artifacts:
|
|
||||||
reports:
|
|
||||||
coverage_report:
|
|
||||||
coverage_format: cobertura
|
|
||||||
path: $BUILDDIR/meson-logs/coverage.xml
|
|
||||||
|
|
||||||
x86_64-debian-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-x86_64
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
aarch64-debian-lts-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-aarch64
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
aarch64-debian-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-aarch64
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
x86_64-clang-debian-lts-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-x86_64
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
x86_64-clang-debian-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-x86_64
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
aarch64-clang-debian-lts-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-aarch64
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
aarch64-clang-debian-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-aarch64
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-options-full-v2
|
|
||||||
|
|
||||||
# Docs should be invariant on all architectures, so we only do it on Debian
|
|
||||||
# x86-64.
|
|
||||||
docs-build:
|
|
||||||
stage: "Other builds"
|
|
||||||
variables:
|
|
||||||
MESON_OPTIONS: >
|
|
||||||
-Dwerror=true
|
|
||||||
-Ddoc=true
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-x86_64
|
|
||||||
- .build-no-test
|
|
||||||
|
|
||||||
# Building without gl-renderer and/or vulkan-renderer, to make sure this keeps working.
|
|
||||||
.build-options-no-gl-no-vulkan:
|
|
||||||
stage: "No-GL/Vulkan build and test"
|
|
||||||
variables:
|
|
||||||
MESON_OPTIONS: >
|
|
||||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
|
||||||
-Drenderer-gl=false
|
|
||||||
-Drenderer-vulkan=false
|
|
||||||
-Dwerror=true
|
|
||||||
|
|
||||||
.build-options-no-gl:
|
|
||||||
stage: "No-GL/Vulkan build and test"
|
|
||||||
variables:
|
|
||||||
MESON_OPTIONS: >
|
|
||||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
|
||||||
-Drenderer-gl=false
|
|
||||||
-Dwerror=true
|
|
||||||
|
|
||||||
.build-options-no-vulkan:
|
|
||||||
stage: "No-GL/Vulkan build and test"
|
|
||||||
variables:
|
|
||||||
MESON_OPTIONS: >
|
|
||||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
|
||||||
-Drenderer-vulkan=false
|
|
||||||
-Dwerror=true
|
|
||||||
|
|
||||||
x86_64-debian-lts-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-x86_64
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
x86_64-debian-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-x86_64
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
armv7-debian-lts-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-lts-armv7
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
armv7-debian-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-armv7
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
armv7-clang-debian-lts-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-lts-armv7
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
armv7-clang-debian-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-armv7
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
aarch64-debian-lts-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-aarch64
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
aarch64-debian-no-gl-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-aarch64
|
|
||||||
- .build-options-no-gl-no-vulkan
|
|
||||||
|
|
||||||
x86_64-debian-no-gl-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-x86_64
|
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
x86_64-debian-no-vulkan-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-x86_64
|
|
||||||
- .build-options-no-vulkan
|
|
||||||
|
|
||||||
|
|
||||||
# Expose docs and coverage reports, so we can show users any changes to these
|
|
||||||
# inside their merge requests, letting us check them before merge.
|
|
||||||
#
|
|
||||||
# This does not build the docs or coverage information itself, but just reuses
|
|
||||||
# the docs and coverage information from the x86-64 Debian builds as the
|
|
||||||
# canonical sources of coverage information; the docs themselves should be
|
|
||||||
# invariant across any architecture or OS.
|
|
||||||
docs-and-coverage:
|
|
||||||
extends:
|
|
||||||
- .default-rules
|
|
||||||
- .debian-lts-x86_64
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
stage: pages
|
|
||||||
needs:
|
|
||||||
- job: docs-build
|
|
||||||
artifacts: true
|
|
||||||
- job: x86_64-debian-lts-full-build
|
|
||||||
artifacts: true
|
|
||||||
timeout: 5m
|
|
||||||
script:
|
|
||||||
- mv prefix-weston-docs-build/share/doc/weston Documentation
|
|
||||||
- mv build-weston-x86_64-debian-lts-full-build/meson-logs/coveragereport Test_Coverage
|
|
||||||
- rm Test_Coverage/gcov.css
|
|
||||||
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
|
|
||||||
- cp doc/style/*.png Test_Coverage/
|
|
||||||
- rm -rf build-* prefix-*
|
|
||||||
artifacts:
|
|
||||||
expose_as: 'Documentation preview and test coverage report'
|
|
||||||
paths:
|
|
||||||
- Documentation/
|
|
||||||
- Test_Coverage/
|
|
||||||
|
|
||||||
# Generate the documentation for https://wayland.pages.freedesktop.org/weston/
|
|
||||||
# Anything under public/ is published to this URL.
|
|
||||||
#
|
|
||||||
# Does not inherit .default-rules as it should only run in our default branch for
|
|
||||||
# the upstream repo.
|
|
||||||
pages:
|
|
||||||
extends:
|
|
||||||
- .debian-x86_64
|
|
||||||
- .fdo.suffixed-image@debian
|
|
||||||
stage: pages
|
|
||||||
timeout: 5m
|
|
||||||
needs:
|
|
||||||
- job: docs-build
|
|
||||||
artifacts: true
|
|
||||||
script:
|
|
||||||
- export PREFIX=$(pwd)/prefix-weston-docs-build
|
|
||||||
- mkdir public
|
|
||||||
- cp -R $PREFIX/share/doc/weston/* public/
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
rules:
|
|
||||||
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_PATH == "wayland/weston" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
|
|
||||||
when: on_success
|
|
||||||
- when: never
|
|
||||||
|
|
@ -1,244 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# Builds the dependencies required for any OS/architecture combination. See
|
|
||||||
# .gitlab-ci.yml for more information. This script is called from an
|
|
||||||
# OS-specific build scripts like debian-install.sh.
|
|
||||||
|
|
||||||
source "${FDO_CI_BASH_HELPERS}"
|
|
||||||
|
|
||||||
set -o xtrace -o errexit
|
|
||||||
|
|
||||||
# Set concurrency to an appropriate level for our shared runners, falling back
|
|
||||||
# to the conservative default form before we had this variable.
|
|
||||||
export MAKEFLAGS="-j${FDO_CI_CONCURRENT:-4}"
|
|
||||||
export NINJAFLAGS="-j${FDO_CI_CONCURRENT:-4}"
|
|
||||||
|
|
||||||
# When calling pip in newer versions, we're required to pass
|
|
||||||
# --break-system-packages so it knows that we did really want to call pip and
|
|
||||||
# aren't just doing it by accident.
|
|
||||||
PIP_ARGS="--user"
|
|
||||||
case "$FDO_DISTRIBUTION_VERSION" in
|
|
||||||
bullseye)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
PIP_ARGS="$PIP_ARGS --break-system-packages"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Build and install Meson. Generally we want to keep this in sync with what
|
|
||||||
# we require inside meson.build.
|
|
||||||
fdo_log_section_start_collapsed install_meson "install_meson"
|
|
||||||
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.4.2
|
|
||||||
export PATH=$HOME/.local/bin:$PATH
|
|
||||||
|
|
||||||
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
|
|
||||||
# generation), Doxygen (parse structures/functions/comments from source code),
|
|
||||||
# Breathe (a bridge between Doxygen and Sphinx), and we use the Read the Docs
|
|
||||||
# theme for the final presentation.
|
|
||||||
pip3 install $PIP_ARGS sphinx==4.2.0
|
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-applehelp==1.0.4
|
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-devhelp==1.0.2
|
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-htmlhelp==2.0.0
|
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-jsmath==1.0.1
|
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-qthelp==1.0.3
|
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
|
|
||||||
pip3 install $PIP_ARGS breathe==4.31.0
|
|
||||||
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
|
|
||||||
fdo_log_section_end install_meson
|
|
||||||
|
|
||||||
|
|
||||||
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
|
|
||||||
# predictably test the DRM backend in the absence of real hardware. We lock the
|
|
||||||
# version here so we see predictable results.
|
|
||||||
#
|
|
||||||
# To run this we use virtme-ng, a QEMU wrapper. It is a fork from virtme, whose
|
|
||||||
# development stalled.
|
|
||||||
#
|
|
||||||
# virtme-ng makes our lives easier by abstracting handling of the console,
|
|
||||||
# filesystem, etc, so we can pretend that the VM we execute in is actually
|
|
||||||
# just a regular container.
|
|
||||||
fdo_log_section_start_collapsed install_kernel "install_kernel"
|
|
||||||
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
|
||||||
git clone --depth=1 --branch drm-misc-next-2026-03-20 https://gitlab.freedesktop.org/drm/misc/kernel.git linux
|
|
||||||
cd linux
|
|
||||||
|
|
||||||
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
|
|
||||||
LINUX_ARCH=x86
|
|
||||||
elif [[ "$BUILD_ARCH" = "aarch64" ]]; then
|
|
||||||
LINUX_ARCH=arm64
|
|
||||||
else
|
|
||||||
echo "Invalid or missing \$BUILD_ARCH"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "${KERNEL_DEFCONFIG}" ]]; then
|
|
||||||
echo "Invalid or missing \$KERNEL_DEFCONFIG"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
if [[ -z "${KERNEL_IMAGE}" ]]; then
|
|
||||||
echo "Invalid or missing \$KERNEL_IMAGE"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
make ARCH=${LINUX_ARCH} ${KERNEL_DEFCONFIG}
|
|
||||||
make ARCH=${LINUX_ARCH} kvm_guest.config
|
|
||||||
./scripts/config \
|
|
||||||
--enable CONFIG_DRM \
|
|
||||||
--enable CONFIG_DRM_KMS_HELPER \
|
|
||||||
--enable CONFIG_DRM_VKMS \
|
|
||||||
--enable CONFIG_UDMABUF
|
|
||||||
make ARCH=${LINUX_ARCH} oldconfig
|
|
||||||
make ARCH=${LINUX_ARCH}
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
mkdir /weston-virtme
|
|
||||||
mv linux/arch/${LINUX_ARCH}/boot/${KERNEL_IMAGE} /weston-virtme/
|
|
||||||
mv linux/.config /weston-virtme/.config
|
|
||||||
rm -rf linux
|
|
||||||
|
|
||||||
git clone --depth=1 --branch=v1.25 --recurse-submodules https://github.com/arighi/virtme-ng.git virtme
|
|
||||||
cd virtme
|
|
||||||
./setup.py install
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
fdo_log_section_end install_kernel
|
|
||||||
|
|
||||||
# Build and install Wayland; keep this version in sync with our dependency
|
|
||||||
# in meson.build.
|
|
||||||
fdo_log_section_start_collapsed install_wayland "install_wayland"
|
|
||||||
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
|
|
||||||
cd wayland
|
|
||||||
git show -s HEAD
|
|
||||||
meson setup build --wrap-mode=nofallback -Ddocumentation=false
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf wayland
|
|
||||||
|
|
||||||
# Keep this version in sync with our dependency in meson.build. If you wish to
|
|
||||||
# raise a MR against custom protocol, please change this reference to clone
|
|
||||||
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
|
|
||||||
git clone --branch 1.46 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
|
||||||
cd wayland-protocols
|
|
||||||
git show -s HEAD
|
|
||||||
meson setup build --wrap-mode=nofallback -Dtests=false
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf wayland-protocols
|
|
||||||
fdo_log_section_end install_wayland
|
|
||||||
|
|
||||||
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
|
|
||||||
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa
|
|
||||||
# depends on 2.4.109 as well.
|
|
||||||
# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30}
|
|
||||||
fdo_log_section_start_collapsed install_libdrm "install_libdrm"
|
|
||||||
git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
|
||||||
cd drm
|
|
||||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
|
||||||
-Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf drm
|
|
||||||
fdo_log_section_end install_libdrm
|
|
||||||
|
|
||||||
# Build and install Vulkan-Headers with a defined version, mostly because
|
|
||||||
# the version in Debian 11 (bullseye) is too old to build vulkan-renderer.
|
|
||||||
fdo_log_section_start_collapsed install_vulkan_headers "install_vulkan_headers"
|
|
||||||
git clone --branch sdk-1.3.239.0 --depth=1 https://github.com/KhronosGroup/Vulkan-Headers
|
|
||||||
cd Vulkan-Headers
|
|
||||||
cmake -G Ninja -B build
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf Vulkan-Headers
|
|
||||||
fdo_log_section_end install_vulkan_headers
|
|
||||||
|
|
||||||
# Build and install our own version of Mesa. Debian provides a perfectly usable
|
|
||||||
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
|
|
||||||
# This doesn't work for our tests which expect pixel-precise reproduction, so
|
|
||||||
# we lock it to a set version for more predictability. If you need newer
|
|
||||||
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
|
|
||||||
# please be prepared for some of the tests to change output, which will need to
|
|
||||||
# be manually inspected for correctness.
|
|
||||||
fdo_log_section_start_collapsed install_mesa "install_mesa"
|
|
||||||
|
|
||||||
# Needed for Mesa >= 25.3
|
|
||||||
git clone --branch 12.2.0 --depth=1 https://github.com/KhronosGroup/glslang
|
|
||||||
cd glslang
|
|
||||||
cmake -G Ninja -B build
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf glslang
|
|
||||||
|
|
||||||
git clone --branch mesa-26.0.4 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
|
||||||
cd mesa
|
|
||||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
|
||||||
-Dgallium-drivers=llvmpipe -Dvulkan-drivers=swrast -Dvideo-codecs= \
|
|
||||||
-Degl=enabled -Dgbm=enabled -Dgles2=enabled -Dllvm=enabled \
|
|
||||||
-Dshared-glapi=enabled -Dglx=disabled
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf mesa
|
|
||||||
fdo_log_section_end install_mesa
|
|
||||||
|
|
||||||
# PipeWire is used for remoting support. Unlike our other dependencies its
|
|
||||||
# behaviour will be stable, however as a pre-1.0 project its API is not yet
|
|
||||||
# stable, so again we lock it to a fixed version.
|
|
||||||
#
|
|
||||||
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
|
|
||||||
fdo_log_section_start_collapsed install_pipewire "install_pipewire"
|
|
||||||
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
|
|
||||||
cd pipewire-src
|
|
||||||
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
|
|
||||||
meson setup build --wrap-mode=nofallback
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf pipewire-src
|
|
||||||
fdo_log_section_end install_pipewire
|
|
||||||
|
|
||||||
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
|
|
||||||
# We use this for our tests using the DRM backend.
|
|
||||||
fdo_log_section_start_collapsed install_seatd "install_seatd"
|
|
||||||
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
|
|
||||||
cd seatd
|
|
||||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
|
||||||
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf seatd
|
|
||||||
fdo_log_section_end install_seatd
|
|
||||||
|
|
||||||
# Build and install aml and neatvnc, which are required for the VNC backend
|
|
||||||
fdo_log_section_start_collapsed install_aml_neatvnc "install_aml_neatvnc"
|
|
||||||
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
|
|
||||||
cd aml
|
|
||||||
meson setup build --wrap-mode=nofallback
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf aml
|
|
||||||
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
|
|
||||||
cd neatvnc
|
|
||||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf neatvnc
|
|
||||||
fdo_log_section_end install_aml_neatvnc
|
|
||||||
|
|
||||||
# Build and install libdisplay-info, used by drm-backend
|
|
||||||
fdo_log_section_start_collapsed install_libdisplay-info "install_libdisplay-info"
|
|
||||||
git clone --branch 0.2.0 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
|
||||||
cd libdisplay-info
|
|
||||||
meson setup build --wrap-mode=nofallback
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf libdisplay-info
|
|
||||||
fdo_log_section_end install_libdisplay-info
|
|
||||||
|
|
||||||
# Build and install lcms2, which we use to support color-management.
|
|
||||||
fdo_log_section_start_collapsed install_lcms2 "install_lcms2"
|
|
||||||
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
|
|
||||||
cd lcms2
|
|
||||||
git checkout -b snapshot lcms2.16
|
|
||||||
meson setup build --wrap-mode=nofallback
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
|
||||||
cd ..
|
|
||||||
rm -rf lcms2
|
|
||||||
fdo_log_section_end install_lcms2
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
source "${FDO_CI_BASH_HELPERS}"
|
|
||||||
|
|
||||||
fdo_log_section_start_collapsed build_weston "build_weston"
|
|
||||||
cd "$BUILDDIR"
|
|
||||||
meson --prefix="$PREFIX" --wrap-mode=nofallback $SANITIZE ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
|
||||||
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
|
||||||
ninja install
|
|
||||||
|
|
||||||
if [ "$CI_JOB_NAME" == "x86_64-debian-full-build" ]; then
|
|
||||||
cd "$BUILDDIR_WESTINY"
|
|
||||||
export NPREFIX=$CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
|
||||||
export PKG_CONFIG_PATH=$NPREFIX/lib/pkgconfig/:$NPREFIX/share/pkgconfig/:$NPREFIX/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
|
|
||||||
meson setup --prefix="$PREFIX_WESTINY" --wrap-mode=nofallback ../westinyplus/
|
|
||||||
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
|
||||||
ninja install
|
|
||||||
ninja clean
|
|
||||||
cd -
|
|
||||||
fi
|
|
||||||
fdo_log_section_end build_weston
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# Constructs the base container image used to build Weston within CI. Per the
|
|
||||||
# comment at the top of .gitlab-ci.yml, any changes in this file must bump the
|
|
||||||
# $FDO_DISTRIBUTION_TAG variable so we know the container has to be rebuilt.
|
|
||||||
|
|
||||||
set -o xtrace -o errexit
|
|
||||||
|
|
||||||
# These get temporary installed for building Linux and then force-removed.
|
|
||||||
LINUX_DEV_PKGS="
|
|
||||||
bc
|
|
||||||
bison
|
|
||||||
flex
|
|
||||||
"
|
|
||||||
|
|
||||||
# These get temporary installed for building Mesa and then force-removed.
|
|
||||||
MESA_DEV_PKGS="
|
|
||||||
bison
|
|
||||||
flex
|
|
||||||
gettext
|
|
||||||
libwayland-egl-backend-dev
|
|
||||||
libxrandr-dev
|
|
||||||
libxshmfence-dev
|
|
||||||
libxrandr-dev
|
|
||||||
llvm-${LLVM_VERSION}-dev
|
|
||||||
python3-mako
|
|
||||||
"
|
|
||||||
|
|
||||||
# These get temporarily installed for other build dependencies and then
|
|
||||||
# force-removed.
|
|
||||||
# cmake is used by Vulkan-Headers
|
|
||||||
BUILD_DEV_PKGS="
|
|
||||||
cmake
|
|
||||||
"
|
|
||||||
|
|
||||||
# Needed for running the custom-built mesa
|
|
||||||
MESA_RUNTIME_PKGS="
|
|
||||||
libllvm${LLVM_VERSION}
|
|
||||||
"
|
|
||||||
|
|
||||||
if [ x"$USE_DEBIAN_BACKPORTS" = "xy" ] ; then
|
|
||||||
echo 'deb http://deb.debian.org/debian '${FDO_DISTRIBUTION_VERSION}'-backports main' >> /etc/apt/sources.list
|
|
||||||
fi
|
|
||||||
|
|
||||||
apt-get update
|
|
||||||
apt-get -y --no-install-recommends install \
|
|
||||||
autoconf \
|
|
||||||
automake \
|
|
||||||
build-essential \
|
|
||||||
clang-${LLVM_VERSION} \
|
|
||||||
curl \
|
|
||||||
doxygen \
|
|
||||||
graphviz \
|
|
||||||
gcovr \
|
|
||||||
git \
|
|
||||||
glslang-tools \
|
|
||||||
hwdata \
|
|
||||||
lcov \
|
|
||||||
libasound2-dev \
|
|
||||||
libbluetooth-dev \
|
|
||||||
libcairo2-dev \
|
|
||||||
libcolord-dev \
|
|
||||||
libdbus-1-dev \
|
|
||||||
libdrm-dev \
|
|
||||||
libegl1-mesa-dev \
|
|
||||||
libelf-dev \
|
|
||||||
libevdev-dev \
|
|
||||||
libexpat1-dev \
|
|
||||||
libffi-dev \
|
|
||||||
libgbm-dev \
|
|
||||||
libgdk-pixbuf-xlib-2.0-dev \
|
|
||||||
libgles2-mesa-dev \
|
|
||||||
libglu1-mesa-dev \
|
|
||||||
libgstreamer1.0-dev \
|
|
||||||
libgstreamer-plugins-base1.0-dev \
|
|
||||||
libinput-dev \
|
|
||||||
libjack-jackd2-dev \
|
|
||||||
libjpeg-dev \
|
|
||||||
libjpeg-dev \
|
|
||||||
liblua5.4-dev \
|
|
||||||
libmtdev-dev \
|
|
||||||
libpam0g-dev \
|
|
||||||
libpango1.0-dev \
|
|
||||||
libpciaccess-dev \
|
|
||||||
libpixman-1-dev \
|
|
||||||
libpng-dev \
|
|
||||||
libpulse-dev \
|
|
||||||
libsbc-dev \
|
|
||||||
libsystemd-dev \
|
|
||||||
libtool \
|
|
||||||
libudev-dev \
|
|
||||||
libva-dev \
|
|
||||||
libvpx-dev \
|
|
||||||
libvulkan-dev \
|
|
||||||
libwebp-dev \
|
|
||||||
libx11-dev \
|
|
||||||
libx11-xcb-dev \
|
|
||||||
libxcb1-dev \
|
|
||||||
libxcb-composite0-dev \
|
|
||||||
libxcb-dri2-0-dev \
|
|
||||||
libxcb-dri3-dev \
|
|
||||||
libxcb-glx0-dev \
|
|
||||||
libxcb-present-dev \
|
|
||||||
libxcb-randr0-dev \
|
|
||||||
libxcb-shm0-dev \
|
|
||||||
libxcb-sync-dev \
|
|
||||||
libxcb-xfixes0-dev \
|
|
||||||
libxcb-xkb-dev \
|
|
||||||
libxcursor-dev \
|
|
||||||
libxcb-cursor-dev \
|
|
||||||
libxdamage-dev \
|
|
||||||
libxext-dev \
|
|
||||||
libxfixes-dev \
|
|
||||||
libxkbcommon-dev \
|
|
||||||
libxml2-dev \
|
|
||||||
libxxf86vm-dev \
|
|
||||||
lld-${LLVM_VERSION} \
|
|
||||||
llvm-${LLVM_VERSION} \
|
|
||||||
llvm-${LLVM_VERSION}-dev \
|
|
||||||
mesa-common-dev \
|
|
||||||
ninja-build \
|
|
||||||
pkg-config \
|
|
||||||
python3-pip \
|
|
||||||
python3-pygments \
|
|
||||||
python3-setuptools \
|
|
||||||
qemu-system \
|
|
||||||
sysvinit-core \
|
|
||||||
x11proto-dev \
|
|
||||||
xwayland \
|
|
||||||
python3-argcomplete \
|
|
||||||
flake8 pylint \
|
|
||||||
cargo rustc \
|
|
||||||
iproute2 udev \
|
|
||||||
$MESA_DEV_PKGS \
|
|
||||||
$BUILD_DEV_PKGS \
|
|
||||||
$MESA_RUNTIME_PKGS \
|
|
||||||
$PACKAGES_SPECIFIC \
|
|
||||||
$LINUX_DEV_PKGS \
|
|
||||||
|
|
||||||
if [ "$FREERDP_VERSION" -ne 0 ] ; then
|
|
||||||
apt-get -y --no-install-recommends install freerdp${FREERDP_VERSION}-dev
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Actually build our dependencies ...
|
|
||||||
./.gitlab-ci/build-deps.sh
|
|
||||||
|
|
||||||
|
|
||||||
# And remove packages which are only required for our build dependencies,
|
|
||||||
# which we don't need bloating the image whilst we build and run Weston.
|
|
||||||
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS $BUILD_DEV_PKGS
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
# AddressSanitizer memory leak suppressions
|
|
||||||
|
|
||||||
# This leaks in Debian's fontconfig/Xwayland setup. We add the entire
|
|
||||||
# fontconfig library because turning off fast unwind -- required to catch other
|
|
||||||
# originating leaks from fontconfig; would stall our tests timing them out.
|
|
||||||
leak:libfontconfig
|
|
||||||
|
|
||||||
# Workarounds for the LeakSanitizer use_tls=0 workaround,
|
|
||||||
# see tests/meson.build
|
|
||||||
leak:wl_shm_buffer_begin_access
|
|
||||||
leak:g_malloc0
|
|
||||||
leak:sysprof_collector_get
|
|
||||||
leak:/ld-*.so*
|
|
||||||
|
|
||||||
# Add all of perfetto, since it's not easy to clean up after it
|
|
||||||
leak:perfetto
|
|
||||||
|
|
||||||
# lavapipe inexplicably leaks when Vulkan physical devices are enumerated,
|
|
||||||
# despite us a) not using that device and b) freeing the instance. This is
|
|
||||||
# apparently a known issue. (Also when ASan creates threads ...)
|
|
||||||
leak:vkEnumeratePhysicalDevices
|
|
||||||
leak:asan_thread_start
|
|
||||||
|
|
||||||
# glib/pangoft for Trixie update
|
|
||||||
leak:libpangoft2
|
|
||||||
leak:libglib
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
source "${FDO_CI_BASH_HELPERS}"
|
|
||||||
|
|
||||||
cd "$BUILDDIR"
|
|
||||||
test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
|
||||||
virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
|
||||||
TEST_RES=$(cat $TESTS_RES_PATH)
|
|
||||||
rm $TESTS_RES_PATH
|
|
||||||
cp -R /weston-virtme ./
|
|
||||||
rm weston-virtme/${KERNEL_IMAGE}
|
|
||||||
exit $TEST_RES
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# folders that are necessary to run Weston tests
|
|
||||||
mkdir -p /tmp/tests
|
|
||||||
mkdir -p /tmp/.X11-unix
|
|
||||||
chmod -R 0700 /tmp
|
|
||||||
|
|
||||||
# set environment variables to run Weston tests
|
|
||||||
export XDG_RUNTIME_DIR=/tmp/tests
|
|
||||||
export LIBSEAT_BACKEND=seatd
|
|
||||||
# In our test suite, we use VKMS to run DRM-backend tests. The order in which
|
|
||||||
# devices are loaded is not predictable, so the DRM node that VKMS takes can
|
|
||||||
# change across each boot. That's why we have this one-liner shell script to get
|
|
||||||
# the appropriate node for VKMS.
|
|
||||||
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/bus/faux/devices/vkms/drm/card*)
|
|
||||||
|
|
||||||
# ninja test depends on meson, and meson itself looks for its modules on folder
|
|
||||||
# $HOME/.local/lib/pythonX.Y/site-packages (the Python version may differ).
|
|
||||||
# build-deps.sh installs dependencies to /usr/local.
|
|
||||||
# virtme starts with HOME=/tmp/roothome, but as we installed meson on user root,
|
|
||||||
# meson can not find its modules. So we change the HOME env var to fix that.
|
|
||||||
export HOME=/root
|
|
||||||
export PATH=$HOME/.local/bin:$PATH
|
|
||||||
export PATH=/usr/local/bin:$PATH
|
|
||||||
|
|
||||||
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
|
|
||||||
# llvmpipe/lavapipe driver module location
|
|
||||||
export WESTON_CI_LEAK_DL_HANDLES=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true):
|
|
||||||
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libvulkan_lvp.so -print 2>/dev/null || true)
|
|
||||||
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libgallium\*.so -print 2>/dev/null || true)
|
|
||||||
|
|
||||||
# run the tests and save the exit status
|
|
||||||
# we give ourselves a very generous timeout multiplier due to ASan overhead
|
|
||||||
echo 0x1f > /sys/module/drm/parameters/debug
|
|
||||||
seatd-launch -- meson test --no-rebuild --timeout-multiplier 4
|
|
||||||
# note that we need to store the return value from the tests in order to
|
|
||||||
# determine if the test suite ran successfully or not.
|
|
||||||
TEST_RES=$?
|
|
||||||
dmesg &> dmesg.log
|
|
||||||
echo 0x00 > /sys/module/drm/parameters/debug
|
|
||||||
|
|
||||||
# create a file to keep the result of this script:
|
|
||||||
# - 0 means the script succeeded
|
|
||||||
# - 1 means the tests failed, so the job itself should fail
|
|
||||||
TESTS_RES_PATH=$(pwd)/tests-res.txt
|
|
||||||
echo $TEST_RES > $TESTS_RES_PATH
|
|
||||||
3
.mailmap
|
|
@ -1,3 +0,0 @@
|
||||||
Faith Ekstrand <faith@gfxstrand.net> <jason@jlekstrand.net>
|
|
||||||
Faith Ekstrand <faith@gfxstrand.net> <jason.ekstrand@intel.com>
|
|
||||||
Faith Ekstrand <faith@gfxstrand.net> <jason.ekstrand@collabora.com>
|
|
||||||
386
CONTRIBUTING.md
|
|
@ -1,386 +0,0 @@
|
||||||
Contributing to Weston
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Sending patches
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Patches should be sent via
|
|
||||||
[GitLab merge requests](https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.html).
|
|
||||||
Weston is
|
|
||||||
[hosted on freedesktop.org's GitLab](https://gitlab.freedesktop.org/wayland/weston/):
|
|
||||||
in order to submit code, you should create an account on this GitLab instance,
|
|
||||||
fork the core Weston repository, push your changes to a branch in your new
|
|
||||||
repository, and then submit these patches for review through a merge request.
|
|
||||||
|
|
||||||
### Forking & Permissions for new users
|
|
||||||
|
|
||||||
Due to huge amounts of spam, freedesktop.org has disabled forking of existing
|
|
||||||
projects for new users. Please head to
|
|
||||||
[How can I contribute](https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home#how-can-i-contribute-to-an-existing-project-or-create-a-new-one)
|
|
||||||
and verify whether you need to perform additional steps.
|
|
||||||
|
|
||||||
### Do not send patches over email
|
|
||||||
|
|
||||||
Weston formerly accepted patches via `git-send-email`, sent to
|
|
||||||
**wayland-devel\@lists.freedesktop.org**; these were
|
|
||||||
[tracked using Patchwork](https://patchwork.freedesktop.org/project/wayland/).
|
|
||||||
New email patches are no longer accepted.
|
|
||||||
|
|
||||||
Finding something to work on
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Weston's development is [tracked on GitLab](https://gitlab.freedesktop.org/wayland/weston).
|
|
||||||
In addition to reviewing code submissions (see below), we use the issue tracker
|
|
||||||
to discuss both bugfixes and development of new features.
|
|
||||||
|
|
||||||
The '[good for new contributors](https://gitlab.freedesktop.org/wayland/weston/issues?label_name%5B%5D=Good+for+new+contributors)'
|
|
||||||
label is used for issues the development team thinks are a good place to begin
|
|
||||||
working on Weston. These issues cover features or bugfixes which are small,
|
|
||||||
self-contained, don't require much specific background knowledge, and aren't
|
|
||||||
blocked by more complex work.
|
|
||||||
|
|
||||||
If you have picked an issue you would like to work on, you may want to mention
|
|
||||||
in the issue tracker that you would like to pick it up. You can also discuss
|
|
||||||
it with the developers in the issue tracker, or on the
|
|
||||||
[mailing list](https://lists.freedesktop.org/mailman/listinfo/wayland-devel).
|
|
||||||
Many developers also use IRC through [OFTC](https://www.oftc.net/)'s
|
|
||||||
`#wayland` channel; however you may need to wait some time for a response on
|
|
||||||
IRC, which requires keeping your client connected. If you cannot stay for a
|
|
||||||
long time (potentially some hours due to timezone differences), then you
|
|
||||||
may want to send your question to the list or issue tracker instead.
|
|
||||||
|
|
||||||
|
|
||||||
Formatting and separating commits
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
Unlike many projects using GitHub and GitLab, Weston has a
|
|
||||||
[linear, 'recipe' style history](http://www.bitsnbites.eu/git-history-work-log-vs-recipe/).
|
|
||||||
This means that every commit should be small, digestible, stand-alone, and
|
|
||||||
functional. Rather than a purely chronological commit history like this:
|
|
||||||
|
|
||||||
doc: final docs for view transforms
|
|
||||||
fix tests when disabled, redo broken doc formatting
|
|
||||||
better transformed-view iteration (thanks Hannah!)
|
|
||||||
try to catch more cases in tests
|
|
||||||
tests: add new spline test
|
|
||||||
fix compilation on splines
|
|
||||||
doc: notes on reticulating splines
|
|
||||||
compositor: add spline reticulation for view transforms
|
|
||||||
|
|
||||||
we aim to have a clean history which only reflects the final state, broken up
|
|
||||||
into functional groupings:
|
|
||||||
|
|
||||||
compositor: add spline reticulation for view transforms
|
|
||||||
compositor: new iterator for view transforms
|
|
||||||
tests: add view-transform correctness tests
|
|
||||||
doc: fix Doxygen formatting for view transforms
|
|
||||||
|
|
||||||
This ensures that the final patch series only contains the final state,
|
|
||||||
without the changes and missteps taken along the development process.
|
|
||||||
|
|
||||||
The first line of a commit message should contain a prefix indicating
|
|
||||||
what part is affected by the patch followed by one sentence that
|
|
||||||
describes the change. For examples:
|
|
||||||
|
|
||||||
compositor-drm: Support modifiers for drm_fb
|
|
||||||
|
|
||||||
and
|
|
||||||
|
|
||||||
input: do not forward unmatched touch-ups
|
|
||||||
|
|
||||||
If in doubt what prefix to use, look at other commits that change the
|
|
||||||
same file(s) as the patch being sent.
|
|
||||||
|
|
||||||
The body of the commit message should describe what the patch changes
|
|
||||||
and why, and also note any particular side effects. This shouldn't be
|
|
||||||
empty on most of the cases. It shouldn't take a lot of effort to write
|
|
||||||
a commit message for an obvious change, so an empty commit message
|
|
||||||
body is only acceptable if the questions "What?" and "Why?" are already
|
|
||||||
answered on the one-line summary.
|
|
||||||
|
|
||||||
The lines of the commit message should have at most 76 characters, to
|
|
||||||
cope with the way git log presents them.
|
|
||||||
|
|
||||||
See [notes on commit messages] for a recommended reading on writing commit
|
|
||||||
messages.
|
|
||||||
|
|
||||||
Your patches must also include a Signed-off-by line with your name
|
|
||||||
(or pseudonym) and email address which indicates that you agree to the
|
|
||||||
[Developer's Certificate of Origin 1.1](DCO-1.1.txt).
|
|
||||||
If you're not the patch's original author, you should
|
|
||||||
also gather S-o-b's from them (and/or whomever gave the patch to you) in
|
|
||||||
addition to your own S-o-b. The
|
|
||||||
significance of this is that it certifies that you created the patch,
|
|
||||||
that it was created under an appropriate open source license, or
|
|
||||||
provided to you under those terms. This lets us indicate a chain of
|
|
||||||
responsibility for the copyright status of the code.
|
|
||||||
|
|
||||||
**Agreeing to DCO 1.1 is mandatory.** Patches without a Signed-off-by cannot
|
|
||||||
be accepted, but using a pseudonym is fine as long as the email address is
|
|
||||||
yours personally.
|
|
||||||
|
|
||||||
When you re-send patches, revised or not, it would be very good to document the
|
|
||||||
changes compared to the previous revision in the commit message and/or the
|
|
||||||
merge request. If you have already received Reviewed-by or Acked-by tags, you
|
|
||||||
should evaluate whether they still apply and include them in the respective
|
|
||||||
commit messages. Otherwise the tags may be lost, reviewers miss the credit they
|
|
||||||
deserve, and the patches may cause redundant review effort.
|
|
||||||
|
|
||||||
|
|
||||||
Tracking patches and following up
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
Once submitted to GitLab, your patches will be reviewed by the Weston
|
|
||||||
development team on GitLab. Review may be entirely positive and result in your
|
|
||||||
code landing instantly, in which case, great! You're done. However, we may ask
|
|
||||||
you to make some revisions: fixing some bugs we've noticed, working to a
|
|
||||||
slightly different design, or adding documentation and tests.
|
|
||||||
|
|
||||||
If you do get asked to revise the patches, please bear in mind the notes above.
|
|
||||||
You should use `git rebase -i` to make revisions, so that your patches follow
|
|
||||||
the clear linear split documented above. Following that split makes it easier
|
|
||||||
for reviewers to understand your work, and to verify that the code you're
|
|
||||||
submitting is correct.
|
|
||||||
|
|
||||||
A common request is to split single large patch into multiple patches. This can
|
|
||||||
happen, for example, if when adding a new feature you notice a bug in Weston's
|
|
||||||
core which you need to fix to progress. Separating these changes into separate
|
|
||||||
commits will allow us to verify and land the bugfix quickly, pushing part of
|
|
||||||
your work for the good of everyone, whilst revision and discussion continues on
|
|
||||||
the larger feature part. It also allows us to direct you towards reviewers who
|
|
||||||
best understand the different areas you are working on.
|
|
||||||
|
|
||||||
When you have made any requested changes, please rebase the commits, verify
|
|
||||||
that they still individually look good, then force-push your new branch to
|
|
||||||
GitLab. This will update the merge request and notify everyone subscribed to
|
|
||||||
your merge request, so they can review it again.
|
|
||||||
|
|
||||||
There are also
|
|
||||||
[many GitLab CLI clients](https://about.gitlab.com/applications/#cli-clients),
|
|
||||||
if you prefer to avoid the web interface. It may be difficult to follow review
|
|
||||||
comments without using the web interface though, so we do recommend using this
|
|
||||||
to go through the review process, even if you use other clients to track the
|
|
||||||
list of available patches.
|
|
||||||
|
|
||||||
|
|
||||||
Coding style
|
|
||||||
------------
|
|
||||||
|
|
||||||
You should follow the style of the file you're editing. In general, we
|
|
||||||
try to follow the rules below.
|
|
||||||
|
|
||||||
**Note: this file uses spaces due to markdown rendering issues for tabs.
|
|
||||||
Code must be indented using tabs.**
|
|
||||||
|
|
||||||
- indent with tabs, and a tab is always 8 characters wide
|
|
||||||
- opening braces are on the same line as the if statement;
|
|
||||||
- no braces in an if-body with just one statement;
|
|
||||||
- if one of the branches of an if-else condition has braces, then the
|
|
||||||
other branch should also have braces;
|
|
||||||
- there is always an empty line between variable declarations and the
|
|
||||||
code;
|
|
||||||
|
|
||||||
```c
|
|
||||||
static int
|
|
||||||
my_function(void)
|
|
||||||
{
|
|
||||||
int a = 0;
|
|
||||||
|
|
||||||
if (a)
|
|
||||||
b();
|
|
||||||
else
|
|
||||||
c();
|
|
||||||
|
|
||||||
if (a) {
|
|
||||||
b();
|
|
||||||
c();
|
|
||||||
} else {
|
|
||||||
d();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- lines should be less than 80 characters wide;
|
|
||||||
- when breaking lines with functions calls, the parameters are aligned
|
|
||||||
with the opening parentheses;
|
|
||||||
- when assigning a variable with the result of a function call, if the
|
|
||||||
line would be longer we break it around the equal '=' sign if it makes
|
|
||||||
sense;
|
|
||||||
|
|
||||||
```c
|
|
||||||
long_variable_name =
|
|
||||||
function_with_a_really_long_name(parameter1, parameter2,
|
|
||||||
parameter3, parameter4);
|
|
||||||
|
|
||||||
x = function_with_a_really_long_name(parameter1, parameter2,
|
|
||||||
parameter3, parameter4);
|
|
||||||
```
|
|
||||||
|
|
||||||
- do not write fallback paths for failed simple memory allocations, use the
|
|
||||||
`x*alloc()` wrappers from `shared/xalloc.h` instead or use
|
|
||||||
`abort_oom_if_null()`
|
|
||||||
|
|
||||||
Conduct
|
|
||||||
=======
|
|
||||||
|
|
||||||
As a freedesktop.org project, Wayland follows the Contributor Covenant,
|
|
||||||
found at:
|
|
||||||
https://www.freedesktop.org/wiki/CodeOfConduct
|
|
||||||
|
|
||||||
Please conduct yourself in a respectful and civilised manner when
|
|
||||||
interacting with community members on mailing lists, IRC, or bug
|
|
||||||
trackers. The community represents the project as a whole, and abusive
|
|
||||||
or bullying behaviour is not tolerated by the project.
|
|
||||||
|
|
||||||
|
|
||||||
Licensing
|
|
||||||
=========
|
|
||||||
|
|
||||||
Weston is licensed with the intention to be usable anywhere X.org is.
|
|
||||||
Originally, X.org was covered under the MIT X11 license, but changed to
|
|
||||||
the MIT Expat license. Similarly, Weston was covered initially as MIT
|
|
||||||
X11 licensed, but changed to the MIT Expat license, following in X.org's
|
|
||||||
footsteps. Other than wording, the two licenses are substantially the
|
|
||||||
same, with the exception of a no-advertising clause in X11 not included
|
|
||||||
in Expat.
|
|
||||||
|
|
||||||
New source code files should specify the MIT Expat license in their
|
|
||||||
boilerplate, as part of the copyright statement.
|
|
||||||
|
|
||||||
|
|
||||||
Review
|
|
||||||
======
|
|
||||||
|
|
||||||
All patches, even trivial ones, require at least one positive review
|
|
||||||
(Reviewed-by). Additionally, if no Reviewed-by's have been given by
|
|
||||||
people with commit access, there needs to be at least one Acked-by from
|
|
||||||
someone with commit access. A person with commit access is expected to be
|
|
||||||
able to evaluate the patch with respect to the project scope and architecture.
|
|
||||||
|
|
||||||
The below review guidelines are intended to be interpreted in spirit, not by
|
|
||||||
the letter. There may be circumstances where some guidelines are better
|
|
||||||
ignored. We rely very much on the judgement of reviewers and commit rights
|
|
||||||
holders.
|
|
||||||
|
|
||||||
During review, the following matters should be checked:
|
|
||||||
|
|
||||||
- The commit message explains why the change is being made.
|
|
||||||
|
|
||||||
- The code fits the project's scope.
|
|
||||||
|
|
||||||
- The code license is the same MIT licence the project generally uses.
|
|
||||||
|
|
||||||
- Stable ABI or API is not broken.
|
|
||||||
|
|
||||||
- Stable ABI or API additions must be justified by actual use cases, not only
|
|
||||||
by speculation. They must also be documented, and it is strongly recommended to
|
|
||||||
include tests exercising the additions in the test suite.
|
|
||||||
|
|
||||||
- The code fits the existing software architecture, e.g. no layering
|
|
||||||
violations.
|
|
||||||
|
|
||||||
- The code is correct and does not introduce new failures for existing users,
|
|
||||||
does not add new corner-case bugs, and does not introduce new compiler
|
|
||||||
warnings.
|
|
||||||
|
|
||||||
- The patch does what it says in the commit message and changes nothing else.
|
|
||||||
|
|
||||||
- The patch is a single logical change. If the commit message addresses
|
|
||||||
multiple points, it is a hint that the commit might need splitting up.
|
|
||||||
|
|
||||||
- A bug fix should target the underlying root cause instead of hiding symptoms.
|
|
||||||
If a complete fix is not practical, partial fixes are acceptable if they come
|
|
||||||
with code comments and filed Gitlab issues for the remaining bugs.
|
|
||||||
|
|
||||||
- The bug root cause rule applies to external software components as well, e.g.
|
|
||||||
do not work around kernel driver issues in userspace.
|
|
||||||
|
|
||||||
- The test suite passes.
|
|
||||||
|
|
||||||
- The code does not depend on API or ABI which has no working free open source
|
|
||||||
implementation.
|
|
||||||
|
|
||||||
- The code is not dead or untestable. E.g. if there are no free open source
|
|
||||||
software users for it then it is effectively dead code.
|
|
||||||
|
|
||||||
- The code is written to be easy to understand, or if code cannot be clear
|
|
||||||
enough on its own there are code comments to explain it.
|
|
||||||
|
|
||||||
- The code is minimal, i.e. prefer refactor and re-use when possible unless
|
|
||||||
clarity suffers.
|
|
||||||
|
|
||||||
- The code adheres to the style guidelines.
|
|
||||||
|
|
||||||
- In a patch series, every intermediate step adheres to the above guidelines.
|
|
||||||
|
|
||||||
|
|
||||||
Commit rights
|
|
||||||
=============
|
|
||||||
|
|
||||||
Commit rights will be granted to anyone who requests them and fulfills the
|
|
||||||
below criteria:
|
|
||||||
|
|
||||||
- Submitted some (10 as a rule of thumb) non-trivial (not just simple
|
|
||||||
spelling fixes and whitespace adjustment) patches that have been merged
|
|
||||||
already.
|
|
||||||
|
|
||||||
- Are actively participating in public discussions about their work (on the
|
|
||||||
mailing list or IRC). This should not be interpreted as a requirement to
|
|
||||||
review other peoples patches but just make sure that patch submission isn't
|
|
||||||
one-way communication. Cross-review is still highly encouraged.
|
|
||||||
|
|
||||||
- Will be regularly contributing further patches. This includes regular
|
|
||||||
contributors to other parts of the open source graphics stack who only
|
|
||||||
do the occasional development in this project.
|
|
||||||
|
|
||||||
- Agrees to use their commit rights in accordance with the documented merge
|
|
||||||
criteria, tools, and processes.
|
|
||||||
|
|
||||||
To apply for commit rights, create a new issue in gitlab for the respective
|
|
||||||
project and give it the "accounts" label.
|
|
||||||
|
|
||||||
Committers are encouraged to request their commit rights get removed when they
|
|
||||||
no longer contribute to the project. Commit rights will be reinstated when they
|
|
||||||
come back to the project.
|
|
||||||
|
|
||||||
Maintainers and committers should encourage contributors to request commit
|
|
||||||
rights, especially junior contributors tend to underestimate their skills.
|
|
||||||
|
|
||||||
|
|
||||||
Stabilising for releases
|
|
||||||
========================
|
|
||||||
|
|
||||||
A release cycle ends with a stable release which also starts a new cycle and
|
|
||||||
lifts any code freezes. Gradual code freezing towards a stable release starts
|
|
||||||
with an alpha release. The release stages of a cycle are:
|
|
||||||
|
|
||||||
- **Alpha release**:
|
|
||||||
Signified by version number #.#.91.
|
|
||||||
Major features must have landed before this. Major features include
|
|
||||||
invasive code motion and refactoring, high risk changes, and new stable
|
|
||||||
library ABI.
|
|
||||||
|
|
||||||
- **Beta release**:
|
|
||||||
Signified by version number #.#.92.
|
|
||||||
Minor features must have landed before this. Minor features include all
|
|
||||||
new features that are not major, low risk changes, clean-ups, and
|
|
||||||
documentation. Stable ABI that was new in the alpha release can be removed
|
|
||||||
before a beta release if necessary.
|
|
||||||
|
|
||||||
- **Release candidates (RC)**:
|
|
||||||
Signified by version number #.#.93 and up to #.#.99.
|
|
||||||
Bug fixes that are not release critical must have landed before this.
|
|
||||||
Release critical bug fixes can still be landed after this, but they may
|
|
||||||
call for another RC.
|
|
||||||
|
|
||||||
- **Stable release**:
|
|
||||||
Signified by version number #.#.0.
|
|
||||||
Ideally no changes since the last RC.
|
|
||||||
|
|
||||||
Mind that version #.#.90 is never released. It is used during development when
|
|
||||||
no code freeze is in effect. Stable branches and point releases are not covered
|
|
||||||
by the above.
|
|
||||||
|
|
||||||
|
|
||||||
[git documentation]: http://git-scm.com/documentation
|
|
||||||
[notes on commit messages]: http://who-t.blogspot.de/2009/12/on-commit-messages.html
|
|
||||||
44
COPYING
|
|
@ -2,8 +2,31 @@ Copyright © 2008-2012 Kristian Høgsberg
|
||||||
Copyright © 2010-2012 Intel Corporation
|
Copyright © 2010-2012 Intel Corporation
|
||||||
Copyright © 2010-2011 Benjamin Franzke
|
Copyright © 2010-2011 Benjamin Franzke
|
||||||
Copyright © 2011-2012 Collabora, Ltd.
|
Copyright © 2011-2012 Collabora, Ltd.
|
||||||
Copyright © 2010 Red Hat <mjg@redhat.com>
|
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that copyright
|
||||||
|
notice and this permission notice appear in supporting documentation, and
|
||||||
|
that the name of the copyright holders not be used in advertising or
|
||||||
|
publicity pertaining to distribution of the software without specific,
|
||||||
|
written prior permission. The copyright holders make no representations
|
||||||
|
about the suitability of this software for any purpose. It is provided "as
|
||||||
|
is" without express or implied warranty.
|
||||||
|
|
||||||
|
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
For libbacklight.c:
|
||||||
|
|
||||||
|
Copyright © 2012 Intel Corporation
|
||||||
|
Copyright © 2010 Red Hat <mjg@redhat.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
to deal in the Software without restriction, including without limitation
|
to deal in the Software without restriction, including without limitation
|
||||||
|
|
@ -15,16 +38,11 @@ The above copyright notice and this permission notice (including the next
|
||||||
paragraph) shall be included in all copies or substantial portions of the
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
Software.
|
Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The above is the version of the MIT "Expat" License used by X.org:
|
|
||||||
|
|
||||||
http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
|
|
||||||
|
|
|
||||||
37
DCO-1.1.txt
|
|
@ -1,37 +0,0 @@
|
||||||
Developer Certificate of Origin
|
|
||||||
Version 1.1
|
|
||||||
|
|
||||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
|
||||||
1 Letterman Drive
|
|
||||||
Suite D4700
|
|
||||||
San Francisco, CA, 94129
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies of this
|
|
||||||
license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
Developer's Certificate of Origin 1.1
|
|
||||||
|
|
||||||
By making a contribution to this project, I certify that:
|
|
||||||
|
|
||||||
(a) The contribution was created in whole or in part by me and I
|
|
||||||
have the right to submit it under the open source license
|
|
||||||
indicated in the file; or
|
|
||||||
|
|
||||||
(b) The contribution is based upon previous work that, to the best
|
|
||||||
of my knowledge, is covered under an appropriate open source
|
|
||||||
license and I have the right under that license to submit that
|
|
||||||
work with modifications, whether created in whole or in part
|
|
||||||
by me, under the same open source license (unless I am
|
|
||||||
permitted to submit under a different license), as indicated
|
|
||||||
in the file; or
|
|
||||||
|
|
||||||
(c) The contribution was provided directly to me by some other
|
|
||||||
person who certified (a), (b) or (c) and I have not modified
|
|
||||||
it.
|
|
||||||
|
|
||||||
(d) I understand and agree that this project and the contribution
|
|
||||||
are public and that a record of the contribution (including all
|
|
||||||
personal information I submit with it, including my sign-off) is
|
|
||||||
maintained indefinitely and may be redistributed consistent with
|
|
||||||
this project or the open source license(s) involved.
|
|
||||||
1231
Makefile.am
Normal file
18
README
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
Weston
|
||||||
|
|
||||||
|
Weston is the reference implementation of a Wayland compositor, and a
|
||||||
|
useful compositor in its own right. Weston has various backends that
|
||||||
|
lets it run on Linux kernel modesetting and evdev input as well as
|
||||||
|
under X11. Weston ships with a few example clients, from simple
|
||||||
|
clients that demonstrate certain aspects of the protocol to more
|
||||||
|
complete clients and a simplistic toolkit. There is also a quite
|
||||||
|
capable terminal emulator (weston-terminal) and an toy/example desktop
|
||||||
|
shell. Finally, weston also provides integration with the Xorg server
|
||||||
|
and can pull X clients into the Wayland desktop and act as a X window
|
||||||
|
manager.
|
||||||
|
|
||||||
|
Refer to http://wayland.freedesktop.org/building.html for building
|
||||||
|
weston and its dependencies.
|
||||||
|
|
||||||
|
The test suite can be invoked via `make check`; see
|
||||||
|
http://wayland.freedesktop.org/testing.html for additional details.
|
||||||
159
README.md
|
|
@ -1,159 +0,0 @@
|
||||||
Weston
|
|
||||||
======
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Weston is a Wayland compositor designed for correctness, reliability,
|
|
||||||
predictability, and performance.
|
|
||||||
|
|
||||||
Out of the box, Weston provides a very basic desktop, or a full-featured
|
|
||||||
environment for non-desktop uses such as automotive, embedded, in-flight,
|
|
||||||
industrial, kiosks, set-top boxes and TVs.
|
|
||||||
|
|
||||||
It also provides a library called [libweston](#libweston) which allows
|
|
||||||
users to build their own custom full-featured environments on top of
|
|
||||||
Weston's core.
|
|
||||||
|
|
||||||
|
|
||||||
Building Weston
|
|
||||||
===============
|
|
||||||
|
|
||||||
Weston is built using [Meson](https://mesonbuild.com/). Weston often depends
|
|
||||||
on the current release versions of
|
|
||||||
[Wayland](https://gitlab.freedesktop.org/wayland/wayland) and
|
|
||||||
[wayland-protocols](https://gitlab.freedesktop.org/wayland/wayland-protocols).
|
|
||||||
|
|
||||||
If necessary, the latest Meson can be installed as a user with:
|
|
||||||
|
|
||||||
$ pip3 install --user meson
|
|
||||||
|
|
||||||
Weston's Meson build does not do autodetection and it defaults to all
|
|
||||||
features enabled, which means you likely hit missing dependencies on the first
|
|
||||||
try. If a dependency is avoidable through a build option, the error message
|
|
||||||
should tell you what option can be used to avoid it. You may need to disable
|
|
||||||
several features if you want to avoid certain dependencies.
|
|
||||||
|
|
||||||
$ git clone https://gitlab.freedesktop.org/wayland/weston.git
|
|
||||||
$ cd weston
|
|
||||||
$ meson build/ --prefix=...
|
|
||||||
$ ninja -C build/ install
|
|
||||||
$ cd ..
|
|
||||||
|
|
||||||
The `meson` command populates the build directory. This step can
|
|
||||||
fail due to missing dependencies. Any build options you want can be added on
|
|
||||||
that line, e.g. `meson build/ --prefix=... -Ddemo-clients=false`. All the build
|
|
||||||
options can be found in the file [meson_options.txt](meson_options.txt).
|
|
||||||
|
|
||||||
Once the build directory has been successfully populated, you can inspect the
|
|
||||||
configuration with `meson configure build/`. If you need to change an
|
|
||||||
option, you can do e.g. `meson configure build/ -Ddemo-clients=false`.
|
|
||||||
|
|
||||||
Every push to the Weston master repository and its forks is built using GitLab
|
|
||||||
CI. [Reading the configuration](.gitlab-ci.yml) may provide a useful example of
|
|
||||||
how to build and install Weston.
|
|
||||||
|
|
||||||
More [detailed documentation on building Weston](https://wayland.freedesktop.org/building.html)
|
|
||||||
is available on the Wayland site. There are also more details on
|
|
||||||
[how to run and write tests](https://wayland.freedesktop.org/testing.html).
|
|
||||||
|
|
||||||
For building the documentation see [documentation](#documentation).
|
|
||||||
|
|
||||||
|
|
||||||
Running Weston
|
|
||||||
==============
|
|
||||||
|
|
||||||
Once Weston is installed, most users can simply run it by typing `weston`. This
|
|
||||||
will launch Weston inside whatever environment you launch it from: when launched
|
|
||||||
from a text console, it will take over that console. When launched from inside
|
|
||||||
an existing Wayland or X11 session, it will start a 'nested' instance of Weston
|
|
||||||
inside a window in that session.
|
|
||||||
|
|
||||||
By default, Weston will start with a skeletal desktop-like environment called
|
|
||||||
`desktop-shell`. Other shells are available; for example, to load the `kiosk`
|
|
||||||
shell designed for single-application environments, you can start with:
|
|
||||||
|
|
||||||
$ weston --shell=kiosk
|
|
||||||
|
|
||||||
Help is available by running `weston --help`, or `man weston`, which will list
|
|
||||||
the available configuration options and display backends. It can also be
|
|
||||||
configured through a file on disk; more information on this can be found through
|
|
||||||
`man weston.ini`.
|
|
||||||
|
|
||||||
A small suite of example or demo clients are also provided: though they can be
|
|
||||||
useful in themselves, their main purpose is to be an example or test case for
|
|
||||||
others building compositors or clients.
|
|
||||||
|
|
||||||
|
|
||||||
Using libweston
|
|
||||||
===============
|
|
||||||
|
|
||||||
libweston is designed to allow users to use Weston's core - its client support,
|
|
||||||
backends and renderers - whilst implementing their own user interface, policy,
|
|
||||||
configuration, and lifecycle. If you would like to implement your own window
|
|
||||||
manager or desktop environment, we recommend building your project using the
|
|
||||||
libweston API.
|
|
||||||
|
|
||||||
Building and installing Weston will also install libweston's shared library
|
|
||||||
and development headers. libweston is both API-compatible and ABI-compatible
|
|
||||||
within a single stable release. It is parallel-installable, so multiple stable
|
|
||||||
releases can be installed and used side by side.
|
|
||||||
|
|
||||||
Documentation for libweston's API can be found within the source (see the
|
|
||||||
[documentation](#documentation) section), and also on
|
|
||||||
[Weston's online documentation](https://wayland.pages.freedesktop.org/weston/)
|
|
||||||
for the current stable release.
|
|
||||||
|
|
||||||
|
|
||||||
Reporting issues and contributing
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Weston's development is
|
|
||||||
[hosted on freedesktop.org GitLab](https://gitlab.freedesktop.org/wayland/weston/).
|
|
||||||
Please also see [the contributing document](CONTRIBUTING.md), which details how
|
|
||||||
to make code or non-technical contributions to Weston.
|
|
||||||
|
|
||||||
Weston and libweston are not suitable for severely memory-constrained environments
|
|
||||||
where the compositor is expected to continue running even in the face of
|
|
||||||
trivial memory allocations failing. If standard functions like `malloc()`
|
|
||||||
fail for small allocations,
|
|
||||||
[you can expect libweston to abort](https://gitlab.freedesktop.org/wayland/weston/-/issues/631).
|
|
||||||
This is only likely to occur if you have disabled your OS's 'overcommit'
|
|
||||||
functionality, and not in common cases.
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
=============
|
|
||||||
|
|
||||||
To read the Weston documentation online, head over to
|
|
||||||
[the Weston website](https://wayland.pages.freedesktop.org/weston/).
|
|
||||||
|
|
||||||
For documenting weston we use [sphinx](http://www.sphinx-doc.org/en/master/)
|
|
||||||
together with [breathe](https://breathe.readthedocs.io/en/latest/) to process
|
|
||||||
and augment code documentation from Doxygen. You should be able to install
|
|
||||||
both sphinx and the breathe extension using pip3 command, or your package
|
|
||||||
manager. Doxygen should be available using your distribution package manager.
|
|
||||||
|
|
||||||
Once those are set up, run `meson` with `-Ddoc=true` option in order to enable
|
|
||||||
building the documentation. Installation will place the documentation in the
|
|
||||||
prefix's path under datadir (i.e., `share/doc`).
|
|
||||||
|
|
||||||
Adding and improving documentation
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
For re-generating the documentation a special `docs` target has been added.
|
|
||||||
Although first time you build (and subsequently install) weston, you'll see the
|
|
||||||
documentation being built, updates to the spinx documentation files or to the
|
|
||||||
source files will only be updated when using `docs` target!
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
$ ninja install # generates and installs the documentation
|
|
||||||
# time passes, hack hack, add doc in sources or rST files
|
|
||||||
$ ninja install # not sufficient, docs will not be updated
|
|
||||||
$ ninja docs && ninja install # run 'docs' then install
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
Improving/adding documentation can be done by modifying rST files under
|
|
||||||
`doc/sphinx/` directory or by modifying the source code using doxygen
|
|
||||||
directives.
|
|
||||||
76
RELEASING.md
|
|
@ -1,76 +0,0 @@
|
||||||
# Releasing
|
|
||||||
|
|
||||||
To make a release of Weston, follow these steps.
|
|
||||||
|
|
||||||
0. Verify the test suites and codebase checks pass. All of the tests should
|
|
||||||
either pass or skip.
|
|
||||||
|
|
||||||
ninja -C build/ test
|
|
||||||
|
|
||||||
1. Verify that the wayland and wayland-protocols version dependencies are
|
|
||||||
correct, and that wayland-protocols has had a release with any needed
|
|
||||||
protocol updates.
|
|
||||||
|
|
||||||
2. Update the first stanza of `meson.build` to the intended version.
|
|
||||||
|
|
||||||
If the ABI has been broken, make sure `libweston_major` has been bumped since
|
|
||||||
the last release.
|
|
||||||
|
|
||||||
Then commit your changes:
|
|
||||||
|
|
||||||
RELEASE_NUMBER="x.y.z"
|
|
||||||
RELEASE_NAME="[alpha|beta|RC1|RC2|official|point]"
|
|
||||||
git status
|
|
||||||
git commit meson.build -m "build: bump to version $RELEASE_NUMBER for the $RELEASE_NAME release"
|
|
||||||
git push
|
|
||||||
|
|
||||||
3. Ensure that you have glab client installed locally and are authenticated to
|
|
||||||
freedesktop.org Gitlab instance. You can do that using the following:
|
|
||||||
|
|
||||||
glab auth login
|
|
||||||
|
|
||||||
Use gitlab web interface to generate a token either on Weston project or
|
|
||||||
on your profile (preferably) and use the token to authenticate. gitlab cli
|
|
||||||
client can be downloaded directly from Gitlab.com or it might be provided
|
|
||||||
directly by the distribution you're currently using to do the release.
|
|
||||||
|
|
||||||
4. Run the `release.sh` script to generate the tarballs, sign and upload them,
|
|
||||||
and generate a release announcement template. This script can be obtained
|
|
||||||
from the Wayland repository:
|
|
||||||
|
|
||||||
https://gitlab.freedesktop.org/wayland/wayland/-/blob/main/release.sh
|
|
||||||
|
|
||||||
5. Compose the release announcements. The script will generate a
|
|
||||||
weston-x.y.z.announce file with a list of changes and tags. Prepend these
|
|
||||||
with a human-readable listing of the most notable changes. For x.y.0
|
|
||||||
releases, indicate the schedule for the x.y+1.0 release.
|
|
||||||
|
|
||||||
6. PGP sign the release announcement and send it to
|
|
||||||
<wayland-devel@lists.freedesktop.org>.
|
|
||||||
|
|
||||||
7. Update `releases.html` in wayland.freedesktop.org with links to tarballs and
|
|
||||||
the release email URL.
|
|
||||||
|
|
||||||
Once satisfied:
|
|
||||||
|
|
||||||
git add releases.html releases/weston-${RELEASE_NUMBER}.tar.xz*
|
|
||||||
git commit -m "releases: add weston ${RELEASE_NUMBER} release"
|
|
||||||
git push
|
|
||||||
|
|
||||||
For x.y.0 releases, also create the release series x.y branch. The x.y branch
|
|
||||||
is for bug fixes and conservative changes to the x.y.0 release, and is where we
|
|
||||||
create x.y.z releases from. Creating the x.y branch opens up master for new
|
|
||||||
development and lets new development move on. We've done this both after the
|
|
||||||
x.y.0 release (to focus development on bug fixing for the x.y.1 release for a
|
|
||||||
little longer) or before the x.y.0 release (like we did with the 1.5.0 release,
|
|
||||||
to unblock master development early).
|
|
||||||
|
|
||||||
git branch x.y [sha]
|
|
||||||
git push origin x.y
|
|
||||||
|
|
||||||
The master branch's `meson.build` version should always be (at least) x.y.90,
|
|
||||||
with x.y being the most recent stable branch. The stable branch's `meson.build`
|
|
||||||
version is just whatever was most recently released from that branch.
|
|
||||||
|
|
||||||
For stable branches, we commit fixes to master first, then `git cherry-pick -x`
|
|
||||||
them back to the stable branch.
|
|
||||||
9
autogen.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
test -n "$srcdir" || srcdir=`dirname "$0"`
|
||||||
|
test -n "$srcdir" || srcdir=.
|
||||||
|
(
|
||||||
|
cd "$srcdir" &&
|
||||||
|
autoreconf --force -v --install
|
||||||
|
) || exit
|
||||||
|
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
|
||||||
|
|
@ -1,45 +1,42 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2012 Intel Corporation
|
* Copyright © 2012 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <getopt.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "shared/helpers.h"
|
#include "../shared/matrix.h"
|
||||||
#include <libweston/matrix.h>
|
|
||||||
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
|
||||||
/* Our points for the calibration must be not be on a line */
|
/* Our points for the calibration must be not be on a line */
|
||||||
static const struct {
|
static const struct {
|
||||||
|
|
@ -117,11 +114,11 @@ finish_calibration (struct calibrator *calibrator)
|
||||||
*/
|
*/
|
||||||
memset(&m, 0, sizeof(m));
|
memset(&m, 0, sizeof(m));
|
||||||
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
||||||
m.M.col[0].el[i] = calibrator->tests[i].clicked_x;
|
m.d[i] = calibrator->tests[i].clicked_x;
|
||||||
m.M.col[1].el[i] = calibrator->tests[i].clicked_y;
|
m.d[i + 4] = calibrator->tests[i].clicked_y;
|
||||||
m.M.col[2].el[i] = 1;
|
m.d[i + 8] = 1;
|
||||||
}
|
}
|
||||||
m.M.col[3].el[3] = 1;
|
m.d[15] = 1;
|
||||||
|
|
||||||
weston_matrix_invert(&inverse, &m);
|
weston_matrix_invert(&inverse, &m);
|
||||||
|
|
||||||
|
|
@ -129,8 +126,8 @@ finish_calibration (struct calibrator *calibrator)
|
||||||
memset(&y_calib, 0, sizeof(y_calib));
|
memset(&y_calib, 0, sizeof(y_calib));
|
||||||
|
|
||||||
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
||||||
x_calib.v.el[i] = calibrator->tests[i].drawn_x;
|
x_calib.f[i] = calibrator->tests[i].drawn_x;
|
||||||
y_calib.v.el[i] = calibrator->tests[i].drawn_y;
|
y_calib.f[i] = calibrator->tests[i].drawn_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Multiples into the vector */
|
/* Multiples into the vector */
|
||||||
|
|
@ -138,8 +135,8 @@ finish_calibration (struct calibrator *calibrator)
|
||||||
weston_matrix_transform(&inverse, &y_calib);
|
weston_matrix_transform(&inverse, &y_calib);
|
||||||
|
|
||||||
printf ("Calibration values: %f %f %f %f %f %f\n",
|
printf ("Calibration values: %f %f %f %f %f %f\n",
|
||||||
x_calib.v.el[0], x_calib.v.el[1], x_calib.v.el[2],
|
x_calib.f[0], x_calib.f[1], x_calib.f[2],
|
||||||
y_calib.v.el[0], y_calib.v.el[1], y_calib.v.el[2]);
|
y_calib.f[0], y_calib.f[1], y_calib.f[2]);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +218,7 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct calibrator *
|
static struct calibrator *
|
||||||
calibrator_create(struct display *display, bool enable_button)
|
calibrator_create(struct display *display)
|
||||||
{
|
{
|
||||||
struct calibrator *calibrator;
|
struct calibrator *calibrator;
|
||||||
|
|
||||||
|
|
@ -232,14 +229,11 @@ calibrator_create(struct display *display, bool enable_button)
|
||||||
calibrator->window = window_create(display);
|
calibrator->window = window_create(display);
|
||||||
calibrator->widget = window_add_widget(calibrator->window, calibrator);
|
calibrator->widget = window_add_widget(calibrator->window, calibrator);
|
||||||
window_set_title(calibrator->window, "Wayland calibrator");
|
window_set_title(calibrator->window, "Wayland calibrator");
|
||||||
window_set_appid(calibrator->window,
|
|
||||||
"org.freedesktop.weston.wayland-calibrator");
|
|
||||||
calibrator->display = display;
|
calibrator->display = display;
|
||||||
|
|
||||||
calibrator->current_test = ARRAY_LENGTH(test_ratios) - 1;
|
calibrator->current_test = ARRAY_LENGTH(test_ratios) - 1;
|
||||||
|
|
||||||
if (enable_button)
|
widget_set_button_handler(calibrator->widget, button_handler);
|
||||||
widget_set_button_handler(calibrator->widget, button_handler);
|
|
||||||
widget_set_touch_down_handler(calibrator->widget, touch_handler);
|
widget_set_touch_down_handler(calibrator->widget, touch_handler);
|
||||||
widget_set_redraw_handler(calibrator->widget, redraw_handler);
|
widget_set_redraw_handler(calibrator->widget, redraw_handler);
|
||||||
|
|
||||||
|
|
@ -256,49 +250,21 @@ calibrator_destroy(struct calibrator *calibrator)
|
||||||
free(calibrator);
|
free(calibrator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
help(const char *name)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: %s [args...]\n", name);
|
|
||||||
fprintf(stderr, " -m, --enable-mouse Enable mouse for testing the touchscreen\n");
|
|
||||||
fprintf(stderr, " -h, --help Display this help message\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct calibrator *calibrator;
|
struct calibrator *calibrator;
|
||||||
int c;
|
|
||||||
bool enable_mouse = 0;
|
|
||||||
struct option opts[] = {
|
|
||||||
{ "enable-mouse", no_argument, NULL, 'm' },
|
|
||||||
{ "help", no_argument, NULL, 'h' },
|
|
||||||
{ 0, 0, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "mh", opts, NULL)) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 'm':
|
|
||||||
enable_mouse = 1;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
help(argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display = display_create(&argc, argv);
|
display = display_create(&argc, argv);
|
||||||
|
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
calibrator = calibrator_create(display, enable_mouse);
|
calibrator = calibrator_create(display);
|
||||||
|
|
||||||
if (!calibrator)
|
if (!calibrator)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,23 @@
|
||||||
* Copyright © 2012 Collabora, Ltd.
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
* Copyright © 2012 Jonas Ådahl
|
* Copyright © 2012 Jonas Ådahl
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -32,16 +31,14 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
|
|
||||||
struct clickdot {
|
struct clickdot {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
|
|
@ -62,7 +59,8 @@ struct clickdot {
|
||||||
int reset;
|
int reset;
|
||||||
|
|
||||||
struct input *cursor_timeout_input;
|
struct input *cursor_timeout_input;
|
||||||
struct toytimer cursor_timeout;
|
int cursor_timeout_fd;
|
||||||
|
struct task cursor_timeout_task;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -223,7 +221,14 @@ button_handler(struct widget *widget,
|
||||||
static void
|
static void
|
||||||
cursor_timeout_reset(struct clickdot *clickdot)
|
cursor_timeout_reset(struct clickdot *clickdot)
|
||||||
{
|
{
|
||||||
toytimer_arm_once_usec(&clickdot->cursor_timeout, 500 * 1000);
|
const long cursor_timeout = 500;
|
||||||
|
struct itimerspec its;
|
||||||
|
|
||||||
|
its.it_interval.tv_sec = 0;
|
||||||
|
its.it_interval.tv_nsec = 0;
|
||||||
|
its.it_value.tv_sec = cursor_timeout / 1000;
|
||||||
|
its.it_value.tv_nsec = (cursor_timeout % 1000) * 1000 * 1000;
|
||||||
|
timerfd_settime(clickdot->cursor_timeout_fd, 0, &its, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -263,10 +268,15 @@ leave_handler(struct widget *widget,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cursor_timeout_func(struct toytimer *tt)
|
cursor_timeout_func(struct task *task, uint32_t events)
|
||||||
{
|
{
|
||||||
struct clickdot *clickdot =
|
struct clickdot *clickdot =
|
||||||
container_of(tt, struct clickdot, cursor_timeout);
|
container_of(task, struct clickdot, cursor_timeout_task);
|
||||||
|
uint64_t exp;
|
||||||
|
|
||||||
|
if (read(clickdot->cursor_timeout_fd, &exp, sizeof (uint64_t)) !=
|
||||||
|
sizeof(uint64_t))
|
||||||
|
abort();
|
||||||
|
|
||||||
input_set_pointer_image(clickdot->cursor_timeout_input,
|
input_set_pointer_image(clickdot->cursor_timeout_input,
|
||||||
CURSOR_LEFT_PTR);
|
CURSOR_LEFT_PTR);
|
||||||
|
|
@ -281,8 +291,6 @@ clickdot_create(struct display *display)
|
||||||
clickdot->window = window_create(display);
|
clickdot->window = window_create(display);
|
||||||
clickdot->widget = window_frame_create(clickdot->window, clickdot);
|
clickdot->widget = window_frame_create(clickdot->window, clickdot);
|
||||||
window_set_title(clickdot->window, "Wayland ClickDot");
|
window_set_title(clickdot->window, "Wayland ClickDot");
|
||||||
window_set_appid(clickdot->window,
|
|
||||||
"org.freedesktop.weston.wayland-clickdot");
|
|
||||||
clickdot->display = display;
|
clickdot->display = display;
|
||||||
clickdot->buffer = NULL;
|
clickdot->buffer = NULL;
|
||||||
|
|
||||||
|
|
@ -306,8 +314,12 @@ clickdot_create(struct display *display)
|
||||||
clickdot->line.old_y = -1;
|
clickdot->line.old_y = -1;
|
||||||
clickdot->reset = 0;
|
clickdot->reset = 0;
|
||||||
|
|
||||||
toytimer_init(&clickdot->cursor_timeout, CLOCK_MONOTONIC,
|
clickdot->cursor_timeout_fd =
|
||||||
display, cursor_timeout_func);
|
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||||
|
clickdot->cursor_timeout_task.run = cursor_timeout_func;
|
||||||
|
display_watch_fd(window_get_display(clickdot->window),
|
||||||
|
clickdot->cursor_timeout_fd,
|
||||||
|
EPOLLIN, &clickdot->cursor_timeout_task);
|
||||||
|
|
||||||
return clickdot;
|
return clickdot;
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +327,9 @@ clickdot_create(struct display *display)
|
||||||
static void
|
static void
|
||||||
clickdot_destroy(struct clickdot *clickdot)
|
clickdot_destroy(struct clickdot *clickdot)
|
||||||
{
|
{
|
||||||
toytimer_fini(&clickdot->cursor_timeout);
|
display_unwatch_fd(window_get_display(clickdot->window),
|
||||||
|
clickdot->cursor_timeout_fd);
|
||||||
|
close(clickdot->cursor_timeout_fd);
|
||||||
if (clickdot->buffer)
|
if (clickdot->buffer)
|
||||||
cairo_surface_destroy(clickdot->buffer);
|
cairo_surface_destroy(clickdot->buffer);
|
||||||
widget_destroy(clickdot->widget);
|
widget_destroy(clickdot->widget);
|
||||||
|
|
@ -331,8 +345,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
display = display_create(&argc, argv);
|
display = display_create(&argc, argv);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,36 +2,31 @@
|
||||||
* Copyright © 2012 Collabora, Ltd.
|
* Copyright © 2012 Collabora, Ltd.
|
||||||
* Copyright © 2012 Rob Clark
|
* Copyright © 2012 Rob Clark
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* cliptest:
|
/* cliptest: for debugging calculate_edges() function.
|
||||||
* For debugging the quad clipper. An arbitrary quad (red) is transformed
|
|
||||||
* from global coordinate space to surface coordinate space and clipped to
|
|
||||||
* an axis-aligned rect (blue).
|
|
||||||
*
|
|
||||||
* controls:
|
* controls:
|
||||||
* surface rect position: mouse left drag, keys: w a s d
|
* clip box position: mouse left drag, keys: w a s d
|
||||||
* surface rect size: mouse right drag, keys: i j k l
|
* clip box size: mouse right drag, keys: i j k l
|
||||||
* quad orientation: mouse wheel, keys: n m
|
* surface orientation: mouse wheel, keys: n m
|
||||||
* quad transform disable: key: r
|
* surface transform disable key: r
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -49,108 +44,144 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
#include "libweston/matrix.h"
|
#include "src/vertex-clipping.h"
|
||||||
#include "libweston/vertex-clipping.h"
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
typedef float GLfloat;
|
typedef float GLfloat;
|
||||||
|
|
||||||
struct geometry {
|
struct geometry {
|
||||||
pixman_box32_t surf;
|
pixman_box32_t clip;
|
||||||
|
|
||||||
pixman_box32_t quad;
|
pixman_box32_t surf;
|
||||||
float s; /* sin phi */
|
float s; /* sin phi */
|
||||||
float c; /* cos phi */
|
float c; /* cos phi */
|
||||||
float phi;
|
float phi;
|
||||||
bool axis_aligned;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_surface {
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_view {
|
struct weston_view {
|
||||||
struct weston_surface *surface;
|
struct {
|
||||||
|
int enabled;
|
||||||
|
} transform;
|
||||||
|
|
||||||
struct geometry *geometry;
|
struct geometry *geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
weston_view_from_global_float(struct weston_view *view,
|
weston_view_to_global_float(struct weston_view *view,
|
||||||
float x, float y, float *sx, float *sy)
|
float sx, float sy, float *x, float *y)
|
||||||
{
|
{
|
||||||
struct geometry *g = view->geometry;
|
struct geometry *g = view->geometry;
|
||||||
|
|
||||||
/* pure rotation around origin by sine and cosine */
|
/* pure rotation around origin by sine and cosine */
|
||||||
*sx = g->c * x + g->s * y;
|
*x = g->c * sx + g->s * sy;
|
||||||
*sy = -g->s * x + g->c * y;
|
*y = -g->s * sx + g->c * sy;
|
||||||
}
|
|
||||||
|
|
||||||
static struct weston_coord_surface
|
|
||||||
weston_coord_global_to_surface(struct weston_view *view, struct weston_coord_global g_pos)
|
|
||||||
{
|
|
||||||
float sx, sy;
|
|
||||||
struct weston_coord_surface pos;
|
|
||||||
|
|
||||||
weston_view_from_global_float(view, g_pos.c.x, g_pos.c.y, &sx, &sy);
|
|
||||||
pos.c = weston_coord(sx, sy);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------- copied begins -----------------------*/
|
/* ---------------------- copied begins -----------------------*/
|
||||||
/* Keep this in sync with what is in gl-renderer.c! */
|
/* Keep this in sync with what is in gl-renderer.c! */
|
||||||
|
|
||||||
static void
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
|
#define min(a, b) (((a) > (b)) ? (b) : (a))
|
||||||
struct clipper_vertex polygon[4])
|
|
||||||
{
|
|
||||||
struct weston_coord_global rect_g[4] = {
|
|
||||||
{ .c = weston_coord(rect->x1, rect->y1) },
|
|
||||||
{ .c = weston_coord(rect->x2, rect->y1) },
|
|
||||||
{ .c = weston_coord(rect->x2, rect->y2) },
|
|
||||||
{ .c = weston_coord(rect->x1, rect->y2) },
|
|
||||||
};
|
|
||||||
struct weston_coord rect_s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
/*
|
||||||
rect_s = weston_coord_global_to_surface(ev, rect_g[i]).c;
|
* Compute the boundary vertices of the intersection of the global coordinate
|
||||||
polygon[i].x = (float)rect_s.x;
|
* aligned rectangle 'rect', and an arbitrary quadrilateral produced from
|
||||||
polygon[i].y = (float)rect_s.y;
|
* 'surf_rect' when transformed from surface coordinates into global coordinates.
|
||||||
|
* The vertices are written to 'ex' and 'ey', and the return value is the
|
||||||
|
* number of vertices. Vertices are produced in clockwise winding order.
|
||||||
|
* Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
|
||||||
|
* polygon area.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
|
||||||
|
pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct clip_context ctx;
|
||||||
|
int i, n;
|
||||||
|
GLfloat min_x, max_x, min_y, max_y;
|
||||||
|
struct polygon8 surf = {
|
||||||
|
{ surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
|
||||||
|
{ surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
|
||||||
|
4
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.clip.x1 = rect->x1;
|
||||||
|
ctx.clip.y1 = rect->y1;
|
||||||
|
ctx.clip.x2 = rect->x2;
|
||||||
|
ctx.clip.y2 = rect->y2;
|
||||||
|
|
||||||
|
/* transform surface to screen space: */
|
||||||
|
for (i = 0; i < surf.n; i++)
|
||||||
|
weston_view_to_global_float(ev, surf.x[i], surf.y[i],
|
||||||
|
&surf.x[i], &surf.y[i]);
|
||||||
|
|
||||||
|
/* find bounding box: */
|
||||||
|
min_x = max_x = surf.x[0];
|
||||||
|
min_y = max_y = surf.y[0];
|
||||||
|
|
||||||
|
for (i = 1; i < surf.n; i++) {
|
||||||
|
min_x = min(min_x, surf.x[i]);
|
||||||
|
max_x = max(max_x, surf.x[i]);
|
||||||
|
min_y = min(min_y, surf.y[i]);
|
||||||
|
max_y = max(max_y, surf.y[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First, simple bounding box check to discard early transformed
|
||||||
|
* surface rects that do not intersect with the clip region:
|
||||||
|
*/
|
||||||
|
if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
|
||||||
|
(min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Simple case, bounding box edges are parallel to surface edges,
|
||||||
|
* there will be only four edges. We just need to clip the surface
|
||||||
|
* vertices to the clip rect bounds:
|
||||||
|
*/
|
||||||
|
if (!ev->transform.enabled)
|
||||||
|
return clip_simple(&ctx, &surf, ex, ey);
|
||||||
|
|
||||||
|
/* Transformed case: use a general polygon clipping algorithm to
|
||||||
|
* clip the surface rectangle with each side of 'rect'.
|
||||||
|
* The algorithm is Sutherland-Hodgman, as explained in
|
||||||
|
* http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
|
||||||
|
* but without looking at any of that code.
|
||||||
|
*/
|
||||||
|
n = clip_transformed(&ctx, &surf, ex, ey);
|
||||||
|
|
||||||
|
if (n < 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------- copied ends -----------------------*/
|
/* ---------------------- copied ends -----------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
geometry_set_phi(struct geometry *g, float phi)
|
geometry_set_phi(struct geometry *g, float phi)
|
||||||
{
|
{
|
||||||
float integer;
|
|
||||||
|
|
||||||
g->phi = phi;
|
g->phi = phi;
|
||||||
g->s = sin(phi);
|
g->s = sin(phi);
|
||||||
g->c = cos(phi);
|
g->c = cos(phi);
|
||||||
g->axis_aligned = fabs(modff(g->c, &integer)) < 0.0001f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
geometry_init(struct geometry *g)
|
geometry_init(struct geometry *g)
|
||||||
{
|
{
|
||||||
g->surf.x1 = -50;
|
g->clip.x1 = -50;
|
||||||
g->surf.y1 = -50;
|
g->clip.y1 = -50;
|
||||||
g->surf.x2 = -10;
|
g->clip.x2 = -10;
|
||||||
g->surf.y2 = -10;
|
g->clip.y2 = -10;
|
||||||
|
|
||||||
g->quad.x1 = -20;
|
g->surf.x1 = -20;
|
||||||
g->quad.y1 = -20;
|
g->surf.y1 = -20;
|
||||||
g->quad.x2 = 20;
|
g->surf.x2 = 20;
|
||||||
g->quad.y2 = 20;
|
g->surf.y2 = 20;
|
||||||
|
|
||||||
geometry_set_phi(g, 0.0);
|
geometry_set_phi(g, 0.0);
|
||||||
}
|
}
|
||||||
|
|
@ -172,36 +203,35 @@ struct cliptest {
|
||||||
struct ui_state ui;
|
struct ui_state ui;
|
||||||
|
|
||||||
struct geometry geometry;
|
struct geometry geometry;
|
||||||
struct weston_surface surface;
|
|
||||||
struct weston_view view;
|
struct weston_view view;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_polygon_closed(cairo_t *cr, struct clipper_vertex *pos, int n)
|
draw_polygon_closed(cairo_t *cr, GLfloat *x, GLfloat *y, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cairo_move_to(cr, pos[0].x, pos[0].y);
|
cairo_move_to(cr, x[0], y[0]);
|
||||||
for (i = 1; i < n; i++)
|
for (i = 1; i < n; i++)
|
||||||
cairo_line_to(cr, pos[i].x, pos[i].y);
|
cairo_line_to(cr, x[i], y[i]);
|
||||||
cairo_line_to(cr, pos[0].x, pos[0].y);
|
cairo_line_to(cr, x[0], y[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_polygon_labels(cairo_t *cr, struct clipper_vertex *pos, int n)
|
draw_polygon_labels(cairo_t *cr, GLfloat *x, GLfloat *y, int n)
|
||||||
{
|
{
|
||||||
char str[16];
|
char str[16];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
snprintf(str, 16, "%d", i);
|
snprintf(str, 16, "%d", i);
|
||||||
cairo_move_to(cr, pos[i].x, pos[i].y);
|
cairo_move_to(cr, x[i], y[i]);
|
||||||
cairo_show_text(cr, str);
|
cairo_show_text(cr, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_coordinates(cairo_t *cr, double ox, double oy, struct clipper_vertex *pos, int n)
|
draw_coordinates(cairo_t *cr, double ox, double oy, GLfloat *x, GLfloat *y, int n)
|
||||||
{
|
{
|
||||||
char str[64];
|
char str[64];
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -209,7 +239,7 @@ draw_coordinates(cairo_t *cr, double ox, double oy, struct clipper_vertex *pos,
|
||||||
|
|
||||||
cairo_font_extents(cr, &ext);
|
cairo_font_extents(cr, &ext);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
snprintf(str, 64, "%d: %14.9f, %14.9f", i, pos[i].x, pos[i].y);
|
snprintf(str, 64, "%d: %14.9f, %14.9f", i, x[i], y[i]);
|
||||||
cairo_move_to(cr, ox, oy + ext.height * (i + 1));
|
cairo_move_to(cr, ox, oy + ext.height * (i + 1));
|
||||||
cairo_show_text(cr, str);
|
cairo_show_text(cr, str);
|
||||||
}
|
}
|
||||||
|
|
@ -218,50 +248,50 @@ draw_coordinates(cairo_t *cr, double ox, double oy, struct clipper_vertex *pos,
|
||||||
static void
|
static void
|
||||||
draw_box(cairo_t *cr, pixman_box32_t *box, struct weston_view *view)
|
draw_box(cairo_t *cr, pixman_box32_t *box, struct weston_view *view)
|
||||||
{
|
{
|
||||||
struct clipper_vertex pos[4];
|
GLfloat x[4], y[4];
|
||||||
|
|
||||||
if (view) {
|
if (view) {
|
||||||
weston_view_from_global_float(view, box->x1, box->y1, &pos[0].x, &pos[0].y);
|
weston_view_to_global_float(view, box->x1, box->y1, &x[0], &y[0]);
|
||||||
weston_view_from_global_float(view, box->x2, box->y1, &pos[1].x, &pos[1].y);
|
weston_view_to_global_float(view, box->x2, box->y1, &x[1], &y[1]);
|
||||||
weston_view_from_global_float(view, box->x2, box->y2, &pos[2].x, &pos[2].y);
|
weston_view_to_global_float(view, box->x2, box->y2, &x[2], &y[2]);
|
||||||
weston_view_from_global_float(view, box->x1, box->y2, &pos[3].x, &pos[3].y);
|
weston_view_to_global_float(view, box->x1, box->y2, &x[3], &y[3]);
|
||||||
} else {
|
} else {
|
||||||
pos[0].x = box->x1; pos[0].y = box->y1;
|
x[0] = box->x1; y[0] = box->y1;
|
||||||
pos[1].x = box->x2; pos[1].y = box->y1;
|
x[1] = box->x2; y[1] = box->y1;
|
||||||
pos[2].x = box->x2; pos[2].y = box->y2;
|
x[2] = box->x2; y[2] = box->y2;
|
||||||
pos[3].x = box->x1; pos[3].y = box->y2;
|
x[3] = box->x1; y[3] = box->y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_polygon_closed(cr, pos, 4);
|
draw_polygon_closed(cr, x, y, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_geometry(cairo_t *cr, struct weston_view *view,
|
draw_geometry(cairo_t *cr, struct weston_view *view,
|
||||||
struct clipper_vertex *v, int n, struct clipper_quad *quad)
|
GLfloat *ex, GLfloat *ey, int n)
|
||||||
{
|
{
|
||||||
struct geometry *g = view->geometry;
|
struct geometry *g = view->geometry;
|
||||||
float cx, cy;
|
float cx, cy;
|
||||||
|
|
||||||
draw_box(cr, &g->quad, view);
|
draw_box(cr, &g->surf, view);
|
||||||
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4);
|
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4);
|
||||||
cairo_fill(cr);
|
cairo_fill(cr);
|
||||||
weston_view_from_global_float(view, g->quad.x1 - 4, g->quad.y1 - 4, &cx, &cy);
|
weston_view_to_global_float(view, g->surf.x1 - 4, g->surf.y1 - 4, &cx, &cy);
|
||||||
cairo_arc(cr, cx, cy, 1.5, 0.0, 2.0 * M_PI);
|
cairo_arc(cr, cx, cy, 1.5, 0.0, 2.0 * M_PI);
|
||||||
if (!quad->axis_aligned)
|
if (view->transform.enabled == 0)
|
||||||
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.8);
|
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.8);
|
||||||
cairo_fill(cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
draw_box(cr, &g->surf, NULL);
|
draw_box(cr, &g->clip, NULL);
|
||||||
cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.4);
|
cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.4);
|
||||||
cairo_fill(cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
if (n) {
|
if (n) {
|
||||||
draw_polygon_closed(cr, v, n);
|
draw_polygon_closed(cr, ex, ey, n);
|
||||||
cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
|
cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.5);
|
cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.5);
|
||||||
draw_polygon_labels(cr, v, n);
|
draw_polygon_labels(cr, ex, ey, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,13 +303,11 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
struct clipper_quad quad;
|
GLfloat ex[8];
|
||||||
struct clipper_vertex transformed_v[4], v[8];
|
GLfloat ey[8];
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
global_to_surface(&g->quad, &cliptest->view, transformed_v);
|
n = calculate_edges(&cliptest->view, &g->clip, &g->surf, ex, ey);
|
||||||
clipper_quad_init(&quad, transformed_v, g->axis_aligned);
|
|
||||||
n = clipper_quad_clip_box32(&quad, &g->surf, v);
|
|
||||||
|
|
||||||
widget_get_allocation(cliptest->widget, &allocation);
|
widget_get_allocation(cliptest->widget, &allocation);
|
||||||
|
|
||||||
|
|
@ -310,10 +338,10 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
cairo_scale(cr, 4.0, 4.0);
|
cairo_scale(cr, 4.0, 4.0);
|
||||||
cairo_set_line_width(cr, 0.5);
|
cairo_set_line_width(cr, 0.5);
|
||||||
cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
|
||||||
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL,
|
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
|
||||||
CAIRO_FONT_WEIGHT_BOLD);
|
CAIRO_FONT_WEIGHT_BOLD);
|
||||||
cairo_set_font_size(cr, 5.0);
|
cairo_set_font_size(cr, 5.0);
|
||||||
draw_geometry(cr, &cliptest->view, v, n, &quad);
|
draw_geometry(cr, &cliptest->view, ex, ey, n);
|
||||||
cairo_pop_group_to_source(cr);
|
cairo_pop_group_to_source(cr);
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
|
|
||||||
|
|
@ -321,7 +349,7 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL,
|
cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL,
|
||||||
CAIRO_FONT_WEIGHT_NORMAL);
|
CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
cairo_set_font_size(cr, 12.0);
|
cairo_set_font_size(cr, 12.0);
|
||||||
draw_coordinates(cr, 10.0, 10.0, v, n);
|
draw_coordinates(cr, 10.0, 10.0, ex, ey, n);
|
||||||
|
|
||||||
cairo_destroy(cr);
|
cairo_destroy(cr);
|
||||||
|
|
||||||
|
|
@ -346,12 +374,12 @@ motion_handler(struct widget *widget, struct input *input,
|
||||||
|
|
||||||
switch (ui->button) {
|
switch (ui->button) {
|
||||||
case BTN_LEFT:
|
case BTN_LEFT:
|
||||||
geom->surf.x1 = ref->surf.x1 + dx;
|
geom->clip.x1 = ref->clip.x1 + dx;
|
||||||
geom->surf.y1 = ref->surf.y1 + dy;
|
geom->clip.y1 = ref->clip.y1 + dy;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case BTN_RIGHT:
|
case BTN_RIGHT:
|
||||||
geom->surf.x2 = ref->surf.x2 + dx;
|
geom->clip.x2 = ref->clip.x2 + dx;
|
||||||
geom->surf.y2 = ref->surf.y2 + dy;
|
geom->clip.y2 = ref->clip.y2 + dy;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return CURSOR_LEFT_PTR;
|
return CURSOR_LEFT_PTR;
|
||||||
|
|
@ -392,6 +420,7 @@ axis_handler(struct widget *widget, struct input *input, uint32_t time,
|
||||||
|
|
||||||
geometry_set_phi(geom, geom->phi +
|
geometry_set_phi(geom, geom->phi +
|
||||||
(M_PI / 12.0) * wl_fixed_to_double(value));
|
(M_PI / 12.0) * wl_fixed_to_double(value));
|
||||||
|
cliptest->view.transform.enabled = 1;
|
||||||
|
|
||||||
widget_schedule_redraw(cliptest->widget);
|
widget_schedule_redraw(cliptest->widget);
|
||||||
}
|
}
|
||||||
|
|
@ -412,41 +441,44 @@ key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
display_exit(cliptest->display);
|
display_exit(cliptest->display);
|
||||||
return;
|
return;
|
||||||
case XKB_KEY_w:
|
case XKB_KEY_w:
|
||||||
g->surf.y1 -= 1;
|
g->clip.y1 -= 1;
|
||||||
g->surf.y2 -= 1;
|
g->clip.y2 -= 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_a:
|
case XKB_KEY_a:
|
||||||
g->surf.x1 -= 1;
|
g->clip.x1 -= 1;
|
||||||
g->surf.x2 -= 1;
|
g->clip.x2 -= 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_s:
|
case XKB_KEY_s:
|
||||||
g->surf.y1 += 1;
|
g->clip.y1 += 1;
|
||||||
g->surf.y2 += 1;
|
g->clip.y2 += 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_d:
|
case XKB_KEY_d:
|
||||||
g->surf.x1 += 1;
|
g->clip.x1 += 1;
|
||||||
g->surf.x2 += 1;
|
g->clip.x2 += 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_i:
|
case XKB_KEY_i:
|
||||||
g->surf.y2 -= 1;
|
g->clip.y2 -= 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_j:
|
case XKB_KEY_j:
|
||||||
g->surf.x2 -= 1;
|
g->clip.x2 -= 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_k:
|
case XKB_KEY_k:
|
||||||
g->surf.y2 += 1;
|
g->clip.y2 += 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_l:
|
case XKB_KEY_l:
|
||||||
g->surf.x2 += 1;
|
g->clip.x2 += 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_n:
|
case XKB_KEY_n:
|
||||||
geometry_set_phi(g, g->phi + (M_PI / 24.0));
|
geometry_set_phi(g, g->phi + (M_PI / 24.0));
|
||||||
|
cliptest->view.transform.enabled = 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_m:
|
case XKB_KEY_m:
|
||||||
geometry_set_phi(g, g->phi - (M_PI / 24.0));
|
geometry_set_phi(g, g->phi - (M_PI / 24.0));
|
||||||
|
cliptest->view.transform.enabled = 1;
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_r:
|
case XKB_KEY_r:
|
||||||
geometry_set_phi(g, 0.0);
|
geometry_set_phi(g, 0.0);
|
||||||
|
cliptest->view.transform.enabled = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
|
@ -479,15 +511,14 @@ cliptest_create(struct display *display)
|
||||||
struct cliptest *cliptest;
|
struct cliptest *cliptest;
|
||||||
|
|
||||||
cliptest = xzalloc(sizeof *cliptest);
|
cliptest = xzalloc(sizeof *cliptest);
|
||||||
cliptest->view.surface = &cliptest->surface;
|
|
||||||
cliptest->view.geometry = &cliptest->geometry;
|
cliptest->view.geometry = &cliptest->geometry;
|
||||||
|
cliptest->view.transform.enabled = 0;
|
||||||
geometry_init(&cliptest->geometry);
|
geometry_init(&cliptest->geometry);
|
||||||
geometry_init(&cliptest->ui.geometry);
|
geometry_init(&cliptest->ui.geometry);
|
||||||
|
|
||||||
cliptest->window = window_create(display);
|
cliptest->window = window_create(display);
|
||||||
cliptest->widget = window_frame_create(cliptest->window, cliptest);
|
cliptest->widget = window_frame_create(cliptest->window, cliptest);
|
||||||
window_set_title(cliptest->window, "cliptest");
|
window_set_title(cliptest->window, "cliptest");
|
||||||
window_set_appid(cliptest->window, "org.freedesktop.weston.cliptest");
|
|
||||||
cliptest->display = display;
|
cliptest->display = display;
|
||||||
|
|
||||||
window_set_user_data(cliptest->window, cliptest);
|
window_set_user_data(cliptest->window, cliptest);
|
||||||
|
|
@ -531,36 +562,32 @@ read_timer(void)
|
||||||
static int
|
static int
|
||||||
benchmark(void)
|
benchmark(void)
|
||||||
{
|
{
|
||||||
struct weston_surface surface;
|
|
||||||
struct weston_view view;
|
struct weston_view view;
|
||||||
struct geometry geom;
|
struct geometry geom;
|
||||||
struct clipper_quad quad;
|
GLfloat ex[8], ey[8];
|
||||||
struct clipper_vertex transformed_v[4], v[8];
|
|
||||||
int i;
|
int i;
|
||||||
double t;
|
double t;
|
||||||
const int N = 1000000;
|
const int N = 1000000;
|
||||||
|
|
||||||
geom.surf.x1 = -19;
|
geom.clip.x1 = -19;
|
||||||
geom.surf.y1 = -19;
|
geom.clip.y1 = -19;
|
||||||
geom.surf.x2 = 19;
|
geom.clip.x2 = 19;
|
||||||
geom.surf.y2 = 19;
|
geom.clip.y2 = 19;
|
||||||
|
|
||||||
geom.quad.x1 = -20;
|
geom.surf.x1 = -20;
|
||||||
geom.quad.y1 = -20;
|
geom.surf.y1 = -20;
|
||||||
geom.quad.x2 = 20;
|
geom.surf.x2 = 20;
|
||||||
geom.quad.y2 = 20;
|
geom.surf.y2 = 20;
|
||||||
|
|
||||||
geometry_set_phi(&geom, 0.0);
|
geometry_set_phi(&geom, 0.0);
|
||||||
|
|
||||||
view.surface = &surface;
|
view.transform.enabled = 1;
|
||||||
view.geometry = &geom;
|
view.geometry = &geom;
|
||||||
|
|
||||||
reset_timer();
|
reset_timer();
|
||||||
for (i = 0; i < N; i++) {
|
for (i = 0; i < N; i++) {
|
||||||
geometry_set_phi(&geom, (float)i / 360.0f);
|
geometry_set_phi(&geom, (float)i / 360.0f);
|
||||||
global_to_surface(&geom.quad, &view, transformed_v);
|
calculate_edges(&view, &geom.clip, &geom.surf, ex, ey);
|
||||||
clipper_quad_init(&quad, transformed_v, geom.axis_aligned);
|
|
||||||
clipper_quad_clip_box32(&quad, &geom.surf, v);
|
|
||||||
}
|
}
|
||||||
t = read_timer();
|
t = read_timer();
|
||||||
|
|
||||||
|
|
@ -592,8 +619,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
610
clients/color.c
|
|
@ -1,610 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2024 SUSE Software Solutions Germany GmbH
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "color-management-v1-client-protocol.h"
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "single-pixel-buffer-v1-client-protocol.h"
|
|
||||||
#include "viewporter-client-protocol.h"
|
|
||||||
#include "window.h"
|
|
||||||
|
|
||||||
enum image_description_status {
|
|
||||||
IMAGE_DESCRIPTION_NOT_CREATED = 0,
|
|
||||||
IMAGE_DESCRIPTION_READY,
|
|
||||||
IMAGE_DESCRIPTION_FAILED,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pixel_color {
|
|
||||||
uint32_t r;
|
|
||||||
uint32_t g;
|
|
||||||
uint32_t b;
|
|
||||||
uint32_t a;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct color {
|
|
||||||
struct display *display;
|
|
||||||
struct window *window;
|
|
||||||
struct widget *parent_widget;
|
|
||||||
struct widget *widget;
|
|
||||||
|
|
||||||
struct wp_color_manager_v1 *color_manager;
|
|
||||||
struct wp_color_management_surface_v1 *color_surface;
|
|
||||||
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
|
|
||||||
struct wp_viewporter *viewporter;
|
|
||||||
struct wp_viewport *viewport;
|
|
||||||
|
|
||||||
struct pixel_color pixel_color;
|
|
||||||
|
|
||||||
bool unmanaged;
|
|
||||||
|
|
||||||
enum wp_color_manager_v1_primaries primaries;
|
|
||||||
enum wp_color_manager_v1_transfer_function transfer_function;
|
|
||||||
float min_lum;
|
|
||||||
float max_lum;
|
|
||||||
float ref_lum;
|
|
||||||
|
|
||||||
uint32_t supported_color_features;
|
|
||||||
uint32_t supported_rendering_intents;
|
|
||||||
uint32_t supported_primaries_named;
|
|
||||||
uint32_t supported_tf_named;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct valid_enum {
|
|
||||||
const char *name;
|
|
||||||
uint32_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool opt_help = false;
|
|
||||||
static uint32_t opt_width = 250;
|
|
||||||
static uint32_t opt_height = 250;
|
|
||||||
static const char *opt_r = NULL;
|
|
||||||
static const char *opt_g = NULL;
|
|
||||||
static const char *opt_b = NULL;
|
|
||||||
static const char *opt_a = NULL;
|
|
||||||
static bool opt_unmanaged = false;
|
|
||||||
static const char *opt_primaries = NULL;
|
|
||||||
static const char *opt_transfer_function = NULL;
|
|
||||||
static const char *opt_min_lum = NULL;
|
|
||||||
static const char *opt_max_lum = NULL;
|
|
||||||
static const char *opt_ref_lum = NULL;
|
|
||||||
static const struct weston_option cli_options[] = {
|
|
||||||
{ WESTON_OPTION_BOOLEAN, "help", 0, &opt_help },
|
|
||||||
{ WESTON_OPTION_UNSIGNED_INTEGER, "width", 'w', &opt_width },
|
|
||||||
{ WESTON_OPTION_UNSIGNED_INTEGER, "height", 'h', &opt_height },
|
|
||||||
{ WESTON_OPTION_STRING, 0, 'R', &opt_r },
|
|
||||||
{ WESTON_OPTION_STRING, 0, 'G', &opt_g },
|
|
||||||
{ WESTON_OPTION_STRING, 0, 'B', &opt_b },
|
|
||||||
{ WESTON_OPTION_STRING, 0, 'A', &opt_a },
|
|
||||||
{ WESTON_OPTION_BOOLEAN, "unmanaged", 'u', &opt_unmanaged },
|
|
||||||
{ WESTON_OPTION_STRING, "primaries", 'p', &opt_primaries },
|
|
||||||
{ WESTON_OPTION_STRING, "transfer-function", 't', &opt_transfer_function },
|
|
||||||
{ WESTON_OPTION_STRING, "min-lum", 'm', &opt_min_lum },
|
|
||||||
{ WESTON_OPTION_STRING, "max-lum", 'M', &opt_max_lum },
|
|
||||||
{ WESTON_OPTION_STRING, "ref-lum", 'r', &opt_ref_lum },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct valid_enum valid_primaries[] = {
|
|
||||||
{ "srgb", WP_COLOR_MANAGER_V1_PRIMARIES_SRGB },
|
|
||||||
{ "bt2020", WP_COLOR_MANAGER_V1_PRIMARIES_BT2020 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct valid_enum valid_transfer_functions[] = {
|
|
||||||
{ "srgb", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB },
|
|
||||||
{ "pq", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ },
|
|
||||||
{ "linear", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR },
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool
|
|
||||||
validate_color(const char *c, uint32_t *dest, uint32_t fallback)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
double value;
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
*dest = fallback;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = strtod(c, &end);
|
|
||||||
if (value < 0.0 || value > 1.0 || *end != '\0') {
|
|
||||||
fprintf(stderr, "Validating color failed, it should be between 0.0 and 1.0\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest = value * UINT32_MAX;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
validate_option(const struct color *color,
|
|
||||||
const char *option, uint32_t *dest,
|
|
||||||
const struct valid_enum *valid_options,
|
|
||||||
int count, uint32_t fallback)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (color->unmanaged && option) {
|
|
||||||
fprintf(stderr, "Option '%s' not valid in unmanaged mode\n", option);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!option) {
|
|
||||||
*dest = fallback;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
if (strcmp(valid_options[i].name, option) == 0) {
|
|
||||||
*dest = valid_options[i].value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Validating option '%s' failed, valid options:\n", option);
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
fprintf(stderr, "'%s' ", valid_options[i].name);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
validate_luminance(const struct color *color,
|
|
||||||
const char *c, float *dest, float fallback)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
float value;
|
|
||||||
|
|
||||||
if (color->unmanaged && c) {
|
|
||||||
fprintf(stderr, "Luminance not valid in unmanaged mode.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
*dest = fallback;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = strtof(c, &end);
|
|
||||||
if (value < 0.f || value > 10000.f || *end != '\0') {
|
|
||||||
fprintf(stderr, "Validating luminance failed, it should be between 0 and 10,000\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest = value;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
validate_options(struct color *color)
|
|
||||||
{
|
|
||||||
color->unmanaged = opt_unmanaged;
|
|
||||||
|
|
||||||
return validate_color(opt_r, &color->pixel_color.r, 0) &&
|
|
||||||
validate_color(opt_g, &color->pixel_color.g, 0) &&
|
|
||||||
validate_color(opt_b, &color->pixel_color.b, 0) &&
|
|
||||||
validate_color(opt_a, &color->pixel_color.a, UINT32_MAX) &&
|
|
||||||
validate_option(color, opt_primaries, &color->primaries,
|
|
||||||
valid_primaries,
|
|
||||||
ARRAY_LENGTH(valid_primaries),
|
|
||||||
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
|
|
||||||
validate_option(color, opt_transfer_function, &color->transfer_function,
|
|
||||||
valid_transfer_functions,
|
|
||||||
ARRAY_LENGTH(valid_transfer_functions),
|
|
||||||
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
|
|
||||||
validate_luminance(color, opt_min_lum, &color->min_lum, -1.f) &&
|
|
||||||
validate_luminance(color, opt_max_lum, &color->max_lum, -1.f) &&
|
|
||||||
validate_luminance(color, opt_ref_lum, &color->ref_lum, -1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(const char *program_name, int exit_code)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
fprintf(stderr, "Usage: %s [OPTIONS]\n", program_name);
|
|
||||||
fprintf(stderr, " --help\n");
|
|
||||||
fprintf(stderr, " --width or -w\n");
|
|
||||||
fprintf(stderr, " --height or -h\n");
|
|
||||||
fprintf(stderr, " -R (0.0 to 1.0)\n");
|
|
||||||
fprintf(stderr, " -G (0.0 to 1.0)\n");
|
|
||||||
fprintf(stderr, " -B (0.0 to 1.0)\n");
|
|
||||||
fprintf(stderr, " -A (0.0 to 1.0)\n");
|
|
||||||
fprintf(stderr, " Mode of operation may be:\n");
|
|
||||||
fprintf(stderr, " --unmanaged or -u: do not use color-management\n");
|
|
||||||
fprintf(stderr, " Or use the following:\n");
|
|
||||||
fprintf(stderr, " --primaries or -p:");
|
|
||||||
fprintf(stderr, "\n ");
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(valid_primaries); i++)
|
|
||||||
fprintf(stderr, " '%s'", valid_primaries[i].name);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, " --transfer-function or -t:");
|
|
||||||
fprintf(stderr, "\n ");
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(valid_transfer_functions); i++)
|
|
||||||
fprintf(stderr, " '%s'", valid_transfer_functions[i].name);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, " --min-lum or -m (0.0 to 10000.0)\n");
|
|
||||||
fprintf(stderr, " --max-lum or -M (0.0 to 10000.0)\n");
|
|
||||||
fprintf(stderr, " --ref-lum or -r (0.0 to 10000.0)\n");
|
|
||||||
|
|
||||||
exit(exit_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
|
||||||
uint32_t render_intent)
|
|
||||||
{
|
|
||||||
struct color *color = data;
|
|
||||||
|
|
||||||
color->supported_rendering_intents |= 1 << render_intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
|
||||||
uint32_t feature)
|
|
||||||
{
|
|
||||||
struct color *color = data;
|
|
||||||
|
|
||||||
color->supported_color_features |= 1 << feature;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
|
||||||
uint32_t tf)
|
|
||||||
{
|
|
||||||
struct color *color = data;
|
|
||||||
|
|
||||||
color->supported_tf_named |= 1 << tf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
supported_primaries_named(void *data,
|
|
||||||
struct wp_color_manager_v1 *wp_color_manager_v1,
|
|
||||||
uint32_t primaries)
|
|
||||||
{
|
|
||||||
struct color *color = data;
|
|
||||||
|
|
||||||
color->supported_primaries_named |= 1 << primaries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wp_color_manager_v1_listener color_manager_listener = {
|
|
||||||
supported_intent,
|
|
||||||
supported_feature,
|
|
||||||
supported_tf_named,
|
|
||||||
supported_primaries_named,
|
|
||||||
done,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
global_handler(struct display *display, uint32_t name,
|
|
||||||
const char *interface, uint32_t version, void *data)
|
|
||||||
{
|
|
||||||
struct color *color = data;
|
|
||||||
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
|
||||||
|
|
||||||
if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
|
||||||
color->single_pixel_manager =
|
|
||||||
display_bind(display, name,
|
|
||||||
&wp_single_pixel_buffer_manager_v1_interface, 1);
|
|
||||||
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
|
||||||
color->viewporter = display_bind(display, name,
|
|
||||||
&wp_viewporter_interface, 1);
|
|
||||||
color->viewport = wp_viewporter_get_viewport(color->viewporter, surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color->unmanaged)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (strcmp(interface, wp_color_manager_v1_interface.name) == 0) {
|
|
||||||
color->color_manager = display_bind(display, name,
|
|
||||||
&wp_color_manager_v1_interface, 1);
|
|
||||||
color->color_surface = wp_color_manager_v1_get_surface(color->color_manager,
|
|
||||||
surface);
|
|
||||||
wp_color_manager_v1_add_listener(color->color_manager,
|
|
||||||
&color_manager_listener, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
check_color_requirements(struct color *color)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!color->color_manager) {
|
|
||||||
fprintf(stderr, "The compositor doesn't expose %s\n",
|
|
||||||
wp_color_manager_v1_interface.name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC))) {
|
|
||||||
fprintf(stderr, "The color manager doesn't support the parametric creator\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(color->supported_primaries_named & (1 << color->primaries))) {
|
|
||||||
fprintf(stderr, "The color manager doesn't support the primaries name\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(color->supported_tf_named & (1 << color->transfer_function))) {
|
|
||||||
fprintf(stderr, "The color manager doesn't support the transfer function\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(color->supported_rendering_intents & (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL))) {
|
|
||||||
fprintf(stderr, "The color manager doesn't support perceptual render intent\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (color->min_lum != -1.f || color->max_lum != -1.f || color->ref_lum != -1.f) {
|
|
||||||
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES))) {
|
|
||||||
fprintf(stderr, "The color manager doesn't support setting luminances\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (color->min_lum == -1.f || color->max_lum == -1.f || color->ref_lum == -1.f) {
|
|
||||||
fprintf(stderr, "To set the luminances it is required min-lum, max-lum and ref-lum\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
color_destroy(struct color *color)
|
|
||||||
{
|
|
||||||
if (color->color_surface)
|
|
||||||
wp_color_management_surface_v1_destroy(color->color_surface);
|
|
||||||
|
|
||||||
if (color->color_manager)
|
|
||||||
wp_color_manager_v1_destroy(color->color_manager);
|
|
||||||
|
|
||||||
if (color->single_pixel_manager)
|
|
||||||
wp_single_pixel_buffer_manager_v1_destroy(color->single_pixel_manager);
|
|
||||||
|
|
||||||
if (color->viewport)
|
|
||||||
wp_viewport_destroy(color->viewport);
|
|
||||||
|
|
||||||
if (color->viewporter)
|
|
||||||
wp_viewporter_destroy(color->viewporter);
|
|
||||||
|
|
||||||
if (color->widget)
|
|
||||||
widget_destroy(color->widget);
|
|
||||||
|
|
||||||
if (color->parent_widget)
|
|
||||||
widget_destroy(color->parent_widget);
|
|
||||||
|
|
||||||
if (color->window)
|
|
||||||
window_destroy(color->window);
|
|
||||||
|
|
||||||
if (color->display)
|
|
||||||
display_destroy(color->display);
|
|
||||||
|
|
||||||
free(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
resize_handler(struct widget *parent_widget, int32_t width, int32_t height, void *data)
|
|
||||||
{
|
|
||||||
struct color *color = data;
|
|
||||||
struct rectangle allocation;
|
|
||||||
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
|
||||||
struct wl_subsurface *subsurface = widget_get_wl_subsurface(color->widget);
|
|
||||||
|
|
||||||
widget_get_allocation(parent_widget, &allocation);
|
|
||||||
wl_subsurface_set_position(subsurface, allocation.x, allocation.y);
|
|
||||||
|
|
||||||
wp_viewport_set_destination(color->viewport, width, height);
|
|
||||||
|
|
||||||
wl_surface_commit(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_empty_input_region(struct color *color, struct widget *widget)
|
|
||||||
{
|
|
||||||
struct wl_region *region;
|
|
||||||
struct wl_compositor *compositor;
|
|
||||||
struct wl_surface *surface = widget_get_wl_surface(widget);
|
|
||||||
|
|
||||||
compositor = display_get_compositor(color->display);
|
|
||||||
region = wl_compositor_create_region(compositor);
|
|
||||||
wl_surface_set_input_region(surface, region);
|
|
||||||
wl_region_destroy(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
buffer_release(void *data, struct wl_buffer *buffer)
|
|
||||||
{
|
|
||||||
wl_buffer_destroy(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_buffer_listener buffer_listener = {
|
|
||||||
buffer_release
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_single_pixel(struct color *color, struct widget *widget)
|
|
||||||
{
|
|
||||||
struct wl_surface *surface = widget_get_wl_surface(widget);
|
|
||||||
struct wl_buffer *buffer =
|
|
||||||
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(color->single_pixel_manager,
|
|
||||||
color->pixel_color.r,
|
|
||||||
color->pixel_color.g,
|
|
||||||
color->pixel_color.b,
|
|
||||||
color->pixel_color.a);
|
|
||||||
wl_buffer_add_listener(buffer, &buffer_listener, NULL);
|
|
||||||
wl_surface_attach(surface, buffer, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
image_description_failed(void *data,
|
|
||||||
struct wp_image_description_v1 *wp_image_description_v1,
|
|
||||||
uint32_t cause, const char *msg)
|
|
||||||
{
|
|
||||||
enum image_description_status *image_desc_status = data;
|
|
||||||
|
|
||||||
fprintf(stderr, "Failed to create image description: %u - %s\n",
|
|
||||||
cause, msg);
|
|
||||||
|
|
||||||
*image_desc_status = IMAGE_DESCRIPTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
|
|
||||||
uint32_t identity)
|
|
||||||
{
|
|
||||||
enum image_description_status *image_desc_status = data;
|
|
||||||
|
|
||||||
*image_desc_status = IMAGE_DESCRIPTION_READY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wp_image_description_v1_listener image_description_listener = {
|
|
||||||
image_description_failed,
|
|
||||||
image_description_ready,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct wp_image_description_v1 *
|
|
||||||
create_image_description(struct color *color, uint32_t primaries_named, uint32_t tf_named)
|
|
||||||
{
|
|
||||||
struct wp_image_description_creator_params_v1 *params_creator;
|
|
||||||
struct wp_image_description_v1 *image_description;
|
|
||||||
enum image_description_status image_desc_status = IMAGE_DESCRIPTION_NOT_CREATED;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
params_creator = wp_color_manager_v1_create_parametric_creator(color->color_manager);
|
|
||||||
wp_image_description_creator_params_v1_set_primaries_named(params_creator, primaries_named);
|
|
||||||
wp_image_description_creator_params_v1_set_tf_named(params_creator, tf_named);
|
|
||||||
if (color->min_lum != -1 && color->max_lum != -1 && color->ref_lum != -1)
|
|
||||||
wp_image_description_creator_params_v1_set_luminances(params_creator,
|
|
||||||
color->min_lum * 10000,
|
|
||||||
color->max_lum,
|
|
||||||
color->ref_lum);
|
|
||||||
|
|
||||||
image_description = wp_image_description_creator_params_v1_create(params_creator);
|
|
||||||
wp_image_description_v1_add_listener(image_description,
|
|
||||||
&image_description_listener,
|
|
||||||
&image_desc_status);
|
|
||||||
|
|
||||||
while (ret != -1 && image_desc_status == IMAGE_DESCRIPTION_NOT_CREATED)
|
|
||||||
ret = wl_display_dispatch(display_get_display(color->display));
|
|
||||||
if (ret == -1) {
|
|
||||||
wp_image_description_v1_destroy(image_description);
|
|
||||||
fprintf(stderr, "Error when creating the image description: %s\n", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image_desc_status == IMAGE_DESCRIPTION_FAILED) {
|
|
||||||
wp_image_description_v1_destroy(image_description);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(image_desc_status == IMAGE_DESCRIPTION_READY);
|
|
||||||
|
|
||||||
return image_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
set_image_description(struct color *color, struct widget *widget)
|
|
||||||
{
|
|
||||||
struct wp_image_description_v1 *image_description;
|
|
||||||
|
|
||||||
image_description =
|
|
||||||
create_image_description(color,
|
|
||||||
color->primaries,
|
|
||||||
color->transfer_function);
|
|
||||||
if (!image_description)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wp_color_management_surface_v1_set_image_description(
|
|
||||||
color->color_surface,
|
|
||||||
image_description,
|
|
||||||
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
|
||||||
|
|
||||||
wp_image_description_v1_destroy(image_description);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct color *color;
|
|
||||||
|
|
||||||
if (parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv) > 1)
|
|
||||||
usage(argv[0], EXIT_FAILURE);
|
|
||||||
|
|
||||||
if (opt_help)
|
|
||||||
usage(argv[0], EXIT_SUCCESS);
|
|
||||||
|
|
||||||
color = xzalloc(sizeof *color);
|
|
||||||
if (!validate_options(color)) {
|
|
||||||
color_destroy(color);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
color->display = display_create(&argc, argv);
|
|
||||||
if (!color->display) {
|
|
||||||
color_destroy(color);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
color->window = window_create(color->display);
|
|
||||||
color->parent_widget = window_frame_create(color->window, color);
|
|
||||||
color->widget = window_add_subsurface(color->window, color, SUBSURFACE_SYNCHRONIZED);
|
|
||||||
|
|
||||||
display_set_user_data(color->display, color);
|
|
||||||
display_set_global_handler(color->display, global_handler);
|
|
||||||
wl_display_roundtrip(display_get_display(color->display));
|
|
||||||
|
|
||||||
if (!color->unmanaged && !check_color_requirements(color)) {
|
|
||||||
color_destroy(color);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
window_unset_shadow(color->window);
|
|
||||||
window_set_title(color->window, "Color");
|
|
||||||
window_set_appid(color->window, "org.freedesktop.weston.color");
|
|
||||||
/* The first resize call sets the min size,
|
|
||||||
* setting 0, 0 sets a default size */
|
|
||||||
window_schedule_resize(color->window, 0, 0);
|
|
||||||
window_schedule_resize(color->window, opt_width, opt_height);
|
|
||||||
|
|
||||||
widget_set_resize_handler(color->parent_widget, resize_handler);
|
|
||||||
widget_set_use_cairo(color->widget, 0);
|
|
||||||
|
|
||||||
set_empty_input_region(color, color->widget);
|
|
||||||
set_single_pixel(color, color->widget);
|
|
||||||
|
|
||||||
if (color->unmanaged || set_image_description(color, color->widget))
|
|
||||||
display_run(color->display);
|
|
||||||
|
|
||||||
color_destroy(color);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,386 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright © 2018 Intel Corporation
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <cairo.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#include "weston-content-protection-client-protocol.h"
|
|
||||||
#include "window.h"
|
|
||||||
#include <wayland-client-protocol.h>
|
|
||||||
|
|
||||||
#define WIDTH 500
|
|
||||||
#define HEIGHT 400
|
|
||||||
#define FRAME_H 18
|
|
||||||
#define FRAME_W 5
|
|
||||||
#define BUTTON_WIDTH 65
|
|
||||||
#define BUTTON_HEIGHT 20
|
|
||||||
|
|
||||||
enum protection_mode {
|
|
||||||
RELAXED,
|
|
||||||
ENFORCED
|
|
||||||
};
|
|
||||||
|
|
||||||
struct protected_content_player {
|
|
||||||
struct weston_content_protection *protection;
|
|
||||||
struct weston_protected_surface *psurface;
|
|
||||||
struct display *display;
|
|
||||||
struct window *window;
|
|
||||||
struct widget *widget;
|
|
||||||
struct button_t *b0, *b1, *off, *enforced, *relaxed;
|
|
||||||
int width, height, x, y;
|
|
||||||
enum weston_protected_surface_type protection_type;
|
|
||||||
enum protection_mode mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct button_t {
|
|
||||||
struct window *window;
|
|
||||||
struct widget *widget;
|
|
||||||
struct protected_content_player *pc_player;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* An event to tell the client that there is a change in protection status
|
|
||||||
*
|
|
||||||
* This event is sent whenever there is a change in content
|
|
||||||
* protection. The content protection status can be ON or OFF. ON
|
|
||||||
* in case of the desired protection type is accepted on all
|
|
||||||
* connectors, and Off in case of any of the connector
|
|
||||||
* content-protection property is changed from "enabled"
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
handle_status_changed(void *data, struct weston_protected_surface *psurface,
|
|
||||||
uint32_t status)
|
|
||||||
{
|
|
||||||
struct protected_content_player *pc_player = data;
|
|
||||||
enum weston_protected_surface_type event_status = status;
|
|
||||||
|
|
||||||
switch (event_status) {
|
|
||||||
case WESTON_PROTECTED_SURFACE_TYPE_HDCP_0:
|
|
||||||
pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_HDCP_0;
|
|
||||||
break;
|
|
||||||
case WESTON_PROTECTED_SURFACE_TYPE_HDCP_1:
|
|
||||||
pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_HDCP_1;
|
|
||||||
break;
|
|
||||||
case WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED:
|
|
||||||
default:
|
|
||||||
pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED;
|
|
||||||
}
|
|
||||||
window_schedule_redraw(pc_player->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct weston_protected_surface_listener pc_player_listener = {
|
|
||||||
handle_status_changed,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_content(cairo_surface_t *surface, int x, int y, int width, int height,
|
|
||||||
enum weston_protected_surface_type type, enum protection_mode mode)
|
|
||||||
{
|
|
||||||
cairo_t *cr;
|
|
||||||
cairo_text_extents_t extents;
|
|
||||||
const char *content_text;
|
|
||||||
const char *mode_text;
|
|
||||||
|
|
||||||
cr = cairo_create(surface);
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_rectangle(cr, x, y, width, height);
|
|
||||||
if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_0)
|
|
||||||
cairo_set_source_rgba(cr, 0, 1.0, 0, 1.0);
|
|
||||||
else if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_1)
|
|
||||||
cairo_set_source_rgba(cr, 0, 0, 1.0, 1.0);
|
|
||||||
else
|
|
||||||
cairo_set_source_rgba(cr, 1.0, 0, 0, 1.0);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
|
|
||||||
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL,
|
|
||||||
CAIRO_FONT_WEIGHT_NORMAL);
|
|
||||||
cairo_set_font_size(cr, 15);
|
|
||||||
if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_0)
|
|
||||||
content_text = "Content-Type : Type-0";
|
|
||||||
else if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_1)
|
|
||||||
content_text = "Content-Type : Type-1";
|
|
||||||
else
|
|
||||||
content_text = "Content-Type : Unprotected";
|
|
||||||
cairo_text_extents(cr, content_text, &extents);
|
|
||||||
cairo_move_to(cr, width/2 - (extents.width/2),
|
|
||||||
height/2 - (extents.height/2));
|
|
||||||
cairo_show_text(cr, content_text);
|
|
||||||
|
|
||||||
if (mode == ENFORCED)
|
|
||||||
mode_text = "Mode : Enforced";
|
|
||||||
else
|
|
||||||
mode_text = "Mode : Relaxed";
|
|
||||||
cairo_text_extents(cr, mode_text, &extents);
|
|
||||||
cairo_move_to(cr, width / 2 - (extents.width / 2),
|
|
||||||
2 * height / 3 - (2 * extents.height / 3));
|
|
||||||
cairo_show_text(cr, mode_text);
|
|
||||||
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_destroy(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
redraw_handler(struct widget *widget, void *data)
|
|
||||||
{
|
|
||||||
struct protected_content_player *pc_player = data;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
struct rectangle rect;
|
|
||||||
|
|
||||||
widget_get_allocation(pc_player->widget, &rect);
|
|
||||||
surface = window_get_surface(pc_player->window);
|
|
||||||
if (surface == NULL ||
|
|
||||||
cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
|
|
||||||
fprintf(stderr, "failed to create cairo egl surface\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
draw_content(surface, rect.x, rect.y, rect.width, rect.height,
|
|
||||||
pc_player->protection_type, pc_player->mode);
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
resize_handler(struct widget *widget, int32_t width, int32_t height, void *data)
|
|
||||||
{
|
|
||||||
struct rectangle allocation;
|
|
||||||
struct protected_content_player *pc_player = data;
|
|
||||||
|
|
||||||
widget_get_allocation(pc_player->widget, &allocation);
|
|
||||||
widget_set_allocation(pc_player->b0->widget,
|
|
||||||
allocation.x + 20, allocation.y + 30,
|
|
||||||
BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
||||||
widget_set_allocation(pc_player->b1->widget,
|
|
||||||
allocation.x + 20 + BUTTON_WIDTH + 5,
|
|
||||||
allocation.y + 30,
|
|
||||||
BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
||||||
widget_set_allocation(pc_player->off->widget,
|
|
||||||
allocation.x + 20 + 2 * (BUTTON_WIDTH + 5),
|
|
||||||
allocation.y + 30,
|
|
||||||
BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
||||||
widget_set_allocation(pc_player->enforced->widget,
|
|
||||||
allocation.x + 20 + 3 * (BUTTON_WIDTH + 5),
|
|
||||||
allocation.y + 30,
|
|
||||||
BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
||||||
widget_set_allocation(pc_player->relaxed->widget,
|
|
||||||
allocation.x + 20 + 4 * (BUTTON_WIDTH + 5),
|
|
||||||
allocation.y + 30,
|
|
||||||
BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
buttons_handler(struct widget *widget, struct input *input, uint32_t time,
|
|
||||||
uint32_t button, enum wl_pointer_button_state state, void *data)
|
|
||||||
{
|
|
||||||
struct button_t *b = data;
|
|
||||||
struct protected_content_player *pc_player = b->pc_player;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
|
|
||||||
if (strcmp(b->name, "ENFORCED") == 0) {
|
|
||||||
weston_protected_surface_enforce(pc_player->psurface);
|
|
||||||
pc_player->mode = ENFORCED;
|
|
||||||
window_schedule_redraw(pc_player->window);
|
|
||||||
}
|
|
||||||
else if (strcmp(b->name, "RELAXED") == 0) {
|
|
||||||
weston_protected_surface_relax(pc_player->psurface);
|
|
||||||
pc_player->mode = RELAXED;
|
|
||||||
window_schedule_redraw(pc_player->window);
|
|
||||||
}
|
|
||||||
else if (strcmp(b->name, "TYPE-0") == 0)
|
|
||||||
weston_protected_surface_set_type(pc_player->psurface,
|
|
||||||
WESTON_PROTECTED_SURFACE_TYPE_HDCP_0);
|
|
||||||
else if (strcmp(b->name, "TYPE-1") == 0)
|
|
||||||
weston_protected_surface_set_type(pc_player->psurface,
|
|
||||||
WESTON_PROTECTED_SURFACE_TYPE_HDCP_1);
|
|
||||||
else
|
|
||||||
weston_protected_surface_set_type(pc_player->psurface,
|
|
||||||
WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED);
|
|
||||||
|
|
||||||
surface = window_get_wl_surface(pc_player->window);
|
|
||||||
wl_surface_commit(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_global(struct display *display, uint32_t name, const char *interface,
|
|
||||||
uint32_t version, void *data)
|
|
||||||
{
|
|
||||||
struct protected_content_player *pc_player = data;
|
|
||||||
|
|
||||||
if (strcmp(interface, "weston_content_protection") == 0) {
|
|
||||||
pc_player->protection = display_bind(display, name,
|
|
||||||
&weston_content_protection_interface,
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
buttons_redraw_handler(struct widget *widget, void *data)
|
|
||||||
{
|
|
||||||
struct button_t *b = data;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
struct rectangle allocation;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
surface = window_get_surface(b->window);
|
|
||||||
widget_get_allocation(b->widget, &allocation);
|
|
||||||
|
|
||||||
cr = cairo_create(surface);
|
|
||||||
cairo_rectangle(cr, allocation.x, allocation.y, allocation.width,
|
|
||||||
allocation.height);
|
|
||||||
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 1, 1, 1, 1);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
|
|
||||||
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL,
|
|
||||||
CAIRO_FONT_WEIGHT_NORMAL);
|
|
||||||
cairo_set_font_size(cr, 10);
|
|
||||||
cairo_move_to(cr, allocation.x + 5, allocation.y + 15);
|
|
||||||
cairo_show_text(cr, b->name);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_destroy(cr);
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct button_t*
|
|
||||||
create_button(struct protected_content_player *pc_player, const char *name)
|
|
||||||
{
|
|
||||||
struct button_t *b;
|
|
||||||
|
|
||||||
b = zalloc(sizeof(struct button_t));
|
|
||||||
if (b == NULL) {
|
|
||||||
fprintf(stderr, "Failed to allocate memory for button.\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
b->widget = widget_add_widget(pc_player->widget, b);
|
|
||||||
b->window = pc_player->window;
|
|
||||||
b->pc_player = pc_player;
|
|
||||||
b->name = name;
|
|
||||||
widget_set_redraw_handler(b->widget, buttons_redraw_handler);
|
|
||||||
widget_set_button_handler(b->widget, buttons_handler);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_button(struct button_t *b)
|
|
||||||
{
|
|
||||||
if (!b)
|
|
||||||
return;
|
|
||||||
widget_destroy(b->widget);
|
|
||||||
free(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_pc_player(struct protected_content_player *pc_player)
|
|
||||||
{
|
|
||||||
if (!pc_player)
|
|
||||||
return;
|
|
||||||
|
|
||||||
destroy_button(pc_player->b0);
|
|
||||||
destroy_button(pc_player->b1);
|
|
||||||
destroy_button(pc_player->off);
|
|
||||||
destroy_button(pc_player->enforced);
|
|
||||||
destroy_button(pc_player->relaxed);
|
|
||||||
widget_destroy(pc_player->widget);
|
|
||||||
window_destroy(pc_player->window);
|
|
||||||
free(pc_player);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct protected_content_player *pc_player;
|
|
||||||
struct display *d;
|
|
||||||
static const char str_type_0[] = "TYPE-0";
|
|
||||||
static const char str_type_1[] = "TYPE-1";
|
|
||||||
static const char str_type_off[] = "OFF";
|
|
||||||
static const char str_type_enforced[] = "ENFORCED";
|
|
||||||
static const char str_type_relaxed[] = "RELAXED";
|
|
||||||
struct wl_surface *surface;
|
|
||||||
|
|
||||||
pc_player = zalloc(sizeof(struct protected_content_player));
|
|
||||||
if (pc_player == NULL) {
|
|
||||||
fprintf(stderr, "failed to allocate memory: %m\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
d = display_create(&argc, argv);
|
|
||||||
if (d == NULL) {
|
|
||||||
fprintf(stderr, "failed to create display: %m\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED;
|
|
||||||
pc_player->mode = RELAXED;
|
|
||||||
pc_player->width = WIDTH * 2.0/4.0;
|
|
||||||
pc_player->height = HEIGHT * 2.0/4.0;
|
|
||||||
pc_player->x = WIDTH * 1.0/4.0;
|
|
||||||
pc_player->y = HEIGHT * 1.0/4.0;
|
|
||||||
pc_player->window = window_create(d);
|
|
||||||
pc_player->widget = window_frame_create(pc_player->window, pc_player);
|
|
||||||
pc_player->display = d;
|
|
||||||
display_set_user_data(d, pc_player);
|
|
||||||
|
|
||||||
display_set_global_handler(d, handle_global);
|
|
||||||
surface = window_get_wl_surface(pc_player->window);
|
|
||||||
if (pc_player->protection == NULL) {
|
|
||||||
printf("The content-protection object is NULL\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pc_player->psurface = weston_content_protection_get_protection(pc_player->protection,
|
|
||||||
surface);
|
|
||||||
weston_protected_surface_add_listener(pc_player->psurface,
|
|
||||||
&pc_player_listener,
|
|
||||||
pc_player);
|
|
||||||
|
|
||||||
pc_player->b0 = create_button(pc_player, str_type_0);
|
|
||||||
pc_player->b1 = create_button(pc_player, str_type_1);
|
|
||||||
pc_player->off = create_button(pc_player, str_type_off);
|
|
||||||
pc_player->enforced = create_button(pc_player, str_type_enforced);
|
|
||||||
pc_player->relaxed = create_button(pc_player, str_type_relaxed);
|
|
||||||
|
|
||||||
window_set_title(pc_player->window, "Weston Content Protection");
|
|
||||||
window_set_appid(pc_player->window,
|
|
||||||
"org.freedesktop.weston.weston-content-protection");
|
|
||||||
widget_set_redraw_handler(pc_player->widget, redraw_handler);
|
|
||||||
widget_set_resize_handler(pc_player->widget, resize_handler);
|
|
||||||
window_schedule_resize(pc_player->window, WIDTH, HEIGHT);
|
|
||||||
widget_schedule_redraw(pc_player->b0->widget);
|
|
||||||
widget_schedule_redraw(pc_player->b1->widget);
|
|
||||||
widget_schedule_redraw(pc_player->off->widget);
|
|
||||||
|
|
||||||
display_run(d);
|
|
||||||
weston_protected_surface_destroy(pc_player->psurface);
|
|
||||||
weston_content_protection_destroy(pc_player->protection);
|
|
||||||
free_pc_player(pc_player);
|
|
||||||
display_destroy(d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
210
clients/dnd.c
|
|
@ -1,24 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2010 Kristian Høgsberg
|
* Copyright © 2010 Kristian Høgsberg
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -35,15 +34,12 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "shared/cairo-util.h"
|
#include "../shared/cairo-util.h"
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
|
|
||||||
struct dnd_drag;
|
struct dnd_drag;
|
||||||
|
|
||||||
|
|
@ -74,7 +70,6 @@ struct dnd_drag {
|
||||||
struct item *item;
|
struct item *item;
|
||||||
int x_offset, y_offset;
|
int x_offset, y_offset;
|
||||||
int width, height;
|
int width, height;
|
||||||
uint32_t dnd_action;
|
|
||||||
const char *mime_type;
|
const char *mime_type;
|
||||||
|
|
||||||
struct wl_surface *drag_surface;
|
struct wl_surface *drag_surface;
|
||||||
|
|
@ -192,7 +187,7 @@ dnd_redraw_handler(struct widget *widget, void *data)
|
||||||
struct dnd *dnd = data;
|
struct dnd *dnd = data;
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
cairo_surface_t *surface, *item_surface;
|
cairo_surface_t *surface;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
surface = window_get_surface(dnd->window);
|
surface = window_get_surface(dnd->window);
|
||||||
|
|
@ -212,13 +207,7 @@ dnd_redraw_handler(struct widget *widget, void *data)
|
||||||
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
|
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
|
||||||
if (!dnd->items[i])
|
if (!dnd->items[i])
|
||||||
continue;
|
continue;
|
||||||
|
cairo_set_source_surface(cr, dnd->items[i]->surface,
|
||||||
if (dnd->current_drag && dnd->items[i] == dnd->current_drag->item)
|
|
||||||
item_surface = dnd->current_drag->translucent;
|
|
||||||
else
|
|
||||||
item_surface = dnd->items[i]->surface;
|
|
||||||
|
|
||||||
cairo_set_source_surface(cr, item_surface,
|
|
||||||
dnd->items[i]->x + allocation.x,
|
dnd->items[i]->x + allocation.x,
|
||||||
dnd->items[i]->y + allocation.y);
|
dnd->items[i]->y + allocation.y);
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
|
|
@ -274,38 +263,17 @@ dnd_get_item(struct dnd *dnd, int32_t x, int32_t y)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
lookup_dnd_cursor(uint32_t dnd_action)
|
|
||||||
{
|
|
||||||
if (dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
|
|
||||||
return CURSOR_DND_MOVE;
|
|
||||||
else if (dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
|
|
||||||
return CURSOR_DND_COPY;
|
|
||||||
|
|
||||||
return CURSOR_DND_FORBIDDEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dnd_drag_update_cursor(struct dnd_drag *dnd_drag)
|
data_source_target(void *data,
|
||||||
{
|
struct wl_data_source *source, const char *mime_type)
|
||||||
int cursor;
|
|
||||||
|
|
||||||
if (dnd_drag->mime_type == NULL)
|
|
||||||
cursor = CURSOR_DND_FORBIDDEN;
|
|
||||||
else
|
|
||||||
cursor = lookup_dnd_cursor(dnd_drag->dnd_action);
|
|
||||||
|
|
||||||
input_set_pointer_image(dnd_drag->input, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dnd_drag_update_surface(struct dnd_drag *dnd_drag)
|
|
||||||
{
|
{
|
||||||
|
struct dnd_drag *dnd_drag = data;
|
||||||
struct dnd *dnd = dnd_drag->dnd;
|
struct dnd *dnd = dnd_drag->dnd;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
|
|
||||||
if (dnd_drag->mime_type && dnd_drag->dnd_action)
|
dnd_drag->mime_type = mime_type;
|
||||||
|
if (mime_type)
|
||||||
surface = dnd_drag->opaque;
|
surface = dnd_drag->opaque;
|
||||||
else
|
else
|
||||||
surface = dnd_drag->translucent;
|
surface = dnd_drag->translucent;
|
||||||
|
|
@ -317,17 +285,6 @@ dnd_drag_update_surface(struct dnd_drag *dnd_drag)
|
||||||
wl_surface_commit(dnd_drag->drag_surface);
|
wl_surface_commit(dnd_drag->drag_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_target(void *data,
|
|
||||||
struct wl_data_source *source, const char *mime_type)
|
|
||||||
{
|
|
||||||
struct dnd_drag *dnd_drag = data;
|
|
||||||
|
|
||||||
dnd_drag->mime_type = mime_type;
|
|
||||||
dnd_drag_update_surface(dnd_drag);
|
|
||||||
dnd_drag_update_cursor(dnd_drag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
data_source_send(void *data, struct wl_data_source *source,
|
data_source_send(void *data, struct wl_data_source *source,
|
||||||
const char *mime_type, int32_t fd)
|
const char *mime_type, int32_t fd)
|
||||||
|
|
@ -359,27 +316,19 @@ data_source_send(void *data, struct wl_data_source *source,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dnd_drag_destroy(struct dnd_drag *dnd_drag, bool delete_item)
|
data_source_cancelled(void *data, struct wl_data_source *source)
|
||||||
{
|
{
|
||||||
struct dnd *dnd = dnd_drag->dnd;
|
struct dnd_drag *dnd_drag = data;
|
||||||
unsigned int i;
|
|
||||||
|
/* The 'cancelled' event means that the source is no longer in
|
||||||
|
* use by the drag (or current selection). We need to clean
|
||||||
|
* up the drag object created and the local state. */
|
||||||
|
|
||||||
wl_data_source_destroy(dnd_drag->data_source);
|
wl_data_source_destroy(dnd_drag->data_source);
|
||||||
|
|
||||||
if (delete_item) {
|
/* Destroy the item that has been dragged out */
|
||||||
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
|
cairo_surface_destroy(dnd_drag->item->surface);
|
||||||
if (dnd_drag->item == dnd->items[i]) {
|
free(dnd_drag->item);
|
||||||
dnd->items[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy the item that has been dragged out */
|
|
||||||
cairo_surface_destroy(dnd_drag->item->surface);
|
|
||||||
free(dnd_drag->item);
|
|
||||||
}
|
|
||||||
|
|
||||||
dnd->current_drag = NULL;
|
|
||||||
|
|
||||||
wl_surface_destroy(dnd_drag->drag_surface);
|
wl_surface_destroy(dnd_drag->drag_surface);
|
||||||
|
|
||||||
|
|
@ -388,58 +337,10 @@ dnd_drag_destroy(struct dnd_drag *dnd_drag, bool delete_item)
|
||||||
free(dnd_drag);
|
free(dnd_drag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_cancelled(void *data, struct wl_data_source *source)
|
|
||||||
{
|
|
||||||
struct dnd_drag *dnd_drag = data;
|
|
||||||
struct dnd *dnd = dnd_drag->dnd;
|
|
||||||
|
|
||||||
/* The 'cancelled' event means that the source is no longer in
|
|
||||||
* use by the drag (or current selection). We need to clean
|
|
||||||
* up the drag object created and the local state. */
|
|
||||||
dnd_drag_destroy(dnd_drag, false);
|
|
||||||
window_schedule_redraw(dnd->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_dnd_drop_performed(void *data, struct wl_data_source *source)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_dnd_finished(void *data, struct wl_data_source *source)
|
|
||||||
{
|
|
||||||
struct dnd_drag *dnd_drag = data;
|
|
||||||
struct dnd *dnd = dnd_drag->dnd;
|
|
||||||
bool delete_item;
|
|
||||||
|
|
||||||
delete_item =
|
|
||||||
dnd_drag->dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
|
||||||
|
|
||||||
/* The operation is already finished, we can destroy all
|
|
||||||
* related data.
|
|
||||||
*/
|
|
||||||
dnd_drag_destroy(dnd_drag, delete_item);
|
|
||||||
window_schedule_redraw(dnd->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_action(void *data, struct wl_data_source *source, uint32_t dnd_action)
|
|
||||||
{
|
|
||||||
struct dnd_drag *dnd_drag = data;
|
|
||||||
|
|
||||||
dnd_drag->dnd_action = dnd_action;
|
|
||||||
dnd_drag_update_surface(dnd_drag);
|
|
||||||
dnd_drag_update_cursor(dnd_drag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_data_source_listener data_source_listener = {
|
static const struct wl_data_source_listener data_source_listener = {
|
||||||
data_source_target,
|
data_source_target,
|
||||||
data_source_send,
|
data_source_send,
|
||||||
data_source_cancelled,
|
data_source_cancelled
|
||||||
data_source_dnd_drop_performed,
|
|
||||||
data_source_dnd_finished,
|
|
||||||
data_source_action,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static cairo_surface_t *
|
static cairo_surface_t *
|
||||||
|
|
@ -488,7 +389,6 @@ create_drag_source(struct dnd *dnd,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
cairo_surface_t *icon;
|
cairo_surface_t *icon;
|
||||||
uint32_t actions;
|
|
||||||
|
|
||||||
widget_get_allocation(dnd->widget, &allocation);
|
widget_get_allocation(dnd->widget, &allocation);
|
||||||
item = dnd_get_item(dnd, x, y);
|
item = dnd_get_item(dnd, x, y);
|
||||||
|
|
@ -503,11 +403,13 @@ create_drag_source(struct dnd *dnd,
|
||||||
dnd_drag->item = item;
|
dnd_drag->item = item;
|
||||||
dnd_drag->x_offset = x - item->x;
|
dnd_drag->x_offset = x - item->x;
|
||||||
dnd_drag->y_offset = y - item->y;
|
dnd_drag->y_offset = y - item->y;
|
||||||
dnd_drag->dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
|
||||||
dnd_drag->mime_type = NULL;
|
|
||||||
|
|
||||||
actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
|
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
|
||||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
if (item == dnd->items[i]){
|
||||||
|
dnd->items[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
display = window_get_display(dnd->window);
|
display = window_get_display(dnd->window);
|
||||||
compositor = display_get_compositor(display);
|
compositor = display_get_compositor(display);
|
||||||
|
|
@ -515,30 +417,11 @@ create_drag_source(struct dnd *dnd,
|
||||||
dnd_drag->drag_surface =
|
dnd_drag->drag_surface =
|
||||||
wl_compositor_create_surface(compositor);
|
wl_compositor_create_surface(compositor);
|
||||||
|
|
||||||
if (dnd->self_only || display_get_data_device_manager_version(display) <
|
|
||||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
|
||||||
/* Data sources version < 3 will not get action
|
|
||||||
* nor dnd_finished events, as we can't honor
|
|
||||||
* the "move" action at the time of finishing
|
|
||||||
* drag-and-drop, do it preemptively here.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) {
|
|
||||||
if (item == dnd->items[i]){
|
|
||||||
dnd->items[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dnd->self_only) {
|
if (dnd->self_only) {
|
||||||
dnd_drag->data_source = NULL;
|
dnd_drag->data_source = NULL;
|
||||||
} else {
|
} else {
|
||||||
dnd_drag->data_source =
|
dnd_drag->data_source =
|
||||||
display_create_data_source(dnd->display);
|
display_create_data_source(dnd->display);
|
||||||
if (!dnd_drag->data_source) {
|
|
||||||
fprintf(stderr, "No data device manager\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
wl_data_source_add_listener(dnd_drag->data_source,
|
wl_data_source_add_listener(dnd_drag->data_source,
|
||||||
&data_source_listener,
|
&data_source_listener,
|
||||||
dnd_drag);
|
dnd_drag);
|
||||||
|
|
@ -546,11 +429,6 @@ create_drag_source(struct dnd *dnd,
|
||||||
flower_mime_type);
|
flower_mime_type);
|
||||||
wl_data_source_offer(dnd_drag->data_source,
|
wl_data_source_offer(dnd_drag->data_source,
|
||||||
text_mime_type);
|
text_mime_type);
|
||||||
|
|
||||||
if (display_get_data_device_manager_version(display) >=
|
|
||||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
|
||||||
wl_data_source_set_actions(dnd_drag->data_source, actions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_data_device_start_drag(input_get_data_device(input),
|
wl_data_device_start_drag(input_get_data_device(input),
|
||||||
|
|
@ -662,6 +540,8 @@ dnd_enter_handler(struct widget *widget,
|
||||||
struct dnd *dnd = data;
|
struct dnd *dnd = data;
|
||||||
struct pointer *new_pointer = malloc(sizeof *new_pointer);
|
struct pointer *new_pointer = malloc(sizeof *new_pointer);
|
||||||
|
|
||||||
|
dnd->current_drag = NULL;
|
||||||
|
|
||||||
if (new_pointer) {
|
if (new_pointer) {
|
||||||
new_pointer->input = input;
|
new_pointer->input = input;
|
||||||
new_pointer->dragging = false;
|
new_pointer->dragging = false;
|
||||||
|
|
@ -772,6 +652,7 @@ dnd_drop_handler(struct window *window, struct input *input,
|
||||||
message.x_offset = dnd->current_drag->x_offset;
|
message.x_offset = dnd->current_drag->x_offset;
|
||||||
message.y_offset = dnd->current_drag->y_offset;
|
message.y_offset = dnd->current_drag->y_offset;
|
||||||
dnd_receive_func(&message, sizeof message, x, y, dnd);
|
dnd_receive_func(&message, sizeof message, x, y, dnd);
|
||||||
|
dnd->current_drag = NULL;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "ignoring drop from another client\n");
|
fprintf(stderr, "ignoring drop from another client\n");
|
||||||
}
|
}
|
||||||
|
|
@ -789,8 +670,6 @@ dnd_create(struct display *display)
|
||||||
dnd->window = window_create(display);
|
dnd->window = window_create(display);
|
||||||
dnd->widget = window_frame_create(dnd->window, dnd);
|
dnd->widget = window_frame_create(dnd->window, dnd);
|
||||||
window_set_title(dnd->window, "Wayland Drag and Drop Demo");
|
window_set_title(dnd->window, "Wayland Drag and Drop Demo");
|
||||||
window_set_appid(dnd->window,
|
|
||||||
"org.freedesktop.weston.wayland-drag-and-drop-demo");
|
|
||||||
|
|
||||||
dnd->display = display;
|
dnd->display = display;
|
||||||
dnd->key = 100;
|
dnd->key = 100;
|
||||||
|
|
@ -851,8 +730,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
327
clients/editor.c
|
|
@ -2,31 +2,28 @@
|
||||||
* Copyright © 2012 Openismus GmbH
|
* Copyright © 2012 Openismus GmbH
|
||||||
* Copyright © 2012 Intel Corporation
|
* Copyright © 2012 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
* to deal in the Software without restriction, including without limitation
|
* that the above copyright notice appear in all copies and that both that
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* copyright notice and this permission notice appear in supporting
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* Software.
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
*
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -38,18 +35,14 @@
|
||||||
|
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
|
||||||
#include <libweston/config-parser.h>
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "text-input-unstable-v1-client-protocol.h"
|
#include "text-client-protocol.h"
|
||||||
|
|
||||||
struct text_entry {
|
struct text_entry {
|
||||||
struct widget *widget;
|
struct widget *widget;
|
||||||
struct window *window;
|
struct window *window;
|
||||||
char *text;
|
char *text;
|
||||||
int active;
|
int active;
|
||||||
bool panel_visible;
|
|
||||||
uint32_t cursor;
|
uint32_t cursor;
|
||||||
uint32_t anchor;
|
uint32_t anchor;
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -69,7 +62,7 @@ struct text_entry {
|
||||||
uint32_t delete_length;
|
uint32_t delete_length;
|
||||||
bool invalid_delete;
|
bool invalid_delete;
|
||||||
} pending_commit;
|
} pending_commit;
|
||||||
struct zwp_text_input_v1 *text_input;
|
struct wl_text_input *text_input;
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
struct {
|
struct {
|
||||||
xkb_mod_mask_t shift_mask;
|
xkb_mod_mask_t shift_mask;
|
||||||
|
|
@ -77,13 +70,13 @@ struct text_entry {
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
uint32_t reset_serial;
|
uint32_t reset_serial;
|
||||||
uint32_t content_purpose;
|
uint32_t content_purpose;
|
||||||
bool click_to_show;
|
uint32_t click_to_show;
|
||||||
char *preferred_language;
|
char *preferred_language;
|
||||||
bool button_pressed;
|
bool button_pressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct editor {
|
struct editor {
|
||||||
struct zwp_text_input_manager_v1 *text_input_manager;
|
struct wl_text_input_manager *text_input_manager;
|
||||||
struct wl_data_source *selection;
|
struct wl_data_source *selection;
|
||||||
char *selected_text;
|
char *selected_text;
|
||||||
struct display *display;
|
struct display *display;
|
||||||
|
|
@ -187,7 +180,7 @@ static void text_entry_update(struct text_entry *entry);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_commit_string(void *data,
|
text_input_commit_string(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
const char *text)
|
const char *text)
|
||||||
{
|
{
|
||||||
|
|
@ -239,7 +232,7 @@ clear_pending_preedit(struct text_entry *entry)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_preedit_string(void *data,
|
text_input_preedit_string(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
const char *text,
|
const char *text,
|
||||||
const char *commit)
|
const char *commit)
|
||||||
|
|
@ -280,7 +273,7 @@ text_input_preedit_string(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_delete_surrounding_text(void *data,
|
text_input_delete_surrounding_text(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
int32_t index,
|
int32_t index,
|
||||||
uint32_t length)
|
uint32_t length)
|
||||||
{
|
{
|
||||||
|
|
@ -305,7 +298,7 @@ text_input_delete_surrounding_text(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_cursor_position(void *data,
|
text_input_cursor_position(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
int32_t index,
|
int32_t index,
|
||||||
int32_t anchor)
|
int32_t anchor)
|
||||||
{
|
{
|
||||||
|
|
@ -317,7 +310,7 @@ text_input_cursor_position(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_preedit_styling(void *data,
|
text_input_preedit_styling(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
uint32_t length,
|
uint32_t length,
|
||||||
uint32_t style)
|
uint32_t style)
|
||||||
|
|
@ -330,24 +323,24 @@ text_input_preedit_styling(void *data,
|
||||||
entry->preedit_info.attr_list = pango_attr_list_new();
|
entry->preedit_info.attr_list = pango_attr_list_new();
|
||||||
|
|
||||||
switch (style) {
|
switch (style) {
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_DEFAULT:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_UNDERLINE:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
|
||||||
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
||||||
break;
|
break;
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INCORRECT:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
|
||||||
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_ERROR);
|
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_ERROR);
|
||||||
attr2 = pango_attr_underline_color_new(65535, 0, 0);
|
attr2 = pango_attr_underline_color_new(65535, 0, 0);
|
||||||
break;
|
break;
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_SELECTION:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
|
||||||
attr1 = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535);
|
attr1 = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535);
|
||||||
attr2 = pango_attr_foreground_new(65535, 65535, 65535);
|
attr2 = pango_attr_foreground_new(65535, 65535, 65535);
|
||||||
break;
|
break;
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ACTIVE:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
|
||||||
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
||||||
attr2 = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
|
attr2 = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
|
||||||
break;
|
break;
|
||||||
case ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INACTIVE:
|
case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
|
||||||
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
||||||
attr2 = pango_attr_foreground_new(0.3 * 65535, 0.3 * 65535, 0.3 * 65535);
|
attr2 = pango_attr_foreground_new(0.3 * 65535, 0.3 * 65535, 0.3 * 65535);
|
||||||
break;
|
break;
|
||||||
|
|
@ -368,7 +361,7 @@ text_input_preedit_styling(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_preedit_cursor(void *data,
|
text_input_preedit_cursor(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
int32_t index)
|
int32_t index)
|
||||||
{
|
{
|
||||||
struct text_entry *entry = data;
|
struct text_entry *entry = data;
|
||||||
|
|
@ -378,7 +371,7 @@ text_input_preedit_cursor(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_modifiers_map(void *data,
|
text_input_modifiers_map(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
struct wl_array *map)
|
struct wl_array *map)
|
||||||
{
|
{
|
||||||
struct text_entry *entry = data;
|
struct text_entry *entry = data;
|
||||||
|
|
@ -388,7 +381,7 @@ text_input_modifiers_map(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_keysym(void *data,
|
text_input_keysym(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
uint32_t time,
|
uint32_t time,
|
||||||
uint32_t key,
|
uint32_t key,
|
||||||
|
|
@ -475,7 +468,7 @@ text_input_keysym(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_enter(void *data,
|
text_input_enter(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
struct wl_surface *surface)
|
struct wl_surface *surface)
|
||||||
{
|
{
|
||||||
struct text_entry *entry = data;
|
struct text_entry *entry = data;
|
||||||
|
|
@ -493,31 +486,29 @@ text_input_enter(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_leave(void *data,
|
text_input_leave(void *data,
|
||||||
struct zwp_text_input_v1 *text_input)
|
struct wl_text_input *text_input)
|
||||||
{
|
{
|
||||||
struct text_entry *entry = data;
|
struct text_entry *entry = data;
|
||||||
|
|
||||||
text_entry_commit_and_reset(entry);
|
text_entry_commit_and_reset(entry);
|
||||||
entry->active--;
|
entry->active--;
|
||||||
|
|
||||||
if (!entry->active) {
|
if (!entry->active)
|
||||||
zwp_text_input_v1_hide_input_panel(text_input);
|
wl_text_input_hide_input_panel(text_input);
|
||||||
entry->panel_visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
widget_schedule_redraw(entry->widget);
|
widget_schedule_redraw(entry->widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_input_panel_state(void *data,
|
text_input_input_panel_state(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_language(void *data,
|
text_input_language(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
const char *language)
|
const char *language)
|
||||||
{
|
{
|
||||||
|
|
@ -526,7 +517,7 @@ text_input_language(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_input_text_direction(void *data,
|
text_input_text_direction(void *data,
|
||||||
struct zwp_text_input_v1 *text_input,
|
struct wl_text_input *text_input,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
uint32_t direction)
|
uint32_t direction)
|
||||||
{
|
{
|
||||||
|
|
@ -536,13 +527,13 @@ text_input_text_direction(void *data,
|
||||||
|
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR:
|
case WL_TEXT_INPUT_TEXT_DIRECTION_LTR:
|
||||||
pango_direction = PANGO_DIRECTION_LTR;
|
pango_direction = PANGO_DIRECTION_LTR;
|
||||||
break;
|
break;
|
||||||
case ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL:
|
case WL_TEXT_INPUT_TEXT_DIRECTION_RTL:
|
||||||
pango_direction = PANGO_DIRECTION_RTL;
|
pango_direction = PANGO_DIRECTION_RTL;
|
||||||
break;
|
break;
|
||||||
case ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_AUTO:
|
case WL_TEXT_INPUT_TEXT_DIRECTION_AUTO:
|
||||||
default:
|
default:
|
||||||
pango_direction = PANGO_DIRECTION_NEUTRAL;
|
pango_direction = PANGO_DIRECTION_NEUTRAL;
|
||||||
}
|
}
|
||||||
|
|
@ -550,7 +541,7 @@ text_input_text_direction(void *data,
|
||||||
pango_context_set_base_dir(context, pango_direction);
|
pango_context_set_base_dir(context, pango_direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_text_input_v1_listener text_input_listener = {
|
static const struct wl_text_input_listener text_input_listener = {
|
||||||
text_input_enter,
|
text_input_enter,
|
||||||
text_input_leave,
|
text_input_leave,
|
||||||
text_input_modifiers_map,
|
text_input_modifiers_map,
|
||||||
|
|
@ -579,10 +570,7 @@ data_source_send(void *data,
|
||||||
{
|
{
|
||||||
struct editor *editor = data;
|
struct editor *editor = data;
|
||||||
|
|
||||||
if (write(fd, editor->selected_text, strlen(editor->selected_text) + 1) < 0)
|
write(fd, editor->selected_text, strlen(editor->selected_text) + 1);
|
||||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -639,9 +627,6 @@ editor_copy_cut(struct editor *editor, struct input *input, bool cut)
|
||||||
|
|
||||||
editor->selection =
|
editor->selection =
|
||||||
display_create_data_source(editor->display);
|
display_create_data_source(editor->display);
|
||||||
if (!editor->selection)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wl_data_source_offer(editor->selection,
|
wl_data_source_offer(editor->selection,
|
||||||
"text/plain;charset=utf-8");
|
"text/plain;charset=utf-8");
|
||||||
wl_data_source_add_listener(editor->selection,
|
wl_data_source_add_listener(editor->selection,
|
||||||
|
|
@ -699,19 +684,17 @@ text_entry_create(struct editor *editor, const char *text)
|
||||||
{
|
{
|
||||||
struct text_entry *entry;
|
struct text_entry *entry;
|
||||||
|
|
||||||
entry = xzalloc(sizeof *entry);
|
entry = xmalloc(sizeof *entry);
|
||||||
|
memset(entry, 0, sizeof *entry);
|
||||||
|
|
||||||
entry->widget = widget_add_widget(editor->widget, entry);
|
entry->widget = widget_add_widget(editor->widget, entry);
|
||||||
entry->window = editor->window;
|
entry->window = editor->window;
|
||||||
entry->text = strdup(text);
|
entry->text = strdup(text);
|
||||||
entry->active = 0;
|
entry->active = 0;
|
||||||
entry->panel_visible = false;
|
|
||||||
entry->cursor = strlen(text);
|
entry->cursor = strlen(text);
|
||||||
entry->anchor = entry->cursor;
|
entry->anchor = entry->cursor;
|
||||||
entry->text_input =
|
entry->text_input = wl_text_input_manager_create_text_input(editor->text_input_manager);
|
||||||
zwp_text_input_manager_v1_create_text_input(editor->text_input_manager);
|
wl_text_input_add_listener(entry->text_input, &text_input_listener, entry);
|
||||||
zwp_text_input_v1_add_listener(entry->text_input,
|
|
||||||
&text_input_listener, entry);
|
|
||||||
|
|
||||||
widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
|
widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
|
||||||
widget_set_button_handler(entry->widget, text_entry_button_handler);
|
widget_set_button_handler(entry->widget, text_entry_button_handler);
|
||||||
|
|
@ -725,10 +708,9 @@ static void
|
||||||
text_entry_destroy(struct text_entry *entry)
|
text_entry_destroy(struct text_entry *entry)
|
||||||
{
|
{
|
||||||
widget_destroy(entry->widget);
|
widget_destroy(entry->widget);
|
||||||
zwp_text_input_v1_destroy(entry->text_input);
|
wl_text_input_destroy(entry->text_input);
|
||||||
g_clear_object(&entry->layout);
|
g_clear_object(&entry->layout);
|
||||||
free(entry->text);
|
free(entry->text);
|
||||||
free(entry->preferred_language);
|
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -794,30 +776,25 @@ text_entry_activate(struct text_entry *entry,
|
||||||
struct wl_surface *surface = window_get_wl_surface(entry->window);
|
struct wl_surface *surface = window_get_wl_surface(entry->window);
|
||||||
|
|
||||||
if (entry->click_to_show && entry->active) {
|
if (entry->click_to_show && entry->active) {
|
||||||
entry->panel_visible = !entry->panel_visible;
|
wl_text_input_show_input_panel(entry->text_input);
|
||||||
|
|
||||||
if (entry->panel_visible)
|
|
||||||
zwp_text_input_v1_show_input_panel(entry->text_input);
|
|
||||||
else
|
|
||||||
zwp_text_input_v1_hide_input_panel(entry->text_input);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry->click_to_show)
|
if (!entry->click_to_show)
|
||||||
zwp_text_input_v1_show_input_panel(entry->text_input);
|
wl_text_input_show_input_panel(entry->text_input);
|
||||||
|
|
||||||
zwp_text_input_v1_activate(entry->text_input,
|
wl_text_input_activate(entry->text_input,
|
||||||
seat,
|
seat,
|
||||||
surface);
|
surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
text_entry_deactivate(struct text_entry *entry,
|
text_entry_deactivate(struct text_entry *entry,
|
||||||
struct wl_seat *seat)
|
struct wl_seat *seat)
|
||||||
{
|
{
|
||||||
zwp_text_input_v1_deactivate(entry->text_input,
|
wl_text_input_deactivate(entry->text_input,
|
||||||
seat);
|
seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -888,27 +865,24 @@ text_entry_update(struct text_entry *entry)
|
||||||
{
|
{
|
||||||
struct rectangle cursor_rectangle;
|
struct rectangle cursor_rectangle;
|
||||||
|
|
||||||
zwp_text_input_v1_set_content_type(entry->text_input,
|
wl_text_input_set_content_type(entry->text_input,
|
||||||
ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE,
|
WL_TEXT_INPUT_CONTENT_HINT_NONE,
|
||||||
entry->content_purpose);
|
entry->content_purpose);
|
||||||
|
|
||||||
zwp_text_input_v1_set_surrounding_text(entry->text_input,
|
wl_text_input_set_surrounding_text(entry->text_input,
|
||||||
entry->text,
|
entry->text,
|
||||||
entry->cursor,
|
entry->cursor,
|
||||||
entry->anchor);
|
entry->anchor);
|
||||||
|
|
||||||
if (entry->preferred_language)
|
if (entry->preferred_language)
|
||||||
zwp_text_input_v1_set_preferred_language(entry->text_input,
|
wl_text_input_set_preferred_language(entry->text_input,
|
||||||
entry->preferred_language);
|
entry->preferred_language);
|
||||||
|
|
||||||
text_entry_get_cursor_rectangle(entry, &cursor_rectangle);
|
text_entry_get_cursor_rectangle(entry, &cursor_rectangle);
|
||||||
zwp_text_input_v1_set_cursor_rectangle(entry->text_input,
|
wl_text_input_set_cursor_rectangle(entry->text_input, cursor_rectangle.x, cursor_rectangle.y,
|
||||||
cursor_rectangle.x,
|
cursor_rectangle.width, cursor_rectangle.height);
|
||||||
cursor_rectangle.y,
|
|
||||||
cursor_rectangle.width,
|
|
||||||
cursor_rectangle.height);
|
|
||||||
|
|
||||||
zwp_text_input_v1_commit_state(entry->text_input, ++entry->serial);
|
wl_text_input_commit_state(entry->text_input, ++entry->serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -970,7 +944,7 @@ text_entry_commit_and_reset(struct text_entry *entry)
|
||||||
free(commit);
|
free(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
zwp_text_input_v1_reset(entry->text_input);
|
wl_text_input_reset(entry->text_input);
|
||||||
text_entry_update(entry);
|
text_entry_update(entry);
|
||||||
entry->reset_serial = entry->serial;
|
entry->reset_serial = entry->serial;
|
||||||
}
|
}
|
||||||
|
|
@ -1019,9 +993,9 @@ text_entry_try_invoke_preedit_action(struct text_entry *entry,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == WL_POINTER_BUTTON_STATE_RELEASED)
|
if (state == WL_POINTER_BUTTON_STATE_RELEASED)
|
||||||
zwp_text_input_v1_invoke_action(entry->text_input,
|
wl_text_input_invoke_action(entry->text_input,
|
||||||
button,
|
button,
|
||||||
cursor - entry->cursor);
|
cursor - entry->cursor);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1496,132 +1470,46 @@ global_handler(struct display *display, uint32_t name,
|
||||||
{
|
{
|
||||||
struct editor *editor = data;
|
struct editor *editor = data;
|
||||||
|
|
||||||
if (!strcmp(interface, "zwp_text_input_manager_v1")) {
|
if (!strcmp(interface, "wl_text_input_manager")) {
|
||||||
editor->text_input_manager =
|
editor->text_input_manager =
|
||||||
display_bind(display, name,
|
display_bind(display, name,
|
||||||
&zwp_text_input_manager_v1_interface, 1);
|
&wl_text_input_manager_interface, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Display help for command line options, and exit */
|
|
||||||
static bool opt_help = false;
|
|
||||||
|
|
||||||
/** Require a distinct click to show the input panel (virtual keyboard) */
|
|
||||||
static bool opt_click_to_show = false;
|
|
||||||
|
|
||||||
/** Set a specific (RFC-3066) language. Used for the virtual keyboard, etc. */
|
|
||||||
static const char *opt_preferred_language = NULL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief command line options for editor
|
|
||||||
*/
|
|
||||||
static const struct weston_option editor_options[] = {
|
|
||||||
{ WESTON_OPTION_BOOLEAN, "help", 'h', &opt_help },
|
|
||||||
{ WESTON_OPTION_BOOLEAN, "click-to-show", 'C', &opt_click_to_show },
|
|
||||||
{ WESTON_OPTION_STRING, "preferred-language", 'L', &opt_preferred_language },
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(const char *program_name, int exit_code)
|
|
||||||
{
|
|
||||||
unsigned k;
|
|
||||||
|
|
||||||
fprintf(stderr, "Usage: %s [OPTIONS] [FILENAME]\n\n", program_name);
|
|
||||||
for (k = 0; k < ARRAY_LENGTH(editor_options); k++) {
|
|
||||||
const struct weston_option *p = &editor_options[k];
|
|
||||||
if (p->name) {
|
|
||||||
fprintf(stderr, " --%s", p->name);
|
|
||||||
if (p->type != WESTON_OPTION_BOOLEAN)
|
|
||||||
fprintf(stderr, "=VALUE");
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
if (p->short_name) {
|
|
||||||
fprintf(stderr, " -%c", p->short_name);
|
|
||||||
if (p->type != WESTON_OPTION_BOOLEAN)
|
|
||||||
fprintf(stderr, "VALUE");
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit(exit_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the contents of a file into a UTF-8 text buffer and return it.
|
|
||||||
*
|
|
||||||
* Caller is responsible for freeing the buffer when done.
|
|
||||||
* On error, returns NULL.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
read_file(char *filename)
|
|
||||||
{
|
|
||||||
char *buffer = NULL;
|
|
||||||
int buf_size, read_size;
|
|
||||||
FILE *fin;
|
|
||||||
int errsv;
|
|
||||||
|
|
||||||
fin = fopen(filename, "r");
|
|
||||||
if (fin == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Determine required buffer size */
|
|
||||||
if (fseek(fin, 0, SEEK_END) != 0)
|
|
||||||
goto error;
|
|
||||||
buf_size = ftell(fin);
|
|
||||||
if (buf_size < 0)
|
|
||||||
goto error;
|
|
||||||
rewind(fin);
|
|
||||||
|
|
||||||
/* Create buffer and read in the text */
|
|
||||||
buffer = (char*) malloc(sizeof(char) * (buf_size + 1));
|
|
||||||
if (buffer == NULL)
|
|
||||||
goto error;
|
|
||||||
read_size = fread(buffer, sizeof(char), buf_size, fin);
|
|
||||||
fclose(fin);
|
|
||||||
if (buf_size != read_size)
|
|
||||||
goto error;
|
|
||||||
buffer[buf_size] = '\0';
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
error:
|
|
||||||
errsv = errno;
|
|
||||||
if (fin)
|
|
||||||
fclose(fin);
|
|
||||||
free(buffer);
|
|
||||||
errno = errsv ? errsv : EINVAL;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct editor editor;
|
struct editor editor;
|
||||||
char *text_buffer = NULL;
|
int i;
|
||||||
|
uint32_t click_to_show = 0;
|
||||||
|
const char *preferred_language = NULL;
|
||||||
|
|
||||||
parse_options(editor_options, ARRAY_LENGTH(editor_options),
|
for (i = 1; i < argc; i++) {
|
||||||
&argc, argv);
|
if (strcmp("--click-to-show", argv[i]) == 0)
|
||||||
if (opt_help)
|
click_to_show = 1;
|
||||||
usage(argv[0], EXIT_SUCCESS);
|
else if (strcmp("--preferred-language", argv[i]) == 0 &&
|
||||||
|
i + 1 < argc) {
|
||||||
if (argc > 1) {
|
preferred_language = argv[i + 1];
|
||||||
if (argv[1][0] == '-')
|
i++;
|
||||||
usage(argv[0], EXIT_FAILURE);
|
} else {
|
||||||
|
printf("Usage: %s [OPTIONS]\n"
|
||||||
text_buffer = read_file(argv[1]);
|
" --click-to-show\n"
|
||||||
if (text_buffer == NULL) {
|
" --preferred-language LANGUAGE\n",
|
||||||
fprintf(stderr, "could not read file '%s': %s\n",
|
argv[0]);
|
||||||
argv[1], strerror(errno));
|
return 1;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&editor, 0, sizeof editor);
|
memset(&editor, 0, sizeof editor);
|
||||||
|
|
||||||
|
#ifdef HAVE_PANGO
|
||||||
|
g_type_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
editor.display = display_create(&argc, argv);
|
editor.display = display_create(&argc, argv);
|
||||||
if (editor.display == NULL) {
|
if (editor.display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
free(text_buffer);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1630,29 +1518,23 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
if (editor.text_input_manager == NULL) {
|
if (editor.text_input_manager == NULL) {
|
||||||
fprintf(stderr, "No text input manager global\n");
|
fprintf(stderr, "No text input manager global\n");
|
||||||
display_destroy(editor.display);
|
|
||||||
free(text_buffer);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.window = window_create(editor.display);
|
editor.window = window_create(editor.display);
|
||||||
editor.widget = window_frame_create(editor.window, &editor);
|
editor.widget = window_frame_create(editor.window, &editor);
|
||||||
|
|
||||||
if (text_buffer)
|
editor.entry = text_entry_create(&editor, "Entry");
|
||||||
editor.entry = text_entry_create(&editor, text_buffer);
|
editor.entry->click_to_show = click_to_show;
|
||||||
else
|
if (preferred_language)
|
||||||
editor.entry = text_entry_create(&editor, "Entry");
|
editor.entry->preferred_language = strdup(preferred_language);
|
||||||
editor.entry->click_to_show = opt_click_to_show;
|
|
||||||
if (opt_preferred_language)
|
|
||||||
editor.entry->preferred_language = strdup(opt_preferred_language);
|
|
||||||
editor.editor = text_entry_create(&editor, "Numeric");
|
editor.editor = text_entry_create(&editor, "Numeric");
|
||||||
editor.editor->content_purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER;
|
editor.editor->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
|
||||||
editor.editor->click_to_show = opt_click_to_show;
|
editor.editor->click_to_show = click_to_show;
|
||||||
editor.selection = NULL;
|
editor.selection = NULL;
|
||||||
editor.selected_text = NULL;
|
editor.selected_text = NULL;
|
||||||
|
|
||||||
window_set_title(editor.window, "Text Editor");
|
window_set_title(editor.window, "Text Editor");
|
||||||
window_set_appid(editor.window, "org.freedesktop.weston.text-editor");
|
|
||||||
window_set_key_handler(editor.window, key_handler);
|
window_set_key_handler(editor.window, key_handler);
|
||||||
window_set_keyboard_focus_handler(editor.window,
|
window_set_keyboard_focus_handler(editor.window,
|
||||||
keyboard_focus_handler);
|
keyboard_focus_handler);
|
||||||
|
|
@ -1676,7 +1558,6 @@ main(int argc, char *argv[])
|
||||||
widget_destroy(editor.widget);
|
widget_destroy(editor.widget);
|
||||||
window_destroy(editor.window);
|
window_destroy(editor.window);
|
||||||
display_destroy(editor.display);
|
display_destroy(editor.display);
|
||||||
free(text_buffer);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2011 Tim Wiederhake
|
* Copyright © 2011 Tim Wiederhake
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -33,21 +32,15 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
/** window title */
|
/** window title */
|
||||||
static char *title = "EventDemo";
|
static char *title = "EventDemo";
|
||||||
static char *appid = "org.freedesktop.weston.eventdemo";
|
|
||||||
|
|
||||||
/** window width */
|
/** window width */
|
||||||
static int width = 500;
|
static int width = 500;
|
||||||
|
|
@ -56,7 +49,7 @@ static int width = 500;
|
||||||
static int height = 400;
|
static int height = 400;
|
||||||
|
|
||||||
/** set if window has no borders */
|
/** set if window has no borders */
|
||||||
static bool noborder = false;
|
static int noborder = 0;
|
||||||
|
|
||||||
/** if non-zero, maximum window width */
|
/** if non-zero, maximum window width */
|
||||||
static int width_max = 0;
|
static int width_max = 0;
|
||||||
|
|
@ -65,25 +58,25 @@ static int width_max = 0;
|
||||||
static int height_max = 0;
|
static int height_max = 0;
|
||||||
|
|
||||||
/** set to log redrawing */
|
/** set to log redrawing */
|
||||||
static bool log_redraw = false;
|
static int log_redraw = 0;
|
||||||
|
|
||||||
/** set to log resizing */
|
/** set to log resizing */
|
||||||
static bool log_resize = false;
|
static int log_resize = 0;
|
||||||
|
|
||||||
/** set to log keyboard focus */
|
/** set to log keyboard focus */
|
||||||
static bool log_focus = false;
|
static int log_focus = 0;
|
||||||
|
|
||||||
/** set to log key events */
|
/** set to log key events */
|
||||||
static bool log_key = false;
|
static int log_key = 0;
|
||||||
|
|
||||||
/** set to log button events */
|
/** set to log button events */
|
||||||
static bool log_button = false;
|
static int log_button = 0;
|
||||||
|
|
||||||
/** set to log axis events */
|
/** set to log axis events */
|
||||||
static bool log_axis = false;
|
static int log_axis = 0;
|
||||||
|
|
||||||
/** set to log motion events */
|
/** set to log motion events */
|
||||||
static bool log_motion = false;
|
static int log_motion = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \struct eventdemo
|
* \struct eventdemo
|
||||||
|
|
@ -98,8 +91,6 @@ struct eventdemo {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
|
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
|
|
||||||
bool print_pointer_frame;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -179,8 +170,8 @@ keyboard_focus_handler(struct window *window,
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
struct eventdemo *e = data;
|
struct eventdemo *e = data;
|
||||||
|
|
||||||
if (log_focus) {
|
if(log_focus) {
|
||||||
if (device) {
|
if(device) {
|
||||||
input_get_position(device, &x, &y);
|
input_get_position(device, &x, &y);
|
||||||
printf("focus x: %d, y: %d\n", x, y);
|
printf("focus x: %d, y: %d\n", x, y);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -194,11 +185,10 @@ keyboard_focus_handler(struct window *window,
|
||||||
/**
|
/**
|
||||||
* \brief CALLBACK function, Wayland informs about key event
|
* \brief CALLBACK function, Wayland informs about key event
|
||||||
* \param window window
|
* \param window window
|
||||||
* \param input input
|
|
||||||
* \param time time
|
|
||||||
* \param key keycode
|
* \param key keycode
|
||||||
* \param unicode associated character
|
* \param unicode associated character
|
||||||
* \param state pressed or released
|
* \param state pressed or released
|
||||||
|
* \param modifiers modifiers: ctrl, alt, meta etc.
|
||||||
* \param data user data associated to the window
|
* \param data user data associated to the window
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
|
|
@ -208,10 +198,10 @@ key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
{
|
{
|
||||||
uint32_t modifiers = input_get_modifiers(input);
|
uint32_t modifiers = input_get_modifiers(input);
|
||||||
|
|
||||||
if (!log_key)
|
if(!log_key)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("key key: %u, unicode: %u, state: %s, modifiers: 0x%x\n",
|
printf("key key: %d, unicode: %d, state: %s, modifiers: 0x%x\n",
|
||||||
key, unicode,
|
key, unicode,
|
||||||
(state == WL_KEYBOARD_KEY_STATE_PRESSED) ? "pressed" :
|
(state == WL_KEYBOARD_KEY_STATE_PRESSED) ? "pressed" :
|
||||||
"released",
|
"released",
|
||||||
|
|
@ -231,16 +221,13 @@ static void
|
||||||
button_handler(struct widget *widget, struct input *input, uint32_t time,
|
button_handler(struct widget *widget, struct input *input, uint32_t time,
|
||||||
uint32_t button, enum wl_pointer_button_state state, void *data)
|
uint32_t button, enum wl_pointer_button_state state, void *data)
|
||||||
{
|
{
|
||||||
struct eventdemo *e = data;
|
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
|
|
||||||
if (!log_button)
|
if (!log_button)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
e->print_pointer_frame = true;
|
|
||||||
|
|
||||||
input_get_position(input, &x, &y);
|
input_get_position(input, &x, &y);
|
||||||
printf("button time: %u, button: %u, state: %s, x: %d, y: %d\n",
|
printf("button time: %d, button: %d, state: %s, x: %d, y: %d\n",
|
||||||
time, button,
|
time, button,
|
||||||
(state == WL_POINTER_BUTTON_STATE_PRESSED) ? "pressed" :
|
(state == WL_POINTER_BUTTON_STATE_PRESSED) ? "pressed" :
|
||||||
"released",
|
"released",
|
||||||
|
|
@ -260,99 +247,25 @@ static void
|
||||||
axis_handler(struct widget *widget, struct input *input, uint32_t time,
|
axis_handler(struct widget *widget, struct input *input, uint32_t time,
|
||||||
uint32_t axis, wl_fixed_t value, void *data)
|
uint32_t axis, wl_fixed_t value, void *data)
|
||||||
{
|
{
|
||||||
struct eventdemo *e = data;
|
|
||||||
|
|
||||||
if (!log_axis)
|
if (!log_axis)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
e->print_pointer_frame = true;
|
printf("axis time: %d, axis: %s, value: %f\n",
|
||||||
|
|
||||||
printf("axis time: %u, axis: %s, value: %f\n",
|
|
||||||
time,
|
time,
|
||||||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" :
|
axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" :
|
||||||
"horizontal",
|
"horizontal",
|
||||||
wl_fixed_to_double(value));
|
wl_fixed_to_double(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pointer_frame_handler(struct widget *widget, struct input *input, void *data)
|
|
||||||
{
|
|
||||||
struct eventdemo *e = data;
|
|
||||||
|
|
||||||
if (!e->print_pointer_frame)
|
|
||||||
return;
|
|
||||||
|
|
||||||
printf("pointer frame\n");
|
|
||||||
e->print_pointer_frame = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
axis_source_handler(struct widget *widget, struct input *input,
|
|
||||||
uint32_t source, void *data)
|
|
||||||
{
|
|
||||||
const char *axis_source;
|
|
||||||
struct eventdemo *e = data;
|
|
||||||
|
|
||||||
if (!log_axis)
|
|
||||||
return;
|
|
||||||
|
|
||||||
e->print_pointer_frame = true;
|
|
||||||
|
|
||||||
switch (source) {
|
|
||||||
case WL_POINTER_AXIS_SOURCE_WHEEL:
|
|
||||||
axis_source = "wheel";
|
|
||||||
break;
|
|
||||||
case WL_POINTER_AXIS_SOURCE_FINGER:
|
|
||||||
axis_source = "finger";
|
|
||||||
break;
|
|
||||||
case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
|
|
||||||
axis_source = "continuous";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
axis_source = "<invalid source value>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("axis source: %s\n", axis_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
axis_stop_handler(struct widget *widget, struct input *input,
|
|
||||||
uint32_t time, uint32_t axis,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct eventdemo *e = data;
|
|
||||||
|
|
||||||
if (!log_axis)
|
|
||||||
return;
|
|
||||||
|
|
||||||
e->print_pointer_frame = true;
|
|
||||||
printf("axis stop time: %u, axis: %s\n",
|
|
||||||
time,
|
|
||||||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" :
|
|
||||||
"horizontal");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
axis_discrete_handler(struct widget *widget, struct input *input,
|
|
||||||
uint32_t axis, int32_t discrete, void *data)
|
|
||||||
{
|
|
||||||
struct eventdemo *e = data;
|
|
||||||
|
|
||||||
if (!log_axis)
|
|
||||||
return;
|
|
||||||
|
|
||||||
e->print_pointer_frame = true;
|
|
||||||
printf("axis discrete axis: %u value: %d\n", axis, discrete);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief CALLBACK function, Waylands informs about pointer motion
|
* \brief CALLBACK function, Waylands informs about pointer motion
|
||||||
* \param widget widget
|
* \param widget widget
|
||||||
* \param input input device that caused the motion event
|
* \param input input device that caused the motion event
|
||||||
* \param time time the event happened
|
* \param time time the event happened
|
||||||
* \param x x position relative to the window
|
* \param x absolute x position
|
||||||
* \param y y position relative to the window
|
* \param y absolute y position
|
||||||
|
* \param sx x position relative to the window
|
||||||
|
* \param sy y position relative to the window
|
||||||
* \param data user data associated to the window
|
* \param data user data associated to the window
|
||||||
*
|
*
|
||||||
* Demonstrates the use of different cursors
|
* Demonstrates the use of different cursors
|
||||||
|
|
@ -364,8 +277,7 @@ motion_handler(struct widget *widget, struct input *input, uint32_t time,
|
||||||
struct eventdemo *e = data;
|
struct eventdemo *e = data;
|
||||||
|
|
||||||
if (log_motion) {
|
if (log_motion) {
|
||||||
printf("motion time: %u, x: %f, y: %f\n", time, x, y);
|
printf("motion time: %d, x: %f, y: %f\n", time, x, y);
|
||||||
e->print_pointer_frame = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x > e->x && x < e->x + e->w)
|
if (x > e->x && x < e->x + e->w)
|
||||||
|
|
@ -385,8 +297,8 @@ eventdemo_create(struct display *d)
|
||||||
{
|
{
|
||||||
struct eventdemo *e;
|
struct eventdemo *e;
|
||||||
|
|
||||||
e = zalloc(sizeof (struct eventdemo));
|
e = malloc(sizeof (struct eventdemo));
|
||||||
if (e == NULL)
|
if(e == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
e->window = window_create(d);
|
e->window = window_create(d);
|
||||||
|
|
@ -399,7 +311,6 @@ eventdemo_create(struct display *d)
|
||||||
} else {
|
} else {
|
||||||
e->widget = window_frame_create(e->window, e);
|
e->widget = window_frame_create(e->window, e);
|
||||||
window_set_title(e->window, title);
|
window_set_title(e->window, title);
|
||||||
window_set_appid(e->window, appid);
|
|
||||||
}
|
}
|
||||||
e->display = d;
|
e->display = d;
|
||||||
|
|
||||||
|
|
@ -434,15 +345,8 @@ eventdemo_create(struct display *d)
|
||||||
/* Set the callback motion handler for the window */
|
/* Set the callback motion handler for the window */
|
||||||
widget_set_motion_handler(e->widget, motion_handler);
|
widget_set_motion_handler(e->widget, motion_handler);
|
||||||
|
|
||||||
/* Set the callback pointer frame handler for the window */
|
|
||||||
widget_set_pointer_frame_handler(e->widget, pointer_frame_handler);
|
|
||||||
|
|
||||||
/* Set the callback axis handler for the window */
|
/* Set the callback axis handler for the window */
|
||||||
widget_set_axis_handlers(e->widget,
|
widget_set_axis_handler(e->widget, axis_handler);
|
||||||
axis_handler,
|
|
||||||
axis_source_handler,
|
|
||||||
axis_stop_handler,
|
|
||||||
axis_discrete_handler);
|
|
||||||
|
|
||||||
/* Initial drawing of the window */
|
/* Initial drawing of the window */
|
||||||
window_schedule_resize(e->window, width, height);
|
window_schedule_resize(e->window, width, height);
|
||||||
|
|
@ -513,21 +417,19 @@ main(int argc, char *argv[])
|
||||||
if (!log_redraw && !log_resize && !log_focus && !log_key &&
|
if (!log_redraw && !log_resize && !log_focus && !log_key &&
|
||||||
!log_button && !log_axis && !log_motion)
|
!log_button && !log_axis && !log_motion)
|
||||||
log_redraw = log_resize = log_focus = log_key =
|
log_redraw = log_resize = log_focus = log_key =
|
||||||
log_button = log_axis = log_motion = true;
|
log_button = log_axis = log_motion = 1;
|
||||||
|
|
||||||
/* Connect to the display and have the arguments parsed */
|
/* Connect to the display and have the arguments parsed */
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create new eventdemo window */
|
/* Create new eventdemo window */
|
||||||
e = eventdemo_create(d);
|
e = eventdemo_create(d);
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
fprintf(stderr, "failed to create eventdemo: %s\n",
|
fprintf(stderr, "failed to create eventdemo: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -30,7 +29,6 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
@ -111,7 +109,7 @@ resize_handler(struct widget *widget,
|
||||||
{
|
{
|
||||||
struct flower *flower = data;
|
struct flower *flower = data;
|
||||||
|
|
||||||
/* Don't resize me */
|
/* Dont resize me */
|
||||||
widget_set_size(flower->widget, flower->width, flower->height);
|
widget_set_size(flower->widget, flower->width, flower->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,8 +171,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,7 +184,6 @@ int main(int argc, char *argv[])
|
||||||
flower.window = window_create(d);
|
flower.window = window_create(d);
|
||||||
flower.widget = window_add_widget(flower.window, &flower);
|
flower.widget = window_add_widget(flower.window, &flower);
|
||||||
window_set_title(flower.window, "Flower");
|
window_set_title(flower.window, "Flower");
|
||||||
window_set_appid(flower.window, "org.freedesktop.weston.flower");
|
|
||||||
|
|
||||||
widget_set_resize_handler(flower.widget, resize_handler);
|
widget_set_resize_handler(flower.widget, resize_handler);
|
||||||
widget_set_redraw_handler(flower.widget, redraw_handler);
|
widget_set_redraw_handler(flower.widget, redraw_handler);
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,23 @@
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
* Copyright © 2012 Intel Corporation
|
* Copyright © 2012 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -30,13 +29,12 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include <libweston/zalloc.h>
|
#include "fullscreen-shell-client-protocol.h"
|
||||||
|
|
||||||
struct fs_output {
|
struct fs_output {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
@ -47,6 +45,8 @@ struct fullscreen {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct window *window;
|
struct window *window;
|
||||||
struct widget *widget;
|
struct widget *widget;
|
||||||
|
struct _wl_fullscreen_shell *fshell;
|
||||||
|
enum _wl_fullscreen_shell_present_method present_method;
|
||||||
int width, height;
|
int width, height;
|
||||||
int fullscreen;
|
int fullscreen;
|
||||||
float pointer_x, pointer_y;
|
float pointer_x, pointer_y;
|
||||||
|
|
@ -77,7 +77,7 @@ draw_string(cairo_t *cr,
|
||||||
|
|
||||||
cairo_save(cr);
|
cairo_save(cr);
|
||||||
|
|
||||||
cairo_select_font_face(cr, "sans-serif",
|
cairo_select_font_face(cr, "sans",
|
||||||
CAIRO_FONT_SLANT_NORMAL,
|
CAIRO_FONT_SLANT_NORMAL,
|
||||||
CAIRO_FONT_WEIGHT_NORMAL);
|
CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
cairo_set_font_size(cr, 14);
|
cairo_set_font_size(cr, 14);
|
||||||
|
|
@ -119,6 +119,7 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
int i;
|
int i;
|
||||||
double x, y, border;
|
double x, y, border;
|
||||||
|
const char *method_name[] = { "default", "center", "zoom", "zoom_crop", "stretch"};
|
||||||
|
|
||||||
surface = window_get_surface(fullscreen->window);
|
surface = window_get_surface(fullscreen->window);
|
||||||
if (surface == NULL ||
|
if (surface == NULL ||
|
||||||
|
|
@ -144,17 +145,33 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
allocation.y + 25);
|
allocation.y + 25);
|
||||||
cairo_set_source_rgb(cr, 1, 1, 1);
|
cairo_set_source_rgb(cr, 1, 1, 1);
|
||||||
|
|
||||||
draw_string(cr,
|
if (fullscreen->fshell) {
|
||||||
"Surface size: %d, %d\n"
|
draw_string(cr,
|
||||||
"Scale: %d, transform: %d\n"
|
"Surface size: %d, %d\n"
|
||||||
"Pointer: %f,%f\n"
|
"Scale: %d, transform: %d\n"
|
||||||
"Fullscreen: %d\n"
|
"Pointer: %f,%f\n"
|
||||||
"Keys: (s)cale, (t)ransform, si(z)e, (f)ullscreen, (q)uit\n",
|
"Output: %s, present method: %s\n"
|
||||||
fullscreen->width, fullscreen->height,
|
"Keys: (s)cale, (t)ransform, si(z)e, (m)ethod,\n"
|
||||||
window_get_buffer_scale (fullscreen->window),
|
" (o)utput, modes(w)itch, (q)uit\n",
|
||||||
window_get_buffer_transform (fullscreen->window),
|
fullscreen->width, fullscreen->height,
|
||||||
fullscreen->pointer_x, fullscreen->pointer_y,
|
window_get_buffer_scale (fullscreen->window),
|
||||||
fullscreen->fullscreen);
|
window_get_buffer_transform (fullscreen->window),
|
||||||
|
fullscreen->pointer_x, fullscreen->pointer_y,
|
||||||
|
method_name[fullscreen->present_method],
|
||||||
|
fullscreen->current_output ? output_get_model(fullscreen->current_output->output): "null");
|
||||||
|
} else {
|
||||||
|
draw_string(cr,
|
||||||
|
"Surface size: %d, %d\n"
|
||||||
|
"Scale: %d, transform: %d\n"
|
||||||
|
"Pointer: %f,%f\n"
|
||||||
|
"Fullscreen: %d\n"
|
||||||
|
"Keys: (s)cale, (t)ransform, si(z)e, (f)ullscreen, (q)uit\n",
|
||||||
|
fullscreen->width, fullscreen->height,
|
||||||
|
window_get_buffer_scale (fullscreen->window),
|
||||||
|
window_get_buffer_transform (fullscreen->window),
|
||||||
|
fullscreen->pointer_x, fullscreen->pointer_y,
|
||||||
|
fullscreen->fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
y = 100;
|
y = 100;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
@ -233,6 +250,8 @@ key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
struct fullscreen *fullscreen = data;
|
struct fullscreen *fullscreen = data;
|
||||||
int transform, scale;
|
int transform, scale;
|
||||||
static int current_size = 0;
|
static int current_size = 0;
|
||||||
|
struct fs_output *fsout;
|
||||||
|
struct wl_output *wl_output;
|
||||||
int widths[] = { 640, 320, 800, 400 };
|
int widths[] = { 640, 320, 800, 400 };
|
||||||
int heights[] = { 480, 240, 600, 300 };
|
int heights[] = { 480, 240, 600, 300 };
|
||||||
|
|
||||||
|
|
@ -258,9 +277,6 @@ key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XKB_KEY_z:
|
case XKB_KEY_z:
|
||||||
if (fullscreen->fullscreen)
|
|
||||||
break;
|
|
||||||
|
|
||||||
current_size = (current_size + 1) % 4;
|
current_size = (current_size + 1) % 4;
|
||||||
fullscreen->width = widths[current_size];
|
fullscreen->width = widths[current_size];
|
||||||
fullscreen->height = heights[current_size];
|
fullscreen->height = heights[current_size];
|
||||||
|
|
@ -268,7 +284,69 @@ key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
fullscreen->width, fullscreen->height);
|
fullscreen->width, fullscreen->height);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case XKB_KEY_m:
|
||||||
|
if (!fullscreen->fshell)
|
||||||
|
break;
|
||||||
|
|
||||||
|
wl_output = NULL;
|
||||||
|
if (fullscreen->current_output)
|
||||||
|
wl_output = output_get_wl_output(fullscreen->current_output->output);
|
||||||
|
fullscreen->present_method = (fullscreen->present_method + 1) % 5;
|
||||||
|
_wl_fullscreen_shell_present_surface(fullscreen->fshell,
|
||||||
|
window_get_wl_surface(fullscreen->window),
|
||||||
|
fullscreen->present_method,
|
||||||
|
wl_output);
|
||||||
|
window_schedule_redraw(window);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XKB_KEY_o:
|
||||||
|
if (!fullscreen->fshell)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fsout = fullscreen->current_output;
|
||||||
|
wl_output = fsout ? output_get_wl_output(fsout->output) : NULL;
|
||||||
|
|
||||||
|
/* Clear the current presentation */
|
||||||
|
_wl_fullscreen_shell_present_surface(fullscreen->fshell, NULL,
|
||||||
|
0, wl_output);
|
||||||
|
|
||||||
|
if (fullscreen->current_output) {
|
||||||
|
if (fullscreen->current_output->link.next == &fullscreen->output_list)
|
||||||
|
fsout = NULL;
|
||||||
|
else
|
||||||
|
fsout = wl_container_of(fullscreen->current_output->link.next,
|
||||||
|
fsout, link);
|
||||||
|
} else {
|
||||||
|
fsout = wl_container_of(fullscreen->output_list.next,
|
||||||
|
fsout, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
fullscreen->current_output = fsout;
|
||||||
|
wl_output = fsout ? output_get_wl_output(fsout->output) : NULL;
|
||||||
|
_wl_fullscreen_shell_present_surface(fullscreen->fshell,
|
||||||
|
window_get_wl_surface(fullscreen->window),
|
||||||
|
fullscreen->present_method,
|
||||||
|
wl_output);
|
||||||
|
window_schedule_redraw(window);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XKB_KEY_w:
|
||||||
|
if (!fullscreen->fshell || !fullscreen->current_output)
|
||||||
|
break;
|
||||||
|
|
||||||
|
wl_output = NULL;
|
||||||
|
if (fullscreen->current_output)
|
||||||
|
wl_output = output_get_wl_output(fullscreen->current_output->output);
|
||||||
|
_wl_fullscreen_shell_mode_feedback_destroy(
|
||||||
|
_wl_fullscreen_shell_present_surface_for_mode(fullscreen->fshell,
|
||||||
|
window_get_wl_surface(fullscreen->window),
|
||||||
|
wl_output, 0));
|
||||||
|
window_schedule_redraw(window);
|
||||||
|
break;
|
||||||
|
|
||||||
case XKB_KEY_f:
|
case XKB_KEY_f:
|
||||||
|
if (fullscreen->fshell)
|
||||||
|
break;
|
||||||
fullscreen->fullscreen ^= 1;
|
fullscreen->fullscreen ^= 1;
|
||||||
window_set_fullscreen(window, fullscreen->fullscreen);
|
window_set_fullscreen(window, fullscreen->fullscreen);
|
||||||
break;
|
break;
|
||||||
|
|
@ -340,13 +418,31 @@ touch_handler(struct widget *widget, struct input *input,
|
||||||
window_move(fullscreen->window, input, display_get_serial(fullscreen->display));
|
window_move(fullscreen->window, input, display_get_serial(fullscreen->display));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fshell_capability_handler(void *data, struct _wl_fullscreen_shell *fshell,
|
||||||
|
uint32_t capability)
|
||||||
|
{
|
||||||
|
struct fullscreen *fullscreen = data;
|
||||||
|
|
||||||
|
switch (capability) {
|
||||||
|
case _WL_FULLSCREEN_SHELL_CAPABILITY_CURSOR_PLANE:
|
||||||
|
fullscreen->draw_cursor = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _wl_fullscreen_shell_listener fullscreen_shell_listener = {
|
||||||
|
fshell_capability_handler
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(int error_code)
|
usage(int error_code)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
|
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
|
||||||
" -w <width>\tSet window width to <width>\n"
|
" -w <width>\tSet window width to <width>\n"
|
||||||
" -h <height>\tSet window height to <height>\n"
|
" -h <height>\tSet window height to <height>\n"
|
||||||
" -f\t\tMap window as fullscreen\n"
|
|
||||||
" --help\tShow this help text\n\n");
|
" --help\tShow this help text\n\n");
|
||||||
|
|
||||||
exit(error_code);
|
exit(error_code);
|
||||||
|
|
@ -363,15 +459,27 @@ output_handler(struct output *output, void *data)
|
||||||
if (fsout->output == output)
|
if (fsout->output == output)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fsout = zalloc(sizeof *fsout);
|
fsout = calloc(1, sizeof *fsout);
|
||||||
if (fsout == NULL) {
|
|
||||||
fprintf(stderr, "out of memory in output_handler\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fsout->output = output;
|
fsout->output = output;
|
||||||
wl_list_insert(&fullscreen->output_list, &fsout->link);
|
wl_list_insert(&fullscreen->output_list, &fsout->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
global_handler(struct display *display, uint32_t id, const char *interface,
|
||||||
|
uint32_t version, void *data)
|
||||||
|
{
|
||||||
|
struct fullscreen *fullscreen = data;
|
||||||
|
|
||||||
|
if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
|
||||||
|
fullscreen->fshell = display_bind(display, id,
|
||||||
|
&_wl_fullscreen_shell_interface,
|
||||||
|
1);
|
||||||
|
_wl_fullscreen_shell_add_listener(fullscreen->fshell,
|
||||||
|
&fullscreen_shell_listener,
|
||||||
|
fullscreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct fullscreen fullscreen;
|
struct fullscreen fullscreen;
|
||||||
|
|
@ -381,6 +489,7 @@ int main(int argc, char *argv[])
|
||||||
fullscreen.width = 640;
|
fullscreen.width = 640;
|
||||||
fullscreen.height = 480;
|
fullscreen.height = 480;
|
||||||
fullscreen.fullscreen = 0;
|
fullscreen.fullscreen = 0;
|
||||||
|
fullscreen.present_method = _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT;
|
||||||
wl_list_init(&fullscreen.output_list);
|
wl_list_init(&fullscreen.output_list);
|
||||||
fullscreen.current_output = NULL;
|
fullscreen.current_output = NULL;
|
||||||
|
|
||||||
|
|
@ -395,8 +504,6 @@ int main(int argc, char *argv[])
|
||||||
usage(EXIT_FAILURE);
|
usage(EXIT_FAILURE);
|
||||||
|
|
||||||
fullscreen.height = atol(argv[i]);
|
fullscreen.height = atol(argv[i]);
|
||||||
} else if (strcmp(argv[i], "-f") == 0) {
|
|
||||||
fullscreen.fullscreen = 1;
|
|
||||||
} else if (strcmp(argv[i], "--help") == 0)
|
} else if (strcmp(argv[i], "--help") == 0)
|
||||||
usage(EXIT_SUCCESS);
|
usage(EXIT_SUCCESS);
|
||||||
else
|
else
|
||||||
|
|
@ -405,23 +512,33 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullscreen.display = d;
|
fullscreen.display = d;
|
||||||
|
fullscreen.fshell = NULL;
|
||||||
display_set_user_data(fullscreen.display, &fullscreen);
|
display_set_user_data(fullscreen.display, &fullscreen);
|
||||||
|
display_set_global_handler(fullscreen.display, global_handler);
|
||||||
display_set_output_configure_handler(fullscreen.display, output_handler);
|
display_set_output_configure_handler(fullscreen.display, output_handler);
|
||||||
|
|
||||||
fullscreen.window = window_create(d);
|
if (fullscreen.fshell) {
|
||||||
fullscreen.draw_cursor = 0;
|
fullscreen.window = window_create_custom(d);
|
||||||
|
_wl_fullscreen_shell_present_surface(fullscreen.fshell,
|
||||||
|
window_get_wl_surface(fullscreen.window),
|
||||||
|
fullscreen.present_method,
|
||||||
|
NULL);
|
||||||
|
/* If we get the CURSOR_PLANE capability, we'll change this */
|
||||||
|
fullscreen.draw_cursor = 1;
|
||||||
|
} else {
|
||||||
|
fullscreen.window = window_create(d);
|
||||||
|
fullscreen.draw_cursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
fullscreen.widget =
|
fullscreen.widget =
|
||||||
window_add_widget(fullscreen.window, &fullscreen);
|
window_add_widget(fullscreen.window, &fullscreen);
|
||||||
|
|
||||||
window_set_title(fullscreen.window, "Fullscreen");
|
window_set_title(fullscreen.window, "Fullscreen");
|
||||||
window_set_appid(fullscreen.window, "org.freedesktop.weston.fullscreen");
|
|
||||||
|
|
||||||
widget_set_transparent(fullscreen.widget, 0);
|
widget_set_transparent(fullscreen.widget, 0);
|
||||||
|
|
||||||
|
|
@ -437,8 +554,6 @@ int main(int argc, char *argv[])
|
||||||
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
|
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
|
||||||
|
|
||||||
window_set_user_data(fullscreen.window, &fullscreen);
|
window_set_user_data(fullscreen.window, &fullscreen);
|
||||||
if (fullscreen.fullscreen)
|
|
||||||
window_set_fullscreen(fullscreen.window, fullscreen.fullscreen);
|
|
||||||
/* Hack to set minimum allocation so we can shrink later */
|
/* Hack to set minimum allocation so we can shrink later */
|
||||||
window_schedule_resize(fullscreen.window,
|
window_schedule_resize(fullscreen.window,
|
||||||
1, 1);
|
1, 1);
|
||||||
|
|
|
||||||
500
clients/gears.c
Normal file
|
|
@ -0,0 +1,500 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
struct gears {
|
||||||
|
struct window *window;
|
||||||
|
struct widget *widget;
|
||||||
|
|
||||||
|
struct display *d;
|
||||||
|
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLDisplay config;
|
||||||
|
EGLContext context;
|
||||||
|
GLfloat angle;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLfloat rotx;
|
||||||
|
GLfloat roty;
|
||||||
|
} view;
|
||||||
|
|
||||||
|
int button_down;
|
||||||
|
int last_x, last_y;
|
||||||
|
|
||||||
|
GLint gear_list[3];
|
||||||
|
int fullscreen;
|
||||||
|
int frames;
|
||||||
|
uint32_t last_fps;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gear_template {
|
||||||
|
GLfloat material[4];
|
||||||
|
GLfloat inner_radius;
|
||||||
|
GLfloat outer_radius;
|
||||||
|
GLfloat width;
|
||||||
|
GLint teeth;
|
||||||
|
GLfloat tooth_depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct gear_template gear_templates[] = {
|
||||||
|
{ { 0.8, 0.1, 0.0, 1.0 }, 1.0, 4.0, 1.0, 20, 0.7 },
|
||||||
|
{ { 0.0, 0.8, 0.2, 1.0 }, 0.5, 2.0, 2.0, 10, 0.7 },
|
||||||
|
{ { 0.2, 0.2, 1.0, 1.0 }, 1.3, 2.0, 0.5, 10, 0.7 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLfloat light_pos[4] = {5.0, 5.0, 10.0, 0.0};
|
||||||
|
|
||||||
|
static void die(const char *msg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s", msg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
make_gear(const struct gear_template *t)
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
GLfloat r0, r1, r2;
|
||||||
|
GLfloat angle, da;
|
||||||
|
GLfloat u, v, len;
|
||||||
|
|
||||||
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->material);
|
||||||
|
|
||||||
|
r0 = t->inner_radius;
|
||||||
|
r1 = t->outer_radius - t->tooth_depth / 2.0;
|
||||||
|
r2 = t->outer_radius + t->tooth_depth / 2.0;
|
||||||
|
|
||||||
|
da = 2.0 * M_PI / t->teeth / 4.0;
|
||||||
|
|
||||||
|
glShadeModel(GL_FLAT);
|
||||||
|
|
||||||
|
glNormal3f(0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
/* draw front face */
|
||||||
|
glBegin(GL_QUAD_STRIP);
|
||||||
|
for (i = 0; i <= t->teeth; i++) {
|
||||||
|
angle = i * 2.0 * M_PI / t->teeth;
|
||||||
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
|
||||||
|
if (i < t->teeth) {
|
||||||
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
/* draw front sides of teeth */
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
da = 2.0 * M_PI / t->teeth / 4.0;
|
||||||
|
for (i = 0; i < t->teeth; i++) {
|
||||||
|
angle = i * 2.0 * M_PI / t->teeth;
|
||||||
|
|
||||||
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
|
||||||
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5);
|
||||||
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glNormal3f(0.0, 0.0, -1.0);
|
||||||
|
|
||||||
|
/* draw back face */
|
||||||
|
glBegin(GL_QUAD_STRIP);
|
||||||
|
for (i = 0; i <= t->teeth; i++) {
|
||||||
|
angle = i * 2.0 * M_PI / t->teeth;
|
||||||
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
|
||||||
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
|
||||||
|
if (i < t->teeth) {
|
||||||
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
|
||||||
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
/* draw back sides of teeth */
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
da = 2.0 * M_PI / t->teeth / 4.0;
|
||||||
|
for (i = 0; i < t->teeth; i++) {
|
||||||
|
angle = i * 2.0 * M_PI / t->teeth;
|
||||||
|
|
||||||
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
|
||||||
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5);
|
||||||
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
/* draw outward faces of teeth */
|
||||||
|
glBegin(GL_QUAD_STRIP);
|
||||||
|
for (i = 0; i < t->teeth; i++) {
|
||||||
|
angle = i * 2.0 * M_PI / t->teeth;
|
||||||
|
|
||||||
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
|
||||||
|
u = r2 * cos(angle + da) - r1 * cos(angle);
|
||||||
|
v = r2 * sin(angle + da) - r1 * sin(angle);
|
||||||
|
len = sqrt(u * u + v * v);
|
||||||
|
u /= len;
|
||||||
|
v /= len;
|
||||||
|
glNormal3f(v, -u, 0.0);
|
||||||
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5);
|
||||||
|
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5);
|
||||||
|
glNormal3f(cos(angle), sin(angle), 0.0);
|
||||||
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5);
|
||||||
|
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5);
|
||||||
|
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
|
||||||
|
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
|
||||||
|
glNormal3f(v, -u, 0.0);
|
||||||
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
|
||||||
|
glNormal3f(cos(angle), sin(angle), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glVertex3f(r1 * cos(0), r1 * sin(0), t->width * 0.5);
|
||||||
|
glVertex3f(r1 * cos(0), r1 * sin(0), -t->width * 0.5);
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glShadeModel(GL_SMOOTH);
|
||||||
|
|
||||||
|
/* draw inside radius cylinder */
|
||||||
|
glBegin(GL_QUAD_STRIP);
|
||||||
|
for (i = 0; i <= t->teeth; i++) {
|
||||||
|
angle = i * 2.0 * M_PI / t->teeth;
|
||||||
|
glNormal3f(-cos(angle), -sin(angle), 0.0);
|
||||||
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
|
||||||
|
glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_fps(struct gears *gears, uint32_t time)
|
||||||
|
{
|
||||||
|
long diff_ms;
|
||||||
|
static bool first_call = true;
|
||||||
|
|
||||||
|
if (first_call) {
|
||||||
|
gears->last_fps = time;
|
||||||
|
first_call = false;
|
||||||
|
} else
|
||||||
|
gears->frames++;
|
||||||
|
|
||||||
|
diff_ms = time - gears->last_fps;
|
||||||
|
|
||||||
|
if (diff_ms > 5000) {
|
||||||
|
float seconds = diff_ms / 1000.0;
|
||||||
|
float fps = gears->frames / seconds;
|
||||||
|
|
||||||
|
printf("%d frames in %6.3f seconds = %6.3f FPS\n", gears->frames, seconds, fps);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
gears->frames = 0;
|
||||||
|
gears->last_fps = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_callback(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
struct gears *gears = data;
|
||||||
|
|
||||||
|
update_fps(gears, time);
|
||||||
|
|
||||||
|
gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
|
||||||
|
|
||||||
|
window_schedule_redraw(gears->window);
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_callback_listener listener = {
|
||||||
|
frame_callback
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
motion_handler(struct widget *widget, struct input *input,
|
||||||
|
uint32_t time, float x, float y, void *data)
|
||||||
|
{
|
||||||
|
struct gears *gears = data;
|
||||||
|
int offset_x, offset_y;
|
||||||
|
float step = 0.5;
|
||||||
|
|
||||||
|
if (gears->button_down) {
|
||||||
|
offset_x = x - gears->last_x;
|
||||||
|
offset_y = y - gears->last_y;
|
||||||
|
gears->last_x = x;
|
||||||
|
gears->last_y = y;
|
||||||
|
gears->view.roty += offset_x * step;
|
||||||
|
gears->view.rotx += offset_y * step;
|
||||||
|
if (gears->view.roty >= 360)
|
||||||
|
gears->view.roty = gears->view.roty - 360;
|
||||||
|
if (gears->view.roty <= 0)
|
||||||
|
gears->view.roty = gears->view.roty + 360;
|
||||||
|
if (gears->view.rotx >= 360)
|
||||||
|
gears->view.rotx = gears->view.rotx - 360;
|
||||||
|
if (gears->view.rotx <= 0)
|
||||||
|
gears->view.rotx = gears->view.rotx + 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CURSOR_LEFT_PTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
button_handler(struct widget *widget, struct input *input,
|
||||||
|
uint32_t time, uint32_t button,
|
||||||
|
enum wl_pointer_button_state state, void *data)
|
||||||
|
{
|
||||||
|
struct gears *gears = data;
|
||||||
|
|
||||||
|
if (button == BTN_LEFT) {
|
||||||
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||||
|
gears->button_down = 1;
|
||||||
|
input_get_position(input,
|
||||||
|
&gears->last_x, &gears->last_y);
|
||||||
|
} else {
|
||||||
|
gears->button_down = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
redraw_handler(struct widget *widget, void *data)
|
||||||
|
{
|
||||||
|
struct rectangle window_allocation;
|
||||||
|
struct rectangle allocation;
|
||||||
|
struct wl_callback *callback;
|
||||||
|
struct gears *gears = data;
|
||||||
|
|
||||||
|
widget_get_allocation(gears->widget, &allocation);
|
||||||
|
window_get_allocation(gears->window, &window_allocation);
|
||||||
|
|
||||||
|
if (display_acquire_window_surface(gears->d,
|
||||||
|
gears->window,
|
||||||
|
gears->context) < 0) {
|
||||||
|
die("Unable to acquire window surface, "
|
||||||
|
"compiled without cairo-egl?\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport(allocation.x,
|
||||||
|
window_allocation.height - allocation.height - allocation.y,
|
||||||
|
allocation.width, allocation.height);
|
||||||
|
glScissor(allocation.x,
|
||||||
|
window_allocation.height - allocation.height - allocation.y,
|
||||||
|
allocation.width, allocation.height);
|
||||||
|
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glTranslatef(0.0, 0.0, -50);
|
||||||
|
|
||||||
|
glRotatef(gears->view.rotx, 1.0, 0.0, 0.0);
|
||||||
|
glRotatef(gears->view.roty, 0.0, 1.0, 0.0);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(-3.0, -2.0, 0.0);
|
||||||
|
glRotatef(gears->angle, 0.0, 0.0, 1.0);
|
||||||
|
glCallList(gears->gear_list[0]);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(3.1, -2.0, 0.0);
|
||||||
|
glRotatef(-2.0 * gears->angle - 9.0, 0.0, 0.0, 1.0);
|
||||||
|
glCallList(gears->gear_list[1]);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(-3.1, 4.2, 0.0);
|
||||||
|
glRotatef(-2.0 * gears->angle - 25.0, 0.0, 0.0, 1.0);
|
||||||
|
glCallList(gears->gear_list[2]);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glFlush();
|
||||||
|
|
||||||
|
display_release_window_surface(gears->d, gears->window);
|
||||||
|
|
||||||
|
callback = wl_surface_frame(window_get_wl_surface(gears->window));
|
||||||
|
wl_callback_add_listener(callback, &listener, gears);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
resize_handler(struct widget *widget,
|
||||||
|
int32_t width, int32_t height, void *data)
|
||||||
|
{
|
||||||
|
struct gears *gears = data;
|
||||||
|
int32_t size, big, small;
|
||||||
|
|
||||||
|
/* Constrain child size to be square and at least 300x300 */
|
||||||
|
if (width < height) {
|
||||||
|
small = width;
|
||||||
|
big = height;
|
||||||
|
} else {
|
||||||
|
small = height;
|
||||||
|
big = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gears->fullscreen)
|
||||||
|
size = small;
|
||||||
|
else
|
||||||
|
size = big;
|
||||||
|
|
||||||
|
widget_set_size(gears->widget, size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_focus_handler(struct window *window,
|
||||||
|
struct input *device, void *data)
|
||||||
|
{
|
||||||
|
window_schedule_redraw(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fullscreen_handler(struct window *window, void *data)
|
||||||
|
{
|
||||||
|
struct gears *gears = data;
|
||||||
|
|
||||||
|
gears->fullscreen ^= 1;
|
||||||
|
window_set_fullscreen(window, gears->fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gears *
|
||||||
|
gears_create(struct display *display)
|
||||||
|
{
|
||||||
|
const int width = 450, height = 500;
|
||||||
|
struct gears *gears;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
gears = zalloc(sizeof *gears);
|
||||||
|
gears->d = display;
|
||||||
|
gears->window = window_create(display);
|
||||||
|
gears->widget = window_frame_create(gears->window, gears);
|
||||||
|
window_set_title(gears->window, "Wayland Gears");
|
||||||
|
|
||||||
|
gears->display = display_get_egl_display(gears->d);
|
||||||
|
if (gears->display == NULL)
|
||||||
|
die("failed to create egl display\n");
|
||||||
|
|
||||||
|
eglBindAPI(EGL_OPENGL_API);
|
||||||
|
|
||||||
|
gears->config = display_get_argb_egl_config(gears->d);
|
||||||
|
|
||||||
|
gears->context = eglCreateContext(gears->display, gears->config,
|
||||||
|
EGL_NO_CONTEXT, NULL);
|
||||||
|
if (gears->context == NULL)
|
||||||
|
die("failed to create context\n");
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context))
|
||||||
|
die("failed to make context current\n");
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
gears->gear_list[i] = glGenLists(1);
|
||||||
|
glNewList(gears->gear_list[i], GL_COMPILE);
|
||||||
|
make_gear(&gear_templates[i]);
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
gears->button_down = 0;
|
||||||
|
gears->last_x = 0;
|
||||||
|
gears->last_y = 0;
|
||||||
|
|
||||||
|
gears->view.rotx = 20.0;
|
||||||
|
gears->view.roty = 30.0;
|
||||||
|
|
||||||
|
printf("Warning: FPS count is limited by the wayland compositor or monitor refresh rate\n");
|
||||||
|
|
||||||
|
glEnable(GL_NORMALIZE);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
|
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glClearColor(0, 0, 0, 0.92);
|
||||||
|
|
||||||
|
window_set_user_data(gears->window, gears);
|
||||||
|
widget_set_resize_handler(gears->widget, resize_handler);
|
||||||
|
widget_set_redraw_handler(gears->widget, redraw_handler);
|
||||||
|
widget_set_button_handler(gears->widget, button_handler);
|
||||||
|
widget_set_motion_handler(gears->widget, motion_handler);
|
||||||
|
window_set_keyboard_focus_handler(gears->window,
|
||||||
|
keyboard_focus_handler);
|
||||||
|
window_set_fullscreen_handler(gears->window, fullscreen_handler);
|
||||||
|
|
||||||
|
window_schedule_resize(gears->window, width, height);
|
||||||
|
|
||||||
|
return gears;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gears_destroy(struct gears *gears)
|
||||||
|
{
|
||||||
|
widget_destroy(gears->widget);
|
||||||
|
window_destroy(gears->window);
|
||||||
|
free(gears);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct display *d;
|
||||||
|
struct gears *gears;
|
||||||
|
|
||||||
|
d = display_create(&argc, argv);
|
||||||
|
if (d == NULL) {
|
||||||
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
gears = gears_create(d);
|
||||||
|
display_run(d);
|
||||||
|
|
||||||
|
gears_destroy(gears);
|
||||||
|
display_destroy(d);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1062
clients/glmatrix.c
Normal file
407
clients/image.c
|
|
@ -2,24 +2,23 @@
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
* Copyright © 2009 Chris Wilson
|
* Copyright © 2009 Chris Wilson
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -36,32 +35,16 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "shared/cairo-util.h"
|
#include "../shared/cairo-util.h"
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/image-loader.h"
|
|
||||||
|
|
||||||
bool verbose;
|
|
||||||
|
|
||||||
#define verbose_print(...) do { \
|
|
||||||
if (verbose) \
|
|
||||||
fprintf(stderr, __VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
struct image {
|
struct image {
|
||||||
struct window *window;
|
struct window *window;
|
||||||
|
struct widget *widget;
|
||||||
/* Decorations, buttons, etc. */
|
|
||||||
struct widget *frame_widget;
|
|
||||||
|
|
||||||
/* Where we draw the image content. */
|
|
||||||
struct widget *image_widget;
|
|
||||||
|
|
||||||
struct display *display;
|
struct display *display;
|
||||||
char *filename;
|
char *filename;
|
||||||
cairo_surface_t *image;
|
cairo_surface_t *image;
|
||||||
|
|
@ -79,39 +62,6 @@ struct image {
|
||||||
cairo_matrix_t matrix;
|
cairo_matrix_t matrix;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cli_render_intent_option {
|
|
||||||
int render_intent;
|
|
||||||
const char *cli_option;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct cli_render_intent_option
|
|
||||||
cli_ri_table[] = {
|
|
||||||
{
|
|
||||||
.render_intent = -1,
|
|
||||||
.cli_option = "off",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.render_intent = RENDER_INTENT_PERCEPTUAL,
|
|
||||||
.cli_option = "per",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.render_intent = RENDER_INTENT_RELATIVE,
|
|
||||||
.cli_option = "rel",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.render_intent = RENDER_INTENT_RELATIVE_BPC,
|
|
||||||
.cli_option = "rel-bpc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.render_intent = RENDER_INTENT_SATURATION,
|
|
||||||
.cli_option = "sat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.render_intent = RENDER_INTENT_ABSOLUTE,
|
|
||||||
.cli_option = "abs",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static double
|
static double
|
||||||
get_scale(struct image *image)
|
get_scale(struct image *image)
|
||||||
{
|
{
|
||||||
|
|
@ -130,7 +80,7 @@ clamp_view(struct image *image)
|
||||||
|
|
||||||
sw = image->width * scale;
|
sw = image->width * scale;
|
||||||
sh = image->height * scale;
|
sh = image->height * scale;
|
||||||
widget_get_allocation(image->frame_widget, &allocation);
|
widget_get_allocation(image->widget, &allocation);
|
||||||
|
|
||||||
if (sw < allocation.width) {
|
if (sw < allocation.width) {
|
||||||
image->matrix.x0 =
|
image->matrix.x0 =
|
||||||
|
|
@ -142,7 +92,7 @@ clamp_view(struct image *image)
|
||||||
image->matrix.x0 = allocation.width - sw;
|
image->matrix.x0 = allocation.width - sw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sh < allocation.height) {
|
if (sh < allocation.width) {
|
||||||
image->matrix.y0 =
|
image->matrix.y0 =
|
||||||
(allocation.height - image->height * scale) / 2;
|
(allocation.height - image->height * scale) / 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -154,45 +104,27 @@ clamp_view(struct image *image)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_redraw_handler(struct widget *widget, void *data)
|
redraw_handler(struct widget *widget, void *data)
|
||||||
{
|
|
||||||
struct rectangle allocation;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
|
||||||
|
|
||||||
cr = widget_cairo_create(widget);
|
|
||||||
cairo_rectangle(cr, allocation.x, allocation.y,
|
|
||||||
allocation.width, allocation.height);
|
|
||||||
cairo_set_source_rgba(cr, 0, 0, 0, 1);
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_fill(cr);
|
|
||||||
cairo_destroy(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
frame_resize_handler(struct widget *widget,
|
|
||||||
int32_t width, int32_t height, void *data)
|
|
||||||
{
|
|
||||||
struct image *image = data;
|
|
||||||
|
|
||||||
clamp_view(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
image_redraw_handler(struct widget *widget, void *data)
|
|
||||||
{
|
{
|
||||||
struct image *image = data;
|
struct image *image = data;
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
cairo_surface_t *surface;
|
||||||
double width, height, doc_aspect, window_aspect, scale;
|
double width, height, doc_aspect, window_aspect, scale;
|
||||||
|
cairo_matrix_t matrix;
|
||||||
|
cairo_matrix_t translate;
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
surface = window_get_surface(image->window);
|
||||||
|
cr = cairo_create(surface);
|
||||||
cr = widget_cairo_create(widget);
|
widget_get_allocation(image->widget, &allocation);
|
||||||
cairo_rectangle(cr, allocation.x, allocation.y,
|
cairo_rectangle(cr, allocation.x, allocation.y,
|
||||||
allocation.width, allocation.height);
|
allocation.width, allocation.height);
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
|
cairo_clip(cr);
|
||||||
|
cairo_push_group(cr);
|
||||||
|
cairo_translate(cr, allocation.x, allocation.y);
|
||||||
|
|
||||||
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||||
|
cairo_set_source_rgba(cr, 0, 0, 0, 1);
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
|
|
||||||
if (!image->initialized) {
|
if (!image->initialized) {
|
||||||
|
|
@ -214,36 +146,49 @@ image_redraw_handler(struct widget *widget, void *data)
|
||||||
clamp_view(image);
|
clamp_view(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_set_matrix(cr, &image->matrix);
|
matrix = image->matrix;
|
||||||
|
cairo_matrix_init_translate(&translate, allocation.x, allocation.y);
|
||||||
|
cairo_matrix_multiply(&matrix, &matrix, &translate);
|
||||||
|
cairo_set_matrix(cr, &matrix);
|
||||||
|
|
||||||
cairo_set_source_surface(cr, image->image, 0, 0);
|
cairo_set_source_surface(cr, image->image, 0, 0);
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
|
|
||||||
|
cairo_pop_group_to_source(cr);
|
||||||
|
cairo_paint(cr);
|
||||||
cairo_destroy(cr);
|
cairo_destroy(cr);
|
||||||
|
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
image_resize_handler(struct widget *widget,
|
resize_handler(struct widget *widget,
|
||||||
int32_t width, int32_t height, void *data)
|
int32_t width, int32_t height, void *data)
|
||||||
{
|
{
|
||||||
struct image *image = data;
|
struct image *image = data;
|
||||||
struct rectangle allocation;
|
|
||||||
|
|
||||||
widget_get_allocation(image->frame_widget, &allocation);
|
clamp_view(image);
|
||||||
|
}
|
||||||
|
|
||||||
widget_set_allocation(widget,
|
static void
|
||||||
allocation.x, allocation.y,
|
keyboard_focus_handler(struct window *window,
|
||||||
allocation.width, allocation.height);
|
struct input *device, void *data)
|
||||||
|
{
|
||||||
|
struct image *image = data;
|
||||||
|
|
||||||
|
window_schedule_redraw(image->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
image_enter_handler(struct widget *widget,
|
enter_handler(struct widget *widget,
|
||||||
struct input *input,
|
struct input *input,
|
||||||
float x, float y, void *data)
|
float x, float y, void *data)
|
||||||
{
|
{
|
||||||
struct image *image = data;
|
struct image *image = data;
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
widget_get_allocation(image->widget, &allocation);
|
||||||
x -= allocation.x;
|
x -= allocation.x;
|
||||||
y -= allocation.y;
|
y -= allocation.y;
|
||||||
|
|
||||||
|
|
@ -268,14 +213,14 @@ move_viewport(struct image *image, double dx, double dy)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
image_motion_handler(struct widget *widget,
|
motion_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
float x, float y, void *data)
|
float x, float y, void *data)
|
||||||
{
|
{
|
||||||
struct image *image = data;
|
struct image *image = data;
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
widget_get_allocation(image->widget, &allocation);
|
||||||
x -= allocation.x;
|
x -= allocation.x;
|
||||||
y -= allocation.y;
|
y -= allocation.y;
|
||||||
|
|
||||||
|
|
@ -290,11 +235,11 @@ image_motion_handler(struct widget *widget,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
image_button_handler(struct widget *widget,
|
button_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
uint32_t button,
|
uint32_t button,
|
||||||
enum wl_pointer_button_state state,
|
enum wl_pointer_button_state state,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct image *image = data;
|
struct image *image = data;
|
||||||
|
|
||||||
|
|
@ -332,35 +277,6 @@ zoom(struct image *image, double scale)
|
||||||
clamp_view(image);
|
clamp_view(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
image_axis_handler(struct widget *widget, struct input *input, uint32_t time,
|
|
||||||
uint32_t axis, wl_fixed_t value, void *data)
|
|
||||||
{
|
|
||||||
struct image *image = data;
|
|
||||||
|
|
||||||
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL &&
|
|
||||||
input_get_modifiers(input) == MOD_CONTROL_MASK) {
|
|
||||||
/* set zoom level to 2% per 10 axis units */
|
|
||||||
zoom(image, (1.0 - wl_fixed_to_double(value) / 500.0));
|
|
||||||
|
|
||||||
window_schedule_redraw(image->window);
|
|
||||||
} else if (input_get_modifiers(input) == 0) {
|
|
||||||
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
|
||||||
move_viewport(image, 0, wl_fixed_to_double(value));
|
|
||||||
else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
|
||||||
move_viewport(image, wl_fixed_to_double(value), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_focus_handler(struct window *window,
|
|
||||||
struct input *device, void *data)
|
|
||||||
{
|
|
||||||
struct image *image = data;
|
|
||||||
|
|
||||||
window_schedule_redraw(image->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
key_handler(struct window *window, struct input *input, uint32_t time,
|
key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
|
uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
|
||||||
|
|
@ -392,6 +308,26 @@ key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
axis_handler(struct widget *widget, struct input *input, uint32_t time,
|
||||||
|
uint32_t axis, wl_fixed_t value, void *data)
|
||||||
|
{
|
||||||
|
struct image *image = data;
|
||||||
|
|
||||||
|
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL &&
|
||||||
|
input_get_modifiers(input) == MOD_CONTROL_MASK) {
|
||||||
|
/* set zoom level to 2% per 10 axis units */
|
||||||
|
zoom(image, (1.0 - wl_fixed_to_double(value) / 500.0));
|
||||||
|
|
||||||
|
window_schedule_redraw(image->window);
|
||||||
|
} else if (input_get_modifiers(input) == 0) {
|
||||||
|
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
|
move_viewport(image, 0, wl_fixed_to_double(value));
|
||||||
|
else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||||
|
move_viewport(image, wl_fixed_to_double(value), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fullscreen_handler(struct window *window, void *data)
|
fullscreen_handler(struct window *window, void *data)
|
||||||
{
|
{
|
||||||
|
|
@ -411,40 +347,18 @@ close_handler(void *data)
|
||||||
if (*image->image_counter == 0)
|
if (*image->image_counter == 0)
|
||||||
display_exit(image->display);
|
display_exit(image->display);
|
||||||
|
|
||||||
cairo_surface_destroy(image->image);
|
widget_destroy(image->widget);
|
||||||
|
|
||||||
free(image->filename);
|
|
||||||
|
|
||||||
widget_destroy(image->image_widget);
|
|
||||||
widget_destroy(image->frame_widget);
|
|
||||||
window_destroy(image->window);
|
window_destroy(image->window);
|
||||||
|
|
||||||
free(image);
|
free(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_empty_input_region(struct widget *widget, struct display *display)
|
|
||||||
{
|
|
||||||
struct wl_compositor *compositor;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
struct wl_region *region;
|
|
||||||
|
|
||||||
compositor = display_get_compositor(display);
|
|
||||||
surface = widget_get_wl_surface(widget);
|
|
||||||
region = wl_compositor_create_region(compositor);
|
|
||||||
wl_surface_set_input_region(surface, region);
|
|
||||||
wl_region_destroy(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct image *
|
static struct image *
|
||||||
image_create(struct display *display, const char *filename,
|
image_create(struct display *display, const char *filename,
|
||||||
int *image_counter, int render_intent)
|
int *image_counter)
|
||||||
{
|
{
|
||||||
struct image *image;
|
struct image *image;
|
||||||
struct weston_image *wimage;
|
char *b, *copy, title[512];;
|
||||||
char *b, *copy, title[512];
|
|
||||||
char *err_msg;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
image = zalloc(sizeof *image);
|
image = zalloc(sizeof *image);
|
||||||
if (image == NULL)
|
if (image == NULL)
|
||||||
|
|
@ -465,166 +379,51 @@ image_create(struct display *display, const char *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
image->window = window_create(display);
|
image->window = window_create(display);
|
||||||
|
image->widget = window_frame_create(image->window, image);
|
||||||
window_set_title(image->window, title);
|
window_set_title(image->window, title);
|
||||||
window_set_appid(image->window, "org.freedesktop.weston.wayland-image");
|
|
||||||
image->display = display;
|
image->display = display;
|
||||||
image->image_counter = image_counter;
|
image->image_counter = image_counter;
|
||||||
*image_counter += 1;
|
*image_counter += 1;
|
||||||
image->initialized = false;
|
image->initialized = false;
|
||||||
|
|
||||||
window_set_user_data(image->window, image);
|
window_set_user_data(image->window, image);
|
||||||
|
widget_set_redraw_handler(image->widget, redraw_handler);
|
||||||
|
widget_set_resize_handler(image->widget, resize_handler);
|
||||||
window_set_keyboard_focus_handler(image->window,
|
window_set_keyboard_focus_handler(image->window,
|
||||||
keyboard_focus_handler);
|
keyboard_focus_handler);
|
||||||
window_set_fullscreen_handler(image->window, fullscreen_handler);
|
window_set_fullscreen_handler(image->window, fullscreen_handler);
|
||||||
window_set_close_handler(image->window, close_handler);
|
window_set_close_handler(image->window, close_handler);
|
||||||
|
|
||||||
|
widget_set_enter_handler(image->widget, enter_handler);
|
||||||
|
widget_set_motion_handler(image->widget, motion_handler);
|
||||||
|
widget_set_button_handler(image->widget, button_handler);
|
||||||
|
widget_set_axis_handler(image->widget, axis_handler);
|
||||||
window_set_key_handler(image->window, key_handler);
|
window_set_key_handler(image->window, key_handler);
|
||||||
|
widget_schedule_resize(image->widget, 500, 400);
|
||||||
image->frame_widget = window_frame_create(image->window, image);
|
|
||||||
widget_set_redraw_handler(image->frame_widget, frame_redraw_handler);
|
|
||||||
widget_set_resize_handler(image->frame_widget, frame_resize_handler);
|
|
||||||
|
|
||||||
image->image_widget = window_add_subsurface(image->window, image,
|
|
||||||
SUBSURFACE_SYNCHRONIZED);
|
|
||||||
/* We set the input region of the subsurface where the image is draw as
|
|
||||||
* NULL, as the input region of the parent surface is automatically set
|
|
||||||
* by the toytoolkit. But as the window that finds the widget in a
|
|
||||||
* certain (x, y) position looks for surfaces that are on top first, it
|
|
||||||
* will call the image_widget handlers for input related stuff. */
|
|
||||||
set_empty_input_region(image->image_widget, display);
|
|
||||||
widget_set_redraw_handler(image->image_widget, image_redraw_handler);
|
|
||||||
widget_set_resize_handler(image->image_widget, image_resize_handler);
|
|
||||||
widget_set_enter_handler(image->image_widget, image_enter_handler);
|
|
||||||
widget_set_motion_handler(image->image_widget, image_motion_handler);
|
|
||||||
widget_set_button_handler(image->image_widget, image_button_handler);
|
|
||||||
widget_set_axis_handler(image->image_widget, image_axis_handler);
|
|
||||||
|
|
||||||
wimage = load_cairo_surface_get_user_data(image->image);
|
|
||||||
assert(wimage);
|
|
||||||
if (wimage->icc_profile_data && render_intent != -1) {
|
|
||||||
verbose_print("Image contains ICC file embedded, let's try to use the Wayland\n" \
|
|
||||||
"color-management protocol to set the surface image description\n" \
|
|
||||||
"using this ICC file.\n");
|
|
||||||
ret = widget_set_image_description_icc(image->image_widget,
|
|
||||||
wimage->icc_profile_data->fd,
|
|
||||||
wimage->icc_profile_data->length,
|
|
||||||
wimage->icc_profile_data->offset,
|
|
||||||
render_intent, &err_msg);
|
|
||||||
if (ret) {
|
|
||||||
verbose_print("Successfully set surface image description " \
|
|
||||||
"using ICC file.\n");
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Failed to set surface image description:\n%s\n",
|
|
||||||
err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* TODO: investigate if/how to get colorimetry info from the
|
|
||||||
* PNG/JPEG/etc image. Then use that to create a parametric image
|
|
||||||
* description and set it as the widget image description. Also, if
|
|
||||||
* clients do not enforce us to avoid setting an image description (i.e.
|
|
||||||
* render_intent != -1) but no colorimetry data is present, we can
|
|
||||||
* create a sRGB image description (through parameters) and set it as
|
|
||||||
* the image description to use. For now Weston do not support creating
|
|
||||||
* image description from parameters, that's why we've added only the
|
|
||||||
* code above that depends on ICC profiles. */
|
|
||||||
|
|
||||||
widget_schedule_resize(image->frame_widget, 500, 400);
|
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
print_usage(const char *program_name)
|
|
||||||
{
|
|
||||||
const struct render_intent_info *intent_info;
|
|
||||||
const char *desc;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
fprintf(stderr, "Usage:\n %s [OPTIONS] [FILENAME0] [FILENAME1] ...\n\n" \
|
|
||||||
"Options:\n", program_name);
|
|
||||||
|
|
||||||
fprintf(stderr, "-v or --verbose to print verbose log information.\n\n");
|
|
||||||
|
|
||||||
fprintf(stderr, "-h or --help to open this HELP dialogue.\n\n");
|
|
||||||
|
|
||||||
fprintf(stderr, "-r or --rendering-intent to choose the color-management rendering intent.\n\n " \
|
|
||||||
"The rendering intent is used when an image file has colorimetry data embedded,\n " \
|
|
||||||
"and the compositor should present this image taking this into account. We use\n " \
|
|
||||||
"the Wayland color-management protocol extension to set the image description\n " \
|
|
||||||
"and a rendering intent, which is up to the client to decide. This is optional,\n " \
|
|
||||||
"and if nothing set we'll use 'perceptual'. Supported values:\n\n");
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(cli_ri_table); i++) {
|
|
||||||
/* "off" option does not have a corresponding render_intent_info
|
|
||||||
* object from which we would be able to get the description. */
|
|
||||||
intent_info = render_intent_info_from(cli_ri_table[i].render_intent);
|
|
||||||
if (intent_info)
|
|
||||||
desc = intent_info->desc;
|
|
||||||
else
|
|
||||||
desc = "No render intent (do not set image description)";
|
|
||||||
|
|
||||||
fprintf(stderr, " %s: %s.\n", cli_ri_table[i].cli_option, desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
get_render_intent(int *render_intent, const char *opt_rendering_intent)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* The default, if client does not set anything. */
|
|
||||||
if (!opt_rendering_intent) {
|
|
||||||
*render_intent = RENDER_INTENT_PERCEPTUAL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(cli_ri_table); i++) {
|
|
||||||
if (strcmp(opt_rendering_intent, cli_ri_table[i].cli_option) == 0) {
|
|
||||||
*render_intent = cli_ri_table[i].render_intent;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Error: unknown rendering intent: %s.\n\n",
|
|
||||||
opt_rendering_intent);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct display *d;
|
struct display *d;
|
||||||
int i;
|
int i;
|
||||||
int image_counter = 0;
|
int image_counter = 0;
|
||||||
int render_intent;
|
|
||||||
bool opt_help = false;
|
|
||||||
char *opt_rendering_intent = NULL;
|
|
||||||
struct weston_option cli_options[] = {
|
|
||||||
{ WESTON_OPTION_BOOLEAN, "help", 'h', &opt_help },
|
|
||||||
{ WESTON_OPTION_BOOLEAN, "verbose", 'v', &verbose },
|
|
||||||
{ WESTON_OPTION_STRING, "rendering-intent", 'r', &opt_rendering_intent },
|
|
||||||
};
|
|
||||||
|
|
||||||
parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv);
|
if (argc <= 1 || argv[1][0]=='-') {
|
||||||
|
printf("Usage: %s image...\n", argv[0]);
|
||||||
if (argc <= 1 || opt_help ||
|
|
||||||
get_render_intent(&render_intent, opt_rendering_intent) < 0) {
|
|
||||||
free(opt_rendering_intent);
|
|
||||||
print_usage(argv[0]);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(opt_rendering_intent);
|
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
image_create(d, argv[i], &image_counter, render_intent);
|
image_create(d, argv[i], &image_counter);
|
||||||
|
|
||||||
if (image_counter > 0)
|
if (image_counter > 0)
|
||||||
display_run(d);
|
display_run(d);
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 DENSO CORPORATION
|
* Copyright (C) 2013 DENSO CORPORATION
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
* to deal in the Software without restriction, including without limitation
|
* that the above copyright notice appear in all copies and that both that
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* copyright notice and this permission notice appear in supporting
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* Software.
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
*
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
@ -35,16 +31,10 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
#include <wayland-client-protocol.h>
|
#include "../shared/cairo-util.h"
|
||||||
#include "shared/cairo-util.h"
|
#include "../shared/config-parser.h"
|
||||||
#include <libweston/config-parser.h>
|
#include "../shared/os-compatibility.h"
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/os-compatibility.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
#include "shared/file-util.h"
|
|
||||||
#include "ivi-application-client-protocol.h"
|
#include "ivi-application-client-protocol.h"
|
||||||
#include "ivi-hmi-controller-client-protocol.h"
|
#include "ivi-hmi-controller-client-protocol.h"
|
||||||
|
|
||||||
|
|
@ -143,8 +133,6 @@ hmi_homescreen_launcher {
|
||||||
uint32_t workspace_id;
|
uint32_t workspace_id;
|
||||||
char *icon;
|
char *icon;
|
||||||
char *path;
|
char *path;
|
||||||
char **argv;
|
|
||||||
|
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -165,10 +153,29 @@ hmi_homescreen_setting {
|
||||||
char *cursor_theme;
|
char *cursor_theme;
|
||||||
int32_t cursor_size;
|
int32_t cursor_size;
|
||||||
uint32_t transition_duration;
|
uint32_t transition_duration;
|
||||||
uint32_t surface_id_offset;
|
|
||||||
int32_t screen_num;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
fail_on_null(void *p, size_t size, char *file, int32_t line)
|
||||||
|
{
|
||||||
|
if (size && !p) {
|
||||||
|
fprintf(stderr, "%s(%d) %zd: out of memory\n",
|
||||||
|
file, line, size);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
mem_alloc(size_t size, char *file, int32_t line)
|
||||||
|
{
|
||||||
|
return fail_on_null(calloc(1, size), size, file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
|
||||||
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Event Handler
|
* Event Handler
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
@ -310,10 +317,12 @@ launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
|
||||||
struct hmi_homescreen_launcher *launcher = NULL;
|
struct hmi_homescreen_launcher *launcher = NULL;
|
||||||
|
|
||||||
wl_list_for_each(launcher, launcher_list, link) {
|
wl_list_for_each(launcher, launcher_list, link) {
|
||||||
|
char *argv[] = { NULL };
|
||||||
|
|
||||||
if (surfaceId != launcher->icon_surface_id)
|
if (surfaceId != launcher->icon_surface_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
execute_process(launcher->path, launcher->argv);
|
execute_process(launcher->path, argv);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -594,10 +603,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||||
wl_shm_add_listener(p_wlCtx->wlShm, &shm_listenter, p_wlCtx);
|
wl_shm_add_listener(p_wlCtx->wlShm, &shm_listenter, p_wlCtx);
|
||||||
} else if (!strcmp(interface, "wl_seat")) {
|
} else if (!strcmp(interface, "wl_seat")) {
|
||||||
/* XXX: should be handling multiple wl_seats */
|
|
||||||
if (p_wlCtx->wlSeat)
|
|
||||||
return;
|
|
||||||
|
|
||||||
p_wlCtx->wlSeat =
|
p_wlCtx->wlSeat =
|
||||||
wl_registry_bind(registry, name, &wl_seat_interface, 1);
|
wl_registry_bind(registry, name, &wl_seat_interface, 1);
|
||||||
wl_seat_add_listener(p_wlCtx->wlSeat, &seat_Listener, data);
|
wl_seat_add_listener(p_wlCtx->wlSeat, &seat_Listener, data);
|
||||||
|
|
@ -612,8 +617,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
|
|
||||||
ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl,
|
ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl,
|
||||||
&hmi_controller_listener, p_wlCtx);
|
&hmi_controller_listener, p_wlCtx);
|
||||||
} else if (!strcmp(interface, "wl_output")) {
|
|
||||||
p_wlCtx->hmi_setting->screen_num++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -757,7 +760,7 @@ create_cursors(struct wlContextCommon *cmm)
|
||||||
cmm->wlShm);
|
cmm->wlShm);
|
||||||
|
|
||||||
cmm->cursors =
|
cmm->cursors =
|
||||||
xzalloc(ARRAY_LENGTH(cursors) * sizeof(cmm->cursors[0]));
|
MEM_ALLOC(ARRAY_LENGTH(cursors) * sizeof(cmm->cursors[0]));
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
|
for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
|
||||||
cursor = NULL;
|
cursor = NULL;
|
||||||
|
|
@ -807,8 +810,8 @@ createShmBuffer(struct wlContextStruct *p_wlCtx)
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
fd = os_create_anonymous_file(size);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
size, strerror(errno));
|
size);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -816,7 +819,7 @@ createShmBuffer(struct wlContextStruct *p_wlCtx)
|
||||||
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
if (MAP_FAILED == p_wlCtx->data) {
|
if (MAP_FAILED == p_wlCtx->data) {
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
fprintf(stderr, "mmap failed: %m\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -829,8 +832,7 @@ createShmBuffer(struct wlContextStruct *p_wlCtx)
|
||||||
WL_SHM_FORMAT_ARGB8888);
|
WL_SHM_FORMAT_ARGB8888);
|
||||||
|
|
||||||
if (NULL == p_wlCtx->wlBuffer) {
|
if (NULL == p_wlCtx->wlBuffer) {
|
||||||
fprintf(stderr, "wl_shm_create_buffer failed: %s\n",
|
fprintf(stderr, "wl_shm_create_buffer failed: %m\n");
|
||||||
strerror(errno));
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1034,7 +1036,7 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
|
||||||
if (0 == launcher_count)
|
if (0 == launcher_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
launchers = xzalloc(launcher_count * sizeof(*launchers));
|
launchers = MEM_ALLOC(launcher_count * sizeof(*launchers));
|
||||||
|
|
||||||
wl_list_for_each(launcher, launcher_list, link) {
|
wl_list_for_each(launcher, launcher_list, link) {
|
||||||
launchers[ii] = launcher;
|
launchers[ii] = launcher;
|
||||||
|
|
@ -1052,7 +1054,7 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
|
||||||
for (jj = start; jj <= ii; jj++) {
|
for (jj = start; jj <= ii; jj++) {
|
||||||
struct wlContextStruct *p_wlCtx;
|
struct wlContextStruct *p_wlCtx;
|
||||||
|
|
||||||
p_wlCtx = xzalloc(sizeof(*p_wlCtx));
|
p_wlCtx = MEM_ALLOC(sizeof(*p_wlCtx));
|
||||||
p_wlCtx->cmm = cmm;
|
p_wlCtx->cmm = cmm;
|
||||||
create_ivisurfaceFromFile(p_wlCtx,
|
create_ivisurfaceFromFile(p_wlCtx,
|
||||||
launchers[jj]->icon_surface_id,
|
launchers[jj]->icon_surface_id,
|
||||||
|
|
@ -1065,32 +1067,6 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
|
||||||
free(launchers);
|
free(launchers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **
|
|
||||||
parse_command(char *str)
|
|
||||||
{
|
|
||||||
char **argv;
|
|
||||||
char *saveptr;
|
|
||||||
char *token;
|
|
||||||
int i;
|
|
||||||
int count = 1;
|
|
||||||
|
|
||||||
for (i = 1; str[i]; i++)
|
|
||||||
if (str[i] == ' ' && str[i-1] != ' ')
|
|
||||||
count++;
|
|
||||||
|
|
||||||
argv = xcalloc(count + 1, sizeof(char*));
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
token = strtok_r(str, " ", &saveptr);
|
|
||||||
while (token != NULL) {
|
|
||||||
argv[i++] = token;
|
|
||||||
|
|
||||||
token = strtok_r(NULL, " ", &saveptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method to read out weston.ini to get configuration
|
* Internal method to read out weston.ini to get configuration
|
||||||
*/
|
*/
|
||||||
|
|
@ -1100,12 +1076,11 @@ hmi_homescreen_setting_create(void)
|
||||||
const char *config_file;
|
const char *config_file;
|
||||||
struct weston_config *config = NULL;
|
struct weston_config *config = NULL;
|
||||||
struct weston_config_section *shellSection = NULL;
|
struct weston_config_section *shellSection = NULL;
|
||||||
struct hmi_homescreen_setting *setting = xzalloc(sizeof(*setting));
|
struct hmi_homescreen_setting *setting = MEM_ALLOC(sizeof(*setting));
|
||||||
struct weston_config_section *section = NULL;
|
struct weston_config_section *section = NULL;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
uint32_t workspace_layer_id;
|
uint32_t workspace_layer_id;
|
||||||
uint32_t icon_surface_id = 0;
|
uint32_t icon_surface_id = 0;
|
||||||
char *filename;
|
|
||||||
|
|
||||||
wl_list_init(&setting->workspace_list);
|
wl_list_init(&setting->workspace_list);
|
||||||
wl_list_init(&setting->launcher_list);
|
wl_list_init(&setting->launcher_list);
|
||||||
|
|
@ -1125,70 +1100,56 @@ hmi_homescreen_setting_create(void)
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "workspace-layer-id", &workspace_layer_id, 3000);
|
shellSection, "workspace-layer-id", &workspace_layer_id, 3000);
|
||||||
|
|
||||||
filename = file_name_with_datadir("background.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "background-image", &setting->background.filePath,
|
shellSection, "background-image", &setting->background.filePath,
|
||||||
filename);
|
DATADIR "/weston/background.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "background-id", &setting->background.id, 1001);
|
shellSection, "background-id", &setting->background.id, 1001);
|
||||||
|
|
||||||
filename = file_name_with_datadir("panel.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "panel-image", &setting->panel.filePath,
|
shellSection, "panel-image", &setting->panel.filePath,
|
||||||
filename);
|
DATADIR "/weston/panel.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "panel-id", &setting->panel.id, 1002);
|
shellSection, "panel-id", &setting->panel.id, 1002);
|
||||||
|
|
||||||
filename = file_name_with_datadir("tiling.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "tiling-image", &setting->tiling.filePath,
|
shellSection, "tiling-image", &setting->tiling.filePath,
|
||||||
filename);
|
DATADIR "/weston/tiling.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "tiling-id", &setting->tiling.id, 1003);
|
shellSection, "tiling-id", &setting->tiling.id, 1003);
|
||||||
|
|
||||||
filename = file_name_with_datadir("sidebyside.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "sidebyside-image", &setting->sidebyside.filePath,
|
shellSection, "sidebyside-image", &setting->sidebyside.filePath,
|
||||||
filename);
|
DATADIR "/weston/sidebyside.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "sidebyside-id", &setting->sidebyside.id, 1004);
|
shellSection, "sidebyside-id", &setting->sidebyside.id, 1004);
|
||||||
|
|
||||||
filename = file_name_with_datadir("fullscreen.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "fullscreen-image", &setting->fullscreen.filePath,
|
shellSection, "fullscreen-image", &setting->fullscreen.filePath,
|
||||||
filename);
|
DATADIR "/weston/fullscreen.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "fullscreen-id", &setting->fullscreen.id, 1005);
|
shellSection, "fullscreen-id", &setting->fullscreen.id, 1005);
|
||||||
|
|
||||||
filename = file_name_with_datadir("random.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "random-image", &setting->random.filePath,
|
shellSection, "random-image", &setting->random.filePath,
|
||||||
filename);
|
DATADIR "/weston/random.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "random-id", &setting->random.id, 1006);
|
shellSection, "random-id", &setting->random.id, 1006);
|
||||||
|
|
||||||
filename = file_name_with_datadir("home.png");
|
|
||||||
weston_config_section_get_string(
|
weston_config_section_get_string(
|
||||||
shellSection, "home-image", &setting->home.filePath,
|
shellSection, "home-image", &setting->home.filePath,
|
||||||
filename);
|
DATADIR "/weston/home.png");
|
||||||
free(filename);
|
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
weston_config_section_get_uint(
|
||||||
shellSection, "home-id", &setting->home.id, 1007);
|
shellSection, "home-id", &setting->home.id, 1007);
|
||||||
|
|
||||||
weston_config_section_get_color(
|
weston_config_section_get_uint(
|
||||||
shellSection, "workspace-background-color",
|
shellSection, "workspace-background-color",
|
||||||
&setting->workspace_background.color, 0x99000000);
|
&setting->workspace_background.color, 0x99000000);
|
||||||
|
|
||||||
|
|
@ -1196,35 +1157,21 @@ hmi_homescreen_setting_create(void)
|
||||||
shellSection, "workspace-background-id",
|
shellSection, "workspace-background-id",
|
||||||
&setting->workspace_background.id, 2001);
|
&setting->workspace_background.id, 2001);
|
||||||
|
|
||||||
weston_config_section_get_uint(
|
|
||||||
shellSection, "surface-id-offset", &setting->surface_id_offset, 10);
|
|
||||||
|
|
||||||
icon_surface_id = workspace_layer_id + 1;
|
icon_surface_id = workspace_layer_id + 1;
|
||||||
|
|
||||||
while (weston_config_next_section(config, §ion, &name)) {
|
while (weston_config_next_section(config, §ion, &name)) {
|
||||||
struct hmi_homescreen_launcher *launcher;
|
struct hmi_homescreen_launcher *launcher;
|
||||||
char *command;
|
|
||||||
|
|
||||||
if (strcmp(name, "ivi-launcher") != 0)
|
if (strcmp(name, "ivi-launcher") != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
launcher = xzalloc(sizeof(*launcher));
|
launcher = MEM_ALLOC(sizeof(*launcher));
|
||||||
wl_list_init(&launcher->link);
|
wl_list_init(&launcher->link);
|
||||||
|
|
||||||
weston_config_section_get_string(section, "icon",
|
weston_config_section_get_string(section, "icon",
|
||||||
&launcher->icon, NULL);
|
&launcher->icon, NULL);
|
||||||
|
weston_config_section_get_string(section, "path",
|
||||||
weston_config_section_get_string(section, "command",
|
&launcher->path, NULL);
|
||||||
&command, NULL);
|
|
||||||
if (command == NULL) {
|
|
||||||
weston_config_section_get_string(section, "path",
|
|
||||||
&launcher->path, NULL);
|
|
||||||
launcher->argv = NULL;
|
|
||||||
} else {
|
|
||||||
launcher->argv = parse_command(command);
|
|
||||||
launcher->path = launcher->argv[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
weston_config_section_get_uint(section, "workspace-id",
|
weston_config_section_get_uint(section, "workspace-id",
|
||||||
&launcher->workspace_id, 0);
|
&launcher->workspace_id, 0);
|
||||||
weston_config_section_get_uint(section, "icon-id",
|
weston_config_section_get_uint(section, "icon-id",
|
||||||
|
|
@ -1250,8 +1197,8 @@ hmi_homescreen_setting_create(void)
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct wlContextCommon wlCtxCommon;
|
struct wlContextCommon wlCtxCommon;
|
||||||
struct wlContextStruct *wlCtx_BackGround;
|
struct wlContextStruct wlCtx_BackGround;
|
||||||
struct wlContextStruct *wlCtx_Panel;
|
struct wlContextStruct wlCtx_Panel;
|
||||||
struct wlContextStruct wlCtx_Button_1;
|
struct wlContextStruct wlCtx_Button_1;
|
||||||
struct wlContextStruct wlCtx_Button_2;
|
struct wlContextStruct wlCtx_Button_2;
|
||||||
struct wlContextStruct wlCtx_Button_3;
|
struct wlContextStruct wlCtx_Button_3;
|
||||||
|
|
@ -1262,11 +1209,12 @@ int main(int argc, char **argv)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct hmi_homescreen_setting *hmi_setting;
|
struct hmi_homescreen_setting *hmi_setting;
|
||||||
struct wlContextStruct *pWlCtxSt = NULL;
|
struct wlContextStruct *pWlCtxSt = NULL;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
hmi_setting = hmi_homescreen_setting_create();
|
hmi_setting = hmi_homescreen_setting_create();
|
||||||
|
|
||||||
memset(&wlCtxCommon, 0x00, sizeof(wlCtxCommon));
|
memset(&wlCtxCommon, 0x00, sizeof(wlCtxCommon));
|
||||||
|
memset(&wlCtx_BackGround, 0x00, sizeof(wlCtx_BackGround));
|
||||||
|
memset(&wlCtx_Panel, 0x00, sizeof(wlCtx_Panel));
|
||||||
memset(&wlCtx_Button_1, 0x00, sizeof(wlCtx_Button_1));
|
memset(&wlCtx_Button_1, 0x00, sizeof(wlCtx_Button_1));
|
||||||
memset(&wlCtx_Button_2, 0x00, sizeof(wlCtx_Button_2));
|
memset(&wlCtx_Button_2, 0x00, sizeof(wlCtx_Button_2));
|
||||||
memset(&wlCtx_Button_3, 0x00, sizeof(wlCtx_Button_3));
|
memset(&wlCtx_Button_3, 0x00, sizeof(wlCtx_Button_3));
|
||||||
|
|
@ -1304,9 +1252,6 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlCtx_BackGround = xzalloc(hmi_setting->screen_num * sizeof(struct wlContextStruct));
|
|
||||||
wlCtx_Panel= xzalloc(hmi_setting->screen_num * sizeof(struct wlContextStruct));
|
|
||||||
|
|
||||||
if (wlCtxCommon.hmi_setting->cursor_theme) {
|
if (wlCtxCommon.hmi_setting->cursor_theme) {
|
||||||
create_cursors(&wlCtxCommon);
|
create_cursors(&wlCtxCommon);
|
||||||
|
|
||||||
|
|
@ -1316,6 +1261,8 @@ int main(int argc, char **argv)
|
||||||
wlCtxCommon.current_cursor = CURSOR_LEFT_PTR;
|
wlCtxCommon.current_cursor = CURSOR_LEFT_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlCtx_BackGround.cmm = &wlCtxCommon;
|
||||||
|
wlCtx_Panel.cmm = &wlCtxCommon;
|
||||||
wlCtx_Button_1.cmm = &wlCtxCommon;
|
wlCtx_Button_1.cmm = &wlCtxCommon;
|
||||||
wlCtx_Button_2.cmm = &wlCtxCommon;
|
wlCtx_Button_2.cmm = &wlCtxCommon;
|
||||||
wlCtx_Button_3.cmm = &wlCtxCommon;
|
wlCtx_Button_3.cmm = &wlCtxCommon;
|
||||||
|
|
@ -1324,23 +1271,11 @@ int main(int argc, char **argv)
|
||||||
wlCtx_WorkSpaceBackGround.cmm = &wlCtxCommon;
|
wlCtx_WorkSpaceBackGround.cmm = &wlCtxCommon;
|
||||||
|
|
||||||
/* create desktop widgets */
|
/* create desktop widgets */
|
||||||
create_launchers(&wlCtxCommon, &hmi_setting->launcher_list);
|
create_background(&wlCtx_BackGround, hmi_setting->background.id,
|
||||||
|
hmi_setting->background.filePath);
|
||||||
|
|
||||||
create_workspace_background(&wlCtx_WorkSpaceBackGround,
|
create_panel(&wlCtx_Panel, hmi_setting->panel.id,
|
||||||
&hmi_setting->workspace_background);
|
hmi_setting->panel.filePath);
|
||||||
|
|
||||||
for (i = 0; i < hmi_setting->screen_num; i++) {
|
|
||||||
wlCtx_BackGround[i].cmm = &wlCtxCommon;
|
|
||||||
create_background(&wlCtx_BackGround[i],
|
|
||||||
hmi_setting->background.id +
|
|
||||||
(i * hmi_setting->surface_id_offset),
|
|
||||||
hmi_setting->background.filePath);
|
|
||||||
|
|
||||||
wlCtx_Panel[i].cmm = &wlCtxCommon;
|
|
||||||
create_panel(&wlCtx_Panel[i],
|
|
||||||
hmi_setting->panel.id + (i * hmi_setting->surface_id_offset),
|
|
||||||
hmi_setting->panel.filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
create_button(&wlCtx_Button_1, hmi_setting->tiling.id,
|
create_button(&wlCtx_Button_1, hmi_setting->tiling.id,
|
||||||
hmi_setting->tiling.filePath, 0);
|
hmi_setting->tiling.filePath, 0);
|
||||||
|
|
@ -1354,21 +1289,23 @@ int main(int argc, char **argv)
|
||||||
create_button(&wlCtx_Button_4, hmi_setting->random.id,
|
create_button(&wlCtx_Button_4, hmi_setting->random.id,
|
||||||
hmi_setting->random.filePath, 3);
|
hmi_setting->random.filePath, 3);
|
||||||
|
|
||||||
|
create_workspace_background(&wlCtx_WorkSpaceBackGround,
|
||||||
|
&hmi_setting->workspace_background);
|
||||||
|
|
||||||
|
create_launchers(&wlCtxCommon, &hmi_setting->launcher_list);
|
||||||
|
|
||||||
create_home_button(&wlCtx_HomeButton, hmi_setting->home.id,
|
create_home_button(&wlCtx_HomeButton, hmi_setting->home.id,
|
||||||
hmi_setting->home.filePath);
|
hmi_setting->home.filePath);
|
||||||
|
|
||||||
UI_ready(wlCtxCommon.hmiCtrl);
|
UI_ready(wlCtxCommon.hmiCtrl);
|
||||||
|
|
||||||
while (ret != -1)
|
while(ret != -1)
|
||||||
ret = wl_display_dispatch(wlCtxCommon.wlDisplay);
|
ret = wl_display_dispatch(wlCtxCommon.wlDisplay);
|
||||||
|
|
||||||
wl_list_for_each(pWlCtxSt, &wlCtxCommon.list_wlContextStruct, link) {
|
wl_list_for_each(pWlCtxSt, &wlCtxCommon.list_wlContextStruct, link) {
|
||||||
destroyWLContextStruct(pWlCtxSt);
|
destroyWLContextStruct(pWlCtxSt);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(wlCtx_BackGround);
|
|
||||||
free(wlCtx_Panel);
|
|
||||||
|
|
||||||
destroyWLContextCommon(&wlCtxCommon);
|
destroyWLContextCommon(&wlCtxCommon);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -2,49 +2,44 @@
|
||||||
* Copyright © 2012 Openismus GmbH
|
* Copyright © 2012 Openismus GmbH
|
||||||
* Copyright © 2012 Intel Corporation
|
* Copyright © 2012 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
* to deal in the Software without restriction, including without limitation
|
* that the above copyright notice appear in all copies and that both that
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* copyright notice and this permission notice appear in supporting
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* Software.
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
*
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "input-method-unstable-v1-client-protocol.h"
|
#include "input-method-client-protocol.h"
|
||||||
#include "text-input-unstable-v1-client-protocol.h"
|
#include "text-client-protocol.h"
|
||||||
#include "shared/xalloc.h"
|
|
||||||
|
|
||||||
struct keyboard;
|
struct keyboard;
|
||||||
|
|
||||||
struct virtual_keyboard {
|
struct virtual_keyboard {
|
||||||
struct zwp_input_panel_v1 *input_panel;
|
struct wl_input_panel *input_panel;
|
||||||
struct zwp_input_method_v1 *input_method;
|
struct wl_input_method *input_method;
|
||||||
struct zwp_input_method_context_v1 *context;
|
struct wl_input_method_context *context;
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct output *output;
|
struct output *output;
|
||||||
char *preedit_string;
|
char *preedit_string;
|
||||||
|
|
@ -59,9 +54,6 @@ struct virtual_keyboard {
|
||||||
char *surrounding_text;
|
char *surrounding_text;
|
||||||
uint32_t surrounding_cursor;
|
uint32_t surrounding_cursor;
|
||||||
struct keyboard *keyboard;
|
struct keyboard *keyboard;
|
||||||
bool toplevel;
|
|
||||||
bool overlay;
|
|
||||||
struct zwp_input_panel_surface_v1 *ips;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum key_type {
|
enum key_type {
|
||||||
|
|
@ -223,7 +215,7 @@ static const struct layout normal_layout = {
|
||||||
12,
|
12,
|
||||||
4,
|
4,
|
||||||
"en",
|
"en",
|
||||||
ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR
|
WL_TEXT_INPUT_TEXT_DIRECTION_LTR
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct layout numeric_layout = {
|
static const struct layout numeric_layout = {
|
||||||
|
|
@ -232,7 +224,7 @@ static const struct layout numeric_layout = {
|
||||||
12,
|
12,
|
||||||
2,
|
2,
|
||||||
"en",
|
"en",
|
||||||
ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR
|
WL_TEXT_INPUT_TEXT_DIRECTION_LTR
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct layout arabic_layout = {
|
static const struct layout arabic_layout = {
|
||||||
|
|
@ -241,7 +233,7 @@ static const struct layout arabic_layout = {
|
||||||
13,
|
13,
|
||||||
4,
|
4,
|
||||||
"ar",
|
"ar",
|
||||||
ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL
|
WL_TEXT_INPUT_TEXT_DIRECTION_RTL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *style_labels[] = {
|
static const char *style_labels[] = {
|
||||||
|
|
@ -276,10 +268,11 @@ static void __attribute__ ((format (printf, 1, 2)))
|
||||||
dbg(const char *fmt, ...)
|
dbg(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
int l;
|
||||||
va_list argp;
|
va_list argp;
|
||||||
|
|
||||||
va_start(argp, fmt);
|
va_start(argp, fmt);
|
||||||
vfprintf(stderr, fmt, argp);
|
l = vfprintf(stderr, fmt, argp);
|
||||||
va_end(argp);
|
va_end(argp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -345,8 +338,8 @@ static const struct layout *
|
||||||
get_current_layout(struct virtual_keyboard *keyboard)
|
get_current_layout(struct virtual_keyboard *keyboard)
|
||||||
{
|
{
|
||||||
switch (keyboard->content_purpose) {
|
switch (keyboard->content_purpose) {
|
||||||
case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS:
|
case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
|
||||||
case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER:
|
case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
|
||||||
return &numeric_layout;
|
return &numeric_layout;
|
||||||
default:
|
default:
|
||||||
if (keyboard->preferred_language &&
|
if (keyboard->preferred_language &&
|
||||||
|
|
@ -377,7 +370,7 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
|
cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
|
||||||
cairo_clip(cr);
|
cairo_clip(cr);
|
||||||
|
|
||||||
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
cairo_select_font_face(cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
||||||
cairo_set_font_size(cr, 16);
|
cairo_set_font_size(cr, 16);
|
||||||
|
|
||||||
cairo_translate(cr, allocation.x, allocation.y);
|
cairo_translate(cr, allocation.x, allocation.y);
|
||||||
|
|
@ -433,11 +426,11 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
|
||||||
strlen(keyboard->preedit_string) == 0)
|
strlen(keyboard->preedit_string) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zwp_input_method_context_v1_cursor_position(keyboard->context,
|
wl_input_method_context_cursor_position(keyboard->context,
|
||||||
0, 0);
|
0, 0);
|
||||||
zwp_input_method_context_v1_commit_string(keyboard->context,
|
wl_input_method_context_commit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
keyboard->preedit_string);
|
keyboard->preedit_string);
|
||||||
|
|
||||||
if (keyboard->surrounding_text) {
|
if (keyboard->surrounding_text) {
|
||||||
surrounding_text = insert_text(keyboard->surrounding_text,
|
surrounding_text = insert_text(keyboard->surrounding_text,
|
||||||
|
|
@ -462,18 +455,18 @@ virtual_keyboard_send_preedit(struct virtual_keyboard *keyboard,
|
||||||
uint32_t index = strlen(keyboard->preedit_string);
|
uint32_t index = strlen(keyboard->preedit_string);
|
||||||
|
|
||||||
if (keyboard->preedit_style)
|
if (keyboard->preedit_style)
|
||||||
zwp_input_method_context_v1_preedit_styling(keyboard->context,
|
wl_input_method_context_preedit_styling(keyboard->context,
|
||||||
0,
|
0,
|
||||||
strlen(keyboard->preedit_string),
|
strlen(keyboard->preedit_string),
|
||||||
keyboard->preedit_style);
|
keyboard->preedit_style);
|
||||||
if (cursor > 0)
|
if (cursor > 0)
|
||||||
index = cursor;
|
index = cursor;
|
||||||
zwp_input_method_context_v1_preedit_cursor(keyboard->context,
|
wl_input_method_context_preedit_cursor(keyboard->context,
|
||||||
index);
|
index);
|
||||||
zwp_input_method_context_v1_preedit_string(keyboard->context,
|
wl_input_method_context_preedit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
keyboard->preedit_string,
|
keyboard->preedit_string,
|
||||||
keyboard->preedit_string);
|
keyboard->preedit_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
@ -505,12 +498,12 @@ delete_before_cursor(struct virtual_keyboard *keyboard)
|
||||||
|
|
||||||
end = keyboard->surrounding_text + keyboard->surrounding_cursor;
|
end = keyboard->surrounding_text + keyboard->surrounding_cursor;
|
||||||
|
|
||||||
zwp_input_method_context_v1_delete_surrounding_text(keyboard->context,
|
wl_input_method_context_delete_surrounding_text(keyboard->context,
|
||||||
start - keyboard->surrounding_text,
|
(start - keyboard->surrounding_text) - keyboard->surrounding_cursor,
|
||||||
end - start);
|
end - start);
|
||||||
zwp_input_method_context_v1_commit_string(keyboard->context,
|
wl_input_method_context_commit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
"");
|
"");
|
||||||
|
|
||||||
/* Update surrounding text */
|
/* Update surrounding text */
|
||||||
keyboard->surrounding_cursor = start - keyboard->surrounding_text;
|
keyboard->surrounding_cursor = start - keyboard->surrounding_text;
|
||||||
|
|
@ -577,10 +570,10 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
|
||||||
break;
|
break;
|
||||||
case keytype_enter:
|
case keytype_enter:
|
||||||
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
||||||
zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
|
wl_input_method_context_keysym(keyboard->keyboard->context,
|
||||||
display_get_serial(keyboard->keyboard->display),
|
display_get_serial(keyboard->keyboard->display),
|
||||||
time,
|
time,
|
||||||
XKB_KEY_Return, key_state, mod_mask);
|
XKB_KEY_Return, key_state, mod_mask);
|
||||||
break;
|
break;
|
||||||
case keytype_space:
|
case keytype_space:
|
||||||
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
|
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
|
||||||
|
|
@ -621,38 +614,38 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
|
||||||
break;
|
break;
|
||||||
case keytype_tab:
|
case keytype_tab:
|
||||||
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
||||||
zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
|
wl_input_method_context_keysym(keyboard->keyboard->context,
|
||||||
display_get_serial(keyboard->keyboard->display),
|
display_get_serial(keyboard->keyboard->display),
|
||||||
time,
|
time,
|
||||||
XKB_KEY_Tab, key_state, mod_mask);
|
XKB_KEY_Tab, key_state, mod_mask);
|
||||||
break;
|
break;
|
||||||
case keytype_arrow_up:
|
case keytype_arrow_up:
|
||||||
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
||||||
zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
|
wl_input_method_context_keysym(keyboard->keyboard->context,
|
||||||
display_get_serial(keyboard->keyboard->display),
|
display_get_serial(keyboard->keyboard->display),
|
||||||
time,
|
time,
|
||||||
XKB_KEY_Up, key_state, mod_mask);
|
XKB_KEY_Up, key_state, mod_mask);
|
||||||
break;
|
break;
|
||||||
case keytype_arrow_left:
|
case keytype_arrow_left:
|
||||||
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
||||||
zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
|
wl_input_method_context_keysym(keyboard->keyboard->context,
|
||||||
display_get_serial(keyboard->keyboard->display),
|
display_get_serial(keyboard->keyboard->display),
|
||||||
time,
|
time,
|
||||||
XKB_KEY_Left, key_state, mod_mask);
|
XKB_KEY_Left, key_state, mod_mask);
|
||||||
break;
|
break;
|
||||||
case keytype_arrow_right:
|
case keytype_arrow_right:
|
||||||
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
||||||
zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
|
wl_input_method_context_keysym(keyboard->keyboard->context,
|
||||||
display_get_serial(keyboard->keyboard->display),
|
display_get_serial(keyboard->keyboard->display),
|
||||||
time,
|
time,
|
||||||
XKB_KEY_Right, key_state, mod_mask);
|
XKB_KEY_Right, key_state, mod_mask);
|
||||||
break;
|
break;
|
||||||
case keytype_arrow_down:
|
case keytype_arrow_down:
|
||||||
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
virtual_keyboard_commit_preedit(keyboard->keyboard);
|
||||||
zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
|
wl_input_method_context_keysym(keyboard->keyboard->context,
|
||||||
display_get_serial(keyboard->keyboard->display),
|
display_get_serial(keyboard->keyboard->display),
|
||||||
time,
|
time,
|
||||||
XKB_KEY_Down, key_state, mod_mask);
|
XKB_KEY_Down, key_state, mod_mask);
|
||||||
break;
|
break;
|
||||||
case keytype_style:
|
case keytype_style:
|
||||||
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
|
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
|
||||||
|
|
@ -756,7 +749,7 @@ touch_up_handler(struct widget *widget, struct input *input,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_surrounding_text(void *data,
|
handle_surrounding_text(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
const char *text,
|
const char *text,
|
||||||
uint32_t cursor,
|
uint32_t cursor,
|
||||||
uint32_t anchor)
|
uint32_t anchor)
|
||||||
|
|
@ -771,7 +764,7 @@ handle_surrounding_text(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_reset(void *data,
|
handle_reset(void *data,
|
||||||
struct zwp_input_method_context_v1 *context)
|
struct wl_input_method_context *context)
|
||||||
{
|
{
|
||||||
struct virtual_keyboard *keyboard = data;
|
struct virtual_keyboard *keyboard = data;
|
||||||
|
|
||||||
|
|
@ -785,7 +778,7 @@ handle_reset(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_content_type(void *data,
|
handle_content_type(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
uint32_t hint,
|
uint32_t hint,
|
||||||
uint32_t purpose)
|
uint32_t purpose)
|
||||||
{
|
{
|
||||||
|
|
@ -797,7 +790,7 @@ handle_content_type(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_invoke_action(void *data,
|
handle_invoke_action(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
uint32_t button,
|
uint32_t button,
|
||||||
uint32_t index)
|
uint32_t index)
|
||||||
{
|
{
|
||||||
|
|
@ -811,7 +804,7 @@ handle_invoke_action(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_commit_state(void *data,
|
handle_commit_state(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
struct virtual_keyboard *keyboard = data;
|
struct virtual_keyboard *keyboard = data;
|
||||||
|
|
@ -828,19 +821,15 @@ handle_commit_state(void *data,
|
||||||
layout->columns * key_width,
|
layout->columns * key_width,
|
||||||
layout->rows * key_height);
|
layout->rows * key_height);
|
||||||
|
|
||||||
zwp_input_method_context_v1_language(context,
|
wl_input_method_context_language(context, keyboard->serial, layout->language);
|
||||||
keyboard->serial,
|
wl_input_method_context_text_direction(context, keyboard->serial, layout->text_direction);
|
||||||
layout->language);
|
|
||||||
zwp_input_method_context_v1_text_direction(context,
|
|
||||||
keyboard->serial,
|
|
||||||
layout->text_direction);
|
|
||||||
|
|
||||||
widget_schedule_redraw(keyboard->keyboard->widget);
|
widget_schedule_redraw(keyboard->keyboard->widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_preferred_language(void *data,
|
handle_preferred_language(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
const char *language)
|
const char *language)
|
||||||
{
|
{
|
||||||
struct virtual_keyboard *keyboard = data;
|
struct virtual_keyboard *keyboard = data;
|
||||||
|
|
@ -854,7 +843,7 @@ handle_preferred_language(void *data,
|
||||||
keyboard->preferred_language = strdup(language);
|
keyboard->preferred_language = strdup(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_input_method_context_v1_listener input_method_context_listener = {
|
static const struct wl_input_method_context_listener input_method_context_listener = {
|
||||||
handle_surrounding_text,
|
handle_surrounding_text,
|
||||||
handle_reset,
|
handle_reset,
|
||||||
handle_content_type,
|
handle_content_type,
|
||||||
|
|
@ -865,8 +854,8 @@ static const struct zwp_input_method_context_v1_listener input_method_context_li
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_method_activate(void *data,
|
input_method_activate(void *data,
|
||||||
struct zwp_input_method_v1 *input_method,
|
struct wl_input_method *input_method,
|
||||||
struct zwp_input_method_context_v1 *context)
|
struct wl_input_method_context *context)
|
||||||
{
|
{
|
||||||
struct virtual_keyboard *keyboard = data;
|
struct virtual_keyboard *keyboard = data;
|
||||||
struct wl_array modifiers_map;
|
struct wl_array modifiers_map;
|
||||||
|
|
@ -875,7 +864,7 @@ input_method_activate(void *data,
|
||||||
keyboard->keyboard->state = KEYBOARD_STATE_DEFAULT;
|
keyboard->keyboard->state = KEYBOARD_STATE_DEFAULT;
|
||||||
|
|
||||||
if (keyboard->context)
|
if (keyboard->context)
|
||||||
zwp_input_method_context_v1_destroy(keyboard->context);
|
wl_input_method_context_destroy(keyboard->context);
|
||||||
|
|
||||||
if (keyboard->preedit_string)
|
if (keyboard->preedit_string)
|
||||||
free(keyboard->preedit_string);
|
free(keyboard->preedit_string);
|
||||||
|
|
@ -891,15 +880,15 @@ input_method_activate(void *data,
|
||||||
keyboard->serial = 0;
|
keyboard->serial = 0;
|
||||||
|
|
||||||
keyboard->context = context;
|
keyboard->context = context;
|
||||||
zwp_input_method_context_v1_add_listener(context,
|
wl_input_method_context_add_listener(context,
|
||||||
&input_method_context_listener,
|
&input_method_context_listener,
|
||||||
keyboard);
|
keyboard);
|
||||||
|
|
||||||
wl_array_init(&modifiers_map);
|
wl_array_init(&modifiers_map);
|
||||||
keysym_modifiers_add(&modifiers_map, "Shift");
|
keysym_modifiers_add(&modifiers_map, "Shift");
|
||||||
keysym_modifiers_add(&modifiers_map, "Control");
|
keysym_modifiers_add(&modifiers_map, "Control");
|
||||||
keysym_modifiers_add(&modifiers_map, "Mod1");
|
keysym_modifiers_add(&modifiers_map, "Mod1");
|
||||||
zwp_input_method_context_v1_modifiers_map(context, &modifiers_map);
|
wl_input_method_context_modifiers_map(context, &modifiers_map);
|
||||||
keyboard->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
|
keyboard->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
|
||||||
wl_array_release(&modifiers_map);
|
wl_array_release(&modifiers_map);
|
||||||
|
|
||||||
|
|
@ -909,31 +898,27 @@ input_method_activate(void *data,
|
||||||
layout->columns * key_width,
|
layout->columns * key_width,
|
||||||
layout->rows * key_height);
|
layout->rows * key_height);
|
||||||
|
|
||||||
zwp_input_method_context_v1_language(context,
|
wl_input_method_context_language(context, keyboard->serial, layout->language);
|
||||||
keyboard->serial,
|
wl_input_method_context_text_direction(context, keyboard->serial, layout->text_direction);
|
||||||
layout->language);
|
|
||||||
zwp_input_method_context_v1_text_direction(context,
|
|
||||||
keyboard->serial,
|
|
||||||
layout->text_direction);
|
|
||||||
|
|
||||||
widget_schedule_redraw(keyboard->keyboard->widget);
|
widget_schedule_redraw(keyboard->keyboard->widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_method_deactivate(void *data,
|
input_method_deactivate(void *data,
|
||||||
struct zwp_input_method_v1 *input_method,
|
struct wl_input_method *input_method,
|
||||||
struct zwp_input_method_context_v1 *context)
|
struct wl_input_method_context *context)
|
||||||
{
|
{
|
||||||
struct virtual_keyboard *keyboard = data;
|
struct virtual_keyboard *keyboard = data;
|
||||||
|
|
||||||
if (!keyboard->context)
|
if (!keyboard->context)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zwp_input_method_context_v1_destroy(keyboard->context);
|
wl_input_method_context_destroy(keyboard->context);
|
||||||
keyboard->context = NULL;
|
keyboard->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_input_method_v1_listener input_method_listener = {
|
static const struct wl_input_method_listener input_method_listener = {
|
||||||
input_method_activate,
|
input_method_activate,
|
||||||
input_method_deactivate
|
input_method_deactivate
|
||||||
};
|
};
|
||||||
|
|
@ -944,56 +929,23 @@ global_handler(struct display *display, uint32_t name,
|
||||||
{
|
{
|
||||||
struct virtual_keyboard *keyboard = data;
|
struct virtual_keyboard *keyboard = data;
|
||||||
|
|
||||||
if (!strcmp(interface, "zwp_input_panel_v1")) {
|
if (!strcmp(interface, "wl_input_panel")) {
|
||||||
keyboard->input_panel =
|
keyboard->input_panel =
|
||||||
display_bind(display, name, &zwp_input_panel_v1_interface, 1);
|
display_bind(display, name, &wl_input_panel_interface, 1);
|
||||||
} else if (!strcmp(interface, "zwp_input_method_v1")) {
|
} else if (!strcmp(interface, "wl_input_method")) {
|
||||||
keyboard->input_method =
|
keyboard->input_method =
|
||||||
display_bind(display, name,
|
display_bind(display, name,
|
||||||
&zwp_input_method_v1_interface, 1);
|
&wl_input_method_interface, 1);
|
||||||
zwp_input_method_v1_add_listener(keyboard->input_method,
|
wl_input_method_add_listener(keyboard->input_method, &input_method_listener, keyboard);
|
||||||
&input_method_listener,
|
|
||||||
keyboard);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_toplevel(struct output *output, struct virtual_keyboard *virtual_keyboard)
|
keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard)
|
||||||
{
|
|
||||||
zwp_input_panel_surface_v1_set_toplevel(virtual_keyboard->ips,
|
|
||||||
output_get_wl_output(output),
|
|
||||||
ZWP_INPUT_PANEL_SURFACE_V1_POSITION_CENTER_BOTTOM);
|
|
||||||
virtual_keyboard->toplevel = true;
|
|
||||||
virtual_keyboard->overlay = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_overlay(struct output *output, struct virtual_keyboard *virtual_keyboard)
|
|
||||||
{
|
|
||||||
zwp_input_panel_surface_v1_set_overlay_panel(virtual_keyboard->ips);
|
|
||||||
virtual_keyboard->toplevel = false;
|
|
||||||
virtual_keyboard->overlay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
display_output_handler(struct output *output, void *data) {
|
|
||||||
struct virtual_keyboard *keyboard = data;
|
|
||||||
const char *type = getenv("WESTON_KEYBOARD_SURFACE_TYPE");
|
|
||||||
|
|
||||||
if (type && strcasecmp("overlay", type) == 0) {
|
|
||||||
if (!keyboard->overlay)
|
|
||||||
set_overlay(output, keyboard);
|
|
||||||
} else {
|
|
||||||
if (!keyboard->toplevel)
|
|
||||||
set_toplevel(output, keyboard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_create(struct virtual_keyboard *virtual_keyboard)
|
|
||||||
{
|
{
|
||||||
struct keyboard *keyboard;
|
struct keyboard *keyboard;
|
||||||
const struct layout *layout;
|
const struct layout *layout;
|
||||||
|
struct wl_input_panel_surface *ips;
|
||||||
|
|
||||||
layout = get_current_layout(virtual_keyboard);
|
layout = get_current_layout(virtual_keyboard);
|
||||||
|
|
||||||
|
|
@ -1002,14 +954,9 @@ keyboard_create(struct virtual_keyboard *virtual_keyboard)
|
||||||
keyboard->window = window_create_custom(virtual_keyboard->display);
|
keyboard->window = window_create_custom(virtual_keyboard->display);
|
||||||
keyboard->widget = window_add_widget(keyboard->window, keyboard);
|
keyboard->widget = window_add_widget(keyboard->window, keyboard);
|
||||||
|
|
||||||
virtual_keyboard->ips =
|
|
||||||
zwp_input_panel_v1_get_input_panel_surface(virtual_keyboard->input_panel,
|
|
||||||
window_get_wl_surface(keyboard->window));
|
|
||||||
virtual_keyboard->keyboard = keyboard;
|
virtual_keyboard->keyboard = keyboard;
|
||||||
|
|
||||||
window_set_title(keyboard->window, "Virtual keyboard");
|
window_set_title(keyboard->window, "Virtual keyboard");
|
||||||
window_set_appid(keyboard->window,
|
|
||||||
"org.freedesktop.weston.virtual-keyboard");
|
|
||||||
window_set_user_data(keyboard->window, keyboard);
|
window_set_user_data(keyboard->window, keyboard);
|
||||||
|
|
||||||
widget_set_redraw_handler(keyboard->widget, redraw_handler);
|
widget_set_redraw_handler(keyboard->widget, redraw_handler);
|
||||||
|
|
@ -1022,38 +969,26 @@ keyboard_create(struct virtual_keyboard *virtual_keyboard)
|
||||||
layout->columns * key_width,
|
layout->columns * key_width,
|
||||||
layout->rows * key_height);
|
layout->rows * key_height);
|
||||||
|
|
||||||
display_set_output_configure_handler(virtual_keyboard->display,
|
|
||||||
display_output_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
ips = wl_input_panel_get_input_panel_surface(virtual_keyboard->input_panel,
|
||||||
keyboard_destroy(struct virtual_keyboard *virtual_keyboard)
|
window_get_wl_surface(keyboard->window));
|
||||||
{
|
|
||||||
if (virtual_keyboard->ips)
|
|
||||||
zwp_input_panel_surface_v1_destroy(virtual_keyboard->ips);
|
|
||||||
|
|
||||||
if (virtual_keyboard->input_panel)
|
wl_input_panel_surface_set_toplevel(ips,
|
||||||
zwp_input_panel_v1_destroy(virtual_keyboard->input_panel);
|
output_get_wl_output(output),
|
||||||
|
WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM);
|
||||||
if (virtual_keyboard->input_method)
|
|
||||||
zwp_input_method_v1_destroy(virtual_keyboard->input_method);
|
|
||||||
|
|
||||||
widget_destroy(virtual_keyboard->keyboard->widget);
|
|
||||||
window_destroy(virtual_keyboard->keyboard->window);
|
|
||||||
free(virtual_keyboard->keyboard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct virtual_keyboard virtual_keyboard;
|
struct virtual_keyboard virtual_keyboard;
|
||||||
|
struct output *output;
|
||||||
|
|
||||||
memset(&virtual_keyboard, 0, sizeof virtual_keyboard);
|
memset(&virtual_keyboard, 0, sizeof virtual_keyboard);
|
||||||
|
|
||||||
virtual_keyboard.display = display_create(&argc, argv);
|
virtual_keyboard.display = display_create(&argc, argv);
|
||||||
if (virtual_keyboard.display == NULL) {
|
if (virtual_keyboard.display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1065,12 +1000,10 @@ main(int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard_create(&virtual_keyboard);
|
output = display_get_output(virtual_keyboard.display);
|
||||||
|
keyboard_create(output, &virtual_keyboard);
|
||||||
|
|
||||||
display_run(virtual_keyboard.display);
|
display_run(virtual_keyboard.display);
|
||||||
|
|
||||||
keyboard_destroy(&virtual_keyboard);
|
|
||||||
display_destroy(virtual_keyboard.display);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
692
clients/matrix3.xpm
Normal file
|
|
@ -0,0 +1,692 @@
|
||||||
|
/* XPM */
|
||||||
|
static char * matrix3_xpm[] = {
|
||||||
|
"512 598 91 1",
|
||||||
|
" c None",
|
||||||
|
". c #020202",
|
||||||
|
"+ c #020602",
|
||||||
|
"@ c #020A02",
|
||||||
|
"# c #061606",
|
||||||
|
"$ c #071E07",
|
||||||
|
"% c #061206",
|
||||||
|
"& c #020E02",
|
||||||
|
"* c #061A06",
|
||||||
|
"= c #0A220A",
|
||||||
|
"- c #0B310E",
|
||||||
|
"; c #0E3E12",
|
||||||
|
"> c #0A260A",
|
||||||
|
", c #0E2A0E",
|
||||||
|
"' c #134A16",
|
||||||
|
") c #0E5A0E",
|
||||||
|
"! c #104616",
|
||||||
|
"~ c #124E1A",
|
||||||
|
"{ c #166A12",
|
||||||
|
"] c #127212",
|
||||||
|
"^ c #1E921A",
|
||||||
|
"/ c #168A16",
|
||||||
|
"( c #1A5E2A",
|
||||||
|
"_ c #165626",
|
||||||
|
": c #227232",
|
||||||
|
"< c #3A965A",
|
||||||
|
"[ c #268A3E",
|
||||||
|
"} c #227A37",
|
||||||
|
"| c #1E662F",
|
||||||
|
"1 c #1E6A32",
|
||||||
|
"2 c #227E3A",
|
||||||
|
"3 c #16320E",
|
||||||
|
"4 c #36822A",
|
||||||
|
"5 c #4A9E72",
|
||||||
|
"6 c #4AAA6E",
|
||||||
|
"7 c #42862A",
|
||||||
|
"8 c #4DAE7B",
|
||||||
|
"9 c #1A3612",
|
||||||
|
"0 c #224616",
|
||||||
|
"a c #264E16",
|
||||||
|
"b c #32621E",
|
||||||
|
"c c #1A3E12",
|
||||||
|
"d c #265A1A",
|
||||||
|
"e c #367622",
|
||||||
|
"f c #3E7626",
|
||||||
|
"g c #5A8636",
|
||||||
|
"h c #4A962E",
|
||||||
|
"i c #669A3E",
|
||||||
|
"j c #82AE52",
|
||||||
|
"k c #3E9222",
|
||||||
|
"l c #4AA232",
|
||||||
|
"m c #66AA3E",
|
||||||
|
"n c #6ABA3E",
|
||||||
|
"o c #82BE4A",
|
||||||
|
"p c #76AA4A",
|
||||||
|
"q c #96BE5E",
|
||||||
|
"r c #1A9E1A",
|
||||||
|
"s c #22BE22",
|
||||||
|
"t c #2AD62A",
|
||||||
|
"u c #6AEE8A",
|
||||||
|
"v c #4AEE4A",
|
||||||
|
"w c #50CE94",
|
||||||
|
"x c #26CB26",
|
||||||
|
"y c #26D226",
|
||||||
|
"z c #1EAE1E",
|
||||||
|
"A c #2ADE2A",
|
||||||
|
"B c #2AE62A",
|
||||||
|
"C c #2EEE2E",
|
||||||
|
"D c #56F24A",
|
||||||
|
"E c #66F65E",
|
||||||
|
"F c #127E12",
|
||||||
|
"G c #42EE42",
|
||||||
|
"H c #3AEE3A",
|
||||||
|
"I c #2B9F4D",
|
||||||
|
"J c #3EBA6E",
|
||||||
|
"K c #2AAA4E",
|
||||||
|
"L c #56F262",
|
||||||
|
"M c #66C29E",
|
||||||
|
"N c #68D6B2",
|
||||||
|
"O c #52BE8A",
|
||||||
|
"P c #3CAE67",
|
||||||
|
"Q c #2A9646",
|
||||||
|
"R c #6AC6AA",
|
||||||
|
"S c #6ACAA2",
|
||||||
|
"T c #C2D672",
|
||||||
|
"U c #B2D26A",
|
||||||
|
"V c #4EAA2E",
|
||||||
|
"W c #9ECE5A",
|
||||||
|
"X c #5EB632",
|
||||||
|
"Y c #62C299",
|
||||||
|
"Z c #8ACA4A",
|
||||||
|
"..............................................................................................................++@@@@@@+++....................+@@@@@@@+........................................................................................................................++@@@@@@+....................+@@@@@@@+................................................................................................................................................................................................+@@@+.......",
|
||||||
|
".............................................................................................................+@##$$$$$#%@+..................+&##$$$$#&+......................................................................................................................+&#$$$$$#%+..................+&#$$$$$#&+..............................................................................................................................................................................................+&#$#%+......",
|
||||||
|
"............................................+@&%#***%&@+...................+@@@@@@@@@+....................@##=--;;;;;;;->$%@...............%#>-;;;;;-,*&+...................+&%&&@+............................................................@&@@+.......................@%*--')))!;-=%@+..............%*-;;!!!!;-*&+.....................+&%###%@+............................................................................................................................................................@#$-;;;-=*@+...",
|
||||||
|
"............................................%**==,-->=*%@.................@%*$$$$$$$*##%&+................%$--;~'))){))!;-=*&.............&#--;)){)~!--=#@...............+&###$$**%@+........................................................@%**$*##&@....................&=,;']^^/])';,*@.............&$-;)){//]);-=#@+...................@#*==>=*#%@.........................................................................................................................................................&*>;!~))!->*@...",
|
||||||
|
"...........................................+%**===,,>**%%+..............+@&%************%@+..............@#*,;!~~))())_';-=*@............+%*=-;~({_~;-=**%+.............+&%*$**$**%@+........................................................&&#*$*#$%%+...................@*=-!:<<[_~!-,#@.............@=-;'(}[<}_-=*#@+..................@%#**>>>*%%&+.......................................................................................................................................................+%$=-!)))!-,$@...",
|
||||||
|
"..........................................+&*$>,-;;-->$$%+..............@&$$$$>$$$$$>$$*#%&@.............@#>-;'((|(||1(~!--$%+..........+&**,-;_:}2(~;->$#&@............@%*$=>>=>$$#%+......................................................+&$*>=>=**%@..................@&*>3_456<:(~;,*@............+&=;!(:786<(;,$*%+.................@&#*>---,>$##@+......................................................................................................................................................@%*-;_|1|(;-*&...",
|
||||||
|
"..........................................@*=,90abbba3,*$&+............@%#*,333333333393>$#@+............&*,cdbbeeff4febd0;=*+.........+@%>-cabfghifbdc9=$#&+.........+&%$,39c09c3,=$@.......................++@@@++.......................+&#,39c993=*%+................+&*=3;bijjifbac,*@............@&=;adfijjifc9>*#@................+%*>,9abdac3*$&+......................................................................................................................................................&*>9aefggfa;=%...",
|
||||||
|
".........................................&*=;abgijjigbc9=#@...........@%*,c0db{b_0_db:bdc3=$&+..........&%=9de47kkklllk4ebac=#........+%$>c'be7mnonphebd03=*&+.......+&%=3cd:eeee(a3=*@....................+&&*=*$*##%@+..................+%*30d:1e(d09=%+..............+&$>9cdfmqom7bd09*&............@*>9db4ioqpgbac3=%+..............@#*>;afgmiifac,*%+...................+@&%#&@+........................................................................................................................+&*,;abipnpif03#+..",
|
||||||
|
"........................................&$-~]rstuuuvws/{;-*+........+&#-;)]rsxyszrrssysz/{';$&........+%=-;{/yABCCBCACCtyz^];,+......+%,;!{/sABDvuEvBAsrF{~-$&......@#=-;)/zxBBAAs^{!-*&.................@%$,-;;;!;;;-,*&+...............@*-;)/zytAsr/{;$%+............+%>;~F^sxAvGAs/]);>*+...........@*-~F^sxGvHAsrF);>%+...........@%$-;~]IxDuvDJ/{';>$%@...............&%$>----,$&+......................................................................................................................&=-~]^sADEDtKF',@..",
|
||||||
|
"........................................&=;~FIyHDEvDAsr]~-$&........+#,;)]/zsABxszssAAysrF);-#+.......@#--!]ryBCBCBCCCBBxsrF~,%.....@#>-!)]ryAHGEuELHBxzrF);-#.....@#*-;'{/yBACBByr]!;,*&...............@#=--!!)))))~!;-=%+.............+%=-!]rsBBBtz/];,*@............&=-;]^zxABCByrF);-=%@...........+#=;)FrsACBBysrF~-=#@.........&#>-;!{/KyDDDGAz])';-,=&.............&%=>;;!;;->=%@.....................................................................................................................&=;~]rJAGLDGs])>&..",
|
||||||
|
"........................................&#=-~][6MNNOP[{!->#&........+%*-;)(F^rI^/FF/IrQ/])'-=%........+&>,;~]^rIzKzKsKzr/F(~;=@.....&*>,;!)][IKOwNwOPKQF|~;,*&.....@#$>-;~]/rrzKr/F)->*%@..............+&*=--''~___~';,=*%@.............+&*,-']/rKr/F_!-*%@............@*=-!{2QIIIQ/(;->*&+.............&%=-!(}^IIr/[]);>$&@.........&*>,-;!(1<ONwO<}_!;--=*&.............@%$=-;!!;-=*%&.....................................................................................................................@*=-~{[POwO5}!-%...",
|
||||||
|
"........................................+*>-a|75RNNR5}('-*#@........@&$-!__:[55<}1}}5554|~;-=%+.......&#*,-_1[QQQIIIIIQ[}1('-*@....+&$=-!(:}[QI68OOO66<}(_;-=&.....+%*=;;_|[[QQQ[2|~!->#&.............+@%$-;~(:f774e1_;,$%@.............@#$,;_:<865[1_;,$&@............@#>-~|}}[QQ[|~;>*%@...............&**-'(}[Q[[}|_;=*%@........+&*,;;c~(e<OSSO5:((_!--$&............+%$=;~b2e|a->#@+...................................................................................................................+&$>3~|}<P65[(c=#+..",
|
||||||
|
".......................................+@*=9afgjTTTUjge0-=%@.......+&%=9cbbgiqqjg7ggjqqggba;=&.......+%$=-;a17khkhhllkh7feb09>@....@#>-abe7khhlmVmmjqqjgedc9>&.....@*>;adbe47k4k77ebac,*%+...........+&#*,9a:gijqqqjgea3=#@.............@*=;0bgpqUqifdc,$&+............@*,cde7kk777ba3>#&+...............@**,0de4kh7hfb0,$%@........&*,;abbbefiqUUqi4bbbba;,#............@&$3afjjjifc,*&+...................................................................................................................@%=,;df7hhh4fd3*@...",
|
||||||
|
"........................................%*9c:kiqTTTWjl7bc>$&........&$>0d:4ijWqoikhmqTqp7eb0,#+......&*=9cde4hlVVVVmVXVVk72b',&...+&*3a14klVVVVVVVXqWWoi7bdc>#+...+&$3cde4k<lllllkk4ea9>*&+..........&*=3;d:75jqTTWomk:03=%+...........+&*30b4iqqUWpgba3*%+...........+%=30e[llVVlke_9=*&+...............+#=3cb4kllVlked;,$@.......@%=3d1e47hlpWUUWjhkk44ed9$@..........+%$,cbgqUWqgbc,$&...................................................................................................................&*,9dehllllheac=%...",
|
||||||
|
".......................................+$-~]zxCDuuEEvAyr{;,*+.......*-!{rsxADEEGABBGuEuGsz/{;=@....+%$;~]/zsAACGHvGvGGHCCAyz/~$...%>;~FzAABCCCBCCCCGvDHtsz/{;$@...&$-~]rzxBCCBCCCCBAs/{;-$%.........@*-')FrstCGLuDvGHtzF~->&...........&=-~FzyBGDEGAs/{;,*@...........&=-~FztACBABxr]'-=@................+*-'{^stBCBCBs/);,*+.....@#,;)/zytBHHDEEEEvvBBtyz^{-#..........@$-;{IxDEEDyI{!-*@.................................................................................................................@$-'{rxAGCAtsr]~-%...",
|
||||||
|
".......................................@#;~]ryADEEEEvBs^]!-#@......+%-;]^zyBHLLvCAAHvuDHsz/{!*+.....#-;{/zsACCBGLLLLLLGCCBBs/)=+.+*,;~FstCCCBCBtyxytBAAysz/{;*+..+%=-~]rstAABACBBBCtxr]'->*&........@=-)F^syBCCAAxyAAAzF~;=%..........+%-;)FsBACCBAs/]~->#+...........@=;)FzACCCBBs/{;,#+.................@$;)FsABCCCAs/{!-*&.....+$-;)/syBHLLEEuEuELGCBxs/);*.........+#,;~{IALLLDyzF);=%+...................................................+...........................................................@#>;~]IAGvHysz/{;-*+..",
|
||||||
|
".......................................+@*-;12IOSNSS8I});,*@........@*,;{F2IPwwPI[QIOwO<2|);,%......&=,!{F^IKKJwwNuNwwwJsKr}_;%...@*>;~FIKzKrI^/2F/[QQ^2]|);=&....&*>-!(]/^IKrKrKrrr^]'-=*%@........@*=;)]}^IKIQ2}}/[/]'-**@..........+@*=;(/QIQQ[[]);-*#+............+#>-~2PJwJK[]~;=#@...................&$-!{/IJJwP[(;,=#@......&$,;)F[QPwNwNuNNuNwJI^F);,#.........&**,;~:5wwNO<1_;,$%+............................................+@+++@@&@@@@@@@@+++................................................@#$-;):5wJP[F_!->#+...",
|
||||||
|
"........................................&*=;_2g8RNNR6[:(;=*&........@#=-~(1[5OO6[2}<6M6<|_;-=@......@*,;_1}[QKKOwNNNNSw6KQ[:_-#...@#*-':[IIIQ[[21::}22}:__!->&....+&*,;_(12[[QQQQQQ[2|~->$#@........+%>9'(}}QQQ}:1111|~;>$%&...........@#>-'|[2}}:(~;,*#+.............@%=-_26OYO<:_;,$%@...................@*,3~|[8YS6<(->$&+......@%=-'(14KONNNSNNNSO5[}(~-*&........@&#>,3_|<YRN6<1!;>*$%@...........................................&%###%#%#%#####%##%@...............................................&#=,9_1<OO<}(';=#+....",
|
||||||
|
"........................................&*=9aegjTTTqpgea;>#@........@#=3adb4impifffgpjigdc9>$&.....+&*-;d:4kimpoqWUUUWoplkkea-%...@$*3c:7hhhhhg7feef4febbac3=%....+&*,;a(be7k7h4h7<44ba;>=$%+.......@#>9abe4hik7ebbbbba-=$%%+..........@&*-cde4ebddc->%@+.............@#=9dgjWWjiea3=*&....................+&=-cbgqqUqgb;,$&+......@%*,cd:fijqUTTTTUqji4eda-*&......+@%**>3caegqWWjiba;9==**@........................................+@%$>>>=>=========***%@.............................................+&$>90dfippgba;3*&+....",
|
||||||
|
".......................................+%*30|7ijTTTUpl4d0=*&........&*>c_be4hiig4ee7iiifdc3=%@......&=3abfhlXqZZZoZWUUZnXVk4d3#...@%$3aehVVlnnnVllhkkk4eba09=%.....@*>3ad:4khllIlVllk7eda9=*&+......&*>0db4hmnmh4}ee:(ac3=$#&.........+@#>,0debdaa93,*#@..............&*>9dhoWWZifd0,$@.....................%,cabgqUWqifa3=#+......@#$,cab4hmoqTTTUZnmk4bdc,*@.....+#*=,c!a(b7mqUUqi7bdcc33=#+.....................................@%#=,333;0cc0;0c;cc;c9,>*%...........................................@%$,;de4hlnmhedc,*%.....",
|
||||||
|
"........................................#-']rxBLuEuEvts/);=%........&$3)F/rzssszrrzsyxs/{!-,#+.....+#-~]rxAGvEEGHHvLEEEGCCts^)$...&$-;{rxCCHvvDGBBCCBAysr/{'-=+....@#,;~F^sACCCCCCACCtyz/]',#@.....+*,;{/zsAGDvtyszrr^F{~;-,=@.........@#=;)F/^])';;-*&..............+*-;(^JvEELtK/{;>#....................+#-~2IyEEEEtK]~3=@......+*-;~]^zxACLEEEELGByz/]~;=&....@*--~)F^rzsxGEEEEHssr^F])!,#....................................@*-;~){]{/^^////////FF]{);=@.........................................@*>;)FzsxABCAs/]_;$%.....",
|
||||||
|
".......................................+*-;_^stDEEELGAs/)-=&.........%,'{F^/rrr/FF/rzz^]);-*@+.....@*-~{rsAAGLLvCBCHLLLGCCAsF'*+..@#,;)/stBBHvGHCCCCCCBsz/{);>%....@#=-!{/stCCCCCACBBAxz/]!-$&....+@*>;{/zsAvLDBxsszr//F]~!-=#.........+&=-!]]])!;-$%++..............@*-;)^xGEEuAs/);-&....................@$-'{IxGEEDAz]~-#+.......#=;~]^zyBHvLEuLGCBxz^]~;$@....%--!{/IzsJyAvEuELGAtyssr/);*...................................+#-;']/rKzzzsssKszszszzK/])-#.........................................%*-;)/sABCCBys/)!-$+.....",
|
||||||
|
"........................................+*-;~:[PSNNOP}|!-=#@.........+&$-;;;~!!;;;;!'~'-,$#@.......@%>-'(][QPwwJKKKJwwOIQ}F{;>@....+*>-~{F2[QPPKKKKKJJKI/})!-*@....+&*=,;)FQrKKKzKzrr/F{~;>*%+....++%*=;~:2<OwwPII^[F]|_)~!-=&...........@%*--;,=*#@+................+&>-;([OwNO<:~;=*@....................+%>-!(<OwNO5:~-=%........&*>-;_]QPOJ86PPJJPQ}{);,#.....&$-;|[68OJOYSNNNNNOOO665[_-*...................................+&=-!1<588866666O6666668<}_,%.........................................&*=;~]/IrIQQ2{!-=*@......",
|
||||||
|
"........................................+&*=;_:<ORN6<|~;,$&...........+&**>==,>====>,,*$%&+........@%*>;~(|[5OO6<[[<OY6<1|_;-$@....+&#--;_(:2[QIIIKPOO8<[}('-*+.....@#$=-!|}QQQPPIQQ[2(_;,*#@......+&$=;~(1g8MM6KQQ}1||11(~;=%............@@@&&%%@....................@#=-a46YSO<1;,$#@....................@#*,;d26YSO<|;,*@........+%*,;_|<6O6<24<5Y8<:(!;=%+...+%>-ab5RRRRRNSNNSNNNRNNRM5b9#....................................#=3af6MMNMNNRNNMNRNNNRRMg(-#.........................................&$,;_:[IIQ2:(;-$#&+......",
|
||||||
|
"........................................+&*>30biqUUjgbc9=*@.............@&*##**$#$*$#$#%@..........@%$=9cdbgpqqmg7giqqjgbbac,%+.....%*>>30dbef7hhlmmoZoik7e09#.....+@#$=90:7hhVmmlkh4edac-=#@......+&$=cabfiqUUjmll74eeeeb_c=#...............+++++...................+&*,9agpWWqgb;,>#@...................+@#*,;dgjWWjib;,$&.......+@#*,cabijqpg7fgjqjibdac=&+...+%>3agjqTTTTTTTTTTTTTTTTUifc#...................................+#>;dgjTTTTTTTTTTTTTTTTTUibc&........................................+#=30b4hhkkeba-=#@@.......",
|
||||||
|
".........................................@$=3abiqUUqib03>#&..............+@@@&&&%&&&%&&@...........&*,9abe7kpqWjlkipqWoi7e|a3$+....+&*=3c0|e47klVVXXZZoXVk7ea>@.....&*,3cdeklVmXXmVlkke|dc3=%......@#=90d:7iqWWZonXlhk7kk71a9#+......................................+%$-0bgjWUWifa9>*&+...................%*,90eioWUqibc3*%........@#>-0dfioZp57kipWqi4bac>*+...@#>!cgjTTTTTTTTTTTTTTTTTTjf0*...............+@%%%%%@+...........+%30agqTTTTTTTTTTTTTTTTTTjb0#.......................................@#$9a14kVVVk4(c3$&@........",
|
||||||
|
"........................................+%=;~FIADEDDyQ);-*@..................+@@@@@@@@+...........&=-!{^xtvDEEEEvGHDuEDHtyz^)-%...+&=-;)F^sxxxtACCCHGLGHCBAs/!#....@$,~{FzsABCHCHCCCCtxszF);$+....+#,;)FrsxHvvvDvvDGGCHABts/'>@.....................................+&*-!{ryuEEEtKF)'-$@..................+$-;)FrtLEELAK{!-$@......+%=3!{^ztvvHxssyHvGAs/]~3>@...&=30|<YuuEuEuEuTuuEuEuuuNXQ_>.............+&*>--;-->$%@+........+#,~e5wuuuuuuuuuuEuuuuuuSX[0$...............+&##**%&+..............+$-!{^sAACCCAs/)!-*@........",
|
||||||
|
".........................................&--'{rwvLLGy/{;>#+......................+...............+%>;)FKGLuEEuEuELEEEEEGCAyr);%...+*=-~]rzxAAyAAytBACCCBCCBs/)$....&>;{FrsxBBCBGBCCCBCBtsr]!,%....&*,;)/syBACHHvLLLELLHCBBs/),@......................................&=-;)[stvvDAs^{!-=#+.................+*-!)FIyGLLDxr{'-$&.......&$-~{/rsyAyzzrzxAxsr/{~-=&...+#,;~]rsXxwvLEEEEEEGtxxss^]!*+...........+#*,;!~~!;--=*@.........&>;~FrVsXsXxxXxXxxxXsssz/{;#..............@#*=>-,-=#@.............&$;)]zAACCBByzF);,#@........",
|
||||||
|
".........................................+%*-;|QJYw6[(;>#@........................................&*>;(<8NNNSNNNNNNNNNwJKI/|;=&...+%$=-~]//^^/////^[QIKKKKrF'-#....+*=;~{]F/QIJJKKKzKzIr/|!-*@....@#=-'1/QIIKKJJwwwNNNwKKr/(;*.......................................+&$,;_25PJPI[]~-,$&+.................+&*,;(2<PJPP[(;-$%@.......+&#>;~(:]11_~_)|2](~;->#@.....+%=,-c~(||e[6wNSR542:b(a!->&...........+&#$>-!~)~'-,*#&..........@$>3!!))()d|((|(dd)0_!';-%+.............@&**>=,==*$%+............&*>;~F^IrrQ/F(;-*#@.........",
|
||||||
|
"..........................................@#*-cb<55<1;,*%+........................................+%*-0:58OMRSRRRwMMRO85[}|~-=+...+&*>;_1}[Q<<<[[}[[Q5KIIQ[(!,&....+&*-;!_(|}[QKIIQQQQQ[}|;,$@....@#$-'_}[QQQQIPJYORNSO5[2:~-#+......................................+&%*,!([<I<Q}|~->#&@.................@#$-0(1[<I<Q:~;=*&..........&=,-;!!';----;';;-,=*@+......+&*=>--c_(:5RNSO<:d~!;->=%+...........@&#=-'(|1|_!->*@..........+%*=>,3,-3c;c-33----,,>=*%+............+&$=,-;;;-,*#&...........+&*=-!|[QQ}}}(~-$#@..........",
|
||||||
|
"..........................................@#*>cabebb0->*&.........................................+%*,;dfg5i5mm8mm8m5ig7:da9=#+...@%*,cd47<imjpi5hhijopmkh4bc=&.....@&*,90_db4khlhk747774ba-$@....@#=9ae4hhhhhhhilmjWqjge1b0-%........................................@#=,cbf7khh7eac=$&+.................@**3abf7hhh7ba3=#@..........+&>>,,-,,==>,,3,=*$#%+........+&**>,39afiqUUjiba09-=$%+...........+&*$,9~bee:bd;,*%+..........+&***>=>=>=,=>===>=>*$*#@.............@%>ccadbda;,$%+.........+&#>=cae4hhfebd0,*%+..........",
|
||||||
|
"..........................................+%$,-0dbbd93=$&..........................................@=,3df7hlVVXXXVmVlVh4ba;3=%....+*>30ekVlXoZWommXnZZZmVh4b0,@.....@&**-99_b4hVVVkkk<llked9=&....@*>cd4lVVVllhhhlmoWUol7f1d9$+.......................................@#$9'b4klllk7eac=$&................+%=3017klllk7:a9>#@...........&&#*$>$*$$#$*=$$*%&+..........+&#*,90dfiqUUqifd;3=$&@............@*$-9d:kkkk4bac>$&...........@&#$*$*$*$***$*$#*##&@@+............+#=;abe474ed9=*%+........+#>30~ehmpl7eda9=$&+..........",
|
||||||
|
".........................................+@*,;_{/^^2{'3,#.........................................+#=c_}zxtAHHCCCCCCCCts^F';>#....+$-'{^yCCCvLvvvGGvGvGBtxrF',%.....+&*>;')]^stCACAyAACBAs/)3%...+#-;{/sCCCBCBCBBCCvLEDHysz^];&.......................................@#,'{^stAACCAs/{;-=&..............+%>;~FzAACCBts^]!-$&...........@&##$>,=*#&##$=*%&+............@#$3!|[KwEEEvAKF);->%+...........+$-;)]ryBHHBAs/{;-#+...........+@%%#%##*=#%#&&&&#%&..............+%-;)FrsABAsr{!-$&.......&=-~]/rsALGtJ/F);-*%...........",
|
||||||
|
"..........................................@*-;'FQzr/{!;,%+.........................................%,;'FryACBHBCCCBCBAyzF)'-=&+....%=;)^sACCBHGLLLLLGCAtzrF)',@.......@#-;)]^sAACBAABCABAz/);*+..@#>;)/stBCCCCCCCBGGLLGHCAsr{;%........................................%=;)FzyBCACAs/{!-=*&.............&=-;)/zACAABAz/);>#&.............+@&%%%&&@.@%%%+...............@*-;)FztLELDxr{~-=#@............&$;~]^sAvLvHts/);,=&..............+.+.+@+++..+.+++...............+*-!{/zxACBAzF~;=%.......#=;~FrzxtGvAz/{~;$%............",
|
||||||
|
"..........................................+&*-;|[I<[(-=*@..........................................&*>-'{F[IKPKKKKzKrQ/]'->$%+.....@%=-)]F2/QIKOwNNwPQ[])';=*&.........+#=-!)F^KzKrrrrKr/F'->@....+#=;)F^KKKJJwwOwOOOOJJO6P2~-&.........................................&*-')F/rIzI/{~;>#@@............+@#=-!(FrKz^//]'->*@...................+.........................+#>-!1<ONwOQ(;,*%+.............@%>-~1[6wNSJI2(;,$&+..............................................@*-!{FQKJJP[_->*@.......&*>;~:2QIPI<:~;,>%+............",
|
||||||
|
"...........................................@#=c15O8<|;>#@..........................................+%*-;_|2}QIIKIIIQ[}|_;-*&+.......@$=-;~_((:[8RNN6<:(!-=**%@..........+#*=;(2QIIIQQQ[[2(;-*@....+@*>;(}[<5YRMMNMMO6P6YRR62a,&.........................................+*=-'(:2QK<[1~;-*#+............+%*,;~|}<<<[:_~;,*&+..............................................@*>9_78YR840->$&+.............@#=-~1[56O852(!-*&+...............................................+#>;(2<8YR6ea-=%@.......@#=-_:2[[<[:(;,*&+.............",
|
||||||
|
"...........................................@#=0bijjib3$%@..........................................+%*>9abe47hlllhh<7ebd9>$&+.......+%*=-339cafiqqqpfd0->$&@............+%$*3_e47477744ebd3=$@....+&*=9a:47ijUUqTqqjiimjqqjg0-+..........................................&*,9cdfgjpieda;>#@............+%$>;dbgppi7ba;,$%@...............................................@#=3agiqjifc3*#@.............@%#=9af7giig7ba3>#&.................................................#=9aegjqqpfa,*%@.......@*=cdf77h77ba;>*&+.............",
|
||||||
|
"...........................................@#>9agggfa9*#&..........................................@#$3c(e4klVVVVlVVlkea9,*&........+@&%#*>>9abhmooifa3>*%&.............+%#>3cdee44ee:bbd03$%@.....@#>,0dbfggiijjjiih4ggjggb3=&..........................................@#=-caemoom7eda3*@............&#,cdb7loZp7ba9,*%+...............................................+%$,9dggggd0,$&+.............+&*-c|4ll5hhfd09=*@+................................................%=9cbggiggb0,$%+.......&$,0|7klllke_3=$@..............",
|
||||||
|
"...........................................&$30ab1bd09>#@..........................................+$-'{/zxtCCCCCCCBBtzF~-=#........@@@&#$--!{/xtHCxK]~-=#@.............+%$,;!)]F///F]()~'->#@.....@#>-!(]}[4hhhkhkQ^^Ik7fbd0,@..........................................@*,;!{rtvvtJz^])-%...........+&=;{/zsADLGK^{!->#@...............................................+%$30_|::(a;-$&+.............%=-'{rxCBBAxzF);-=@.................................................%>;~{:474bdc->#+......+%-!{rxAAAAs/{;-*@..............",
|
||||||
|
"............................................%$-;;'';--$&...........................................+&>;)/rsAACCCCCABByzF~-=@.............+#>;'FzAAxs^]~-=%................%*,;!~'))))~';;->#&+......@#,;;~))){){{]{F]{){(__;,*@..........................................+%=-'(^JGGAsr/{!>#+...........@*;)F^syBwAzF);-#&+................................................+*,-;!'~;;-$%+..............@*,;]rtABxsz^]!;>%+.................................................+#-;!))))~;--#+........*-;{rsyByszF);>#+..............",
|
||||||
|
".............................................+%*====%&+..............................................%=-~{]FQrKKrIrr^F|'-*&+..............@#=-!{//2]';,$#@.................+&%*=====,,=***@+..........@#$>,--------;-,-,-=,=#+............................................+%*>;~1241(~'-,%+.............@=-;!(14}:~;,#&+...................................................+&#*>=>*#&@.................&*=;)FFFF1)!;>*%+....................................................&#$>-,,==#&+.........&=,;)]FFF{);->*@...............",
|
||||||
|
"..............................................+&&%%&@+...............................................+#-;;~(|}}2}221(~!-**@................@**-'_(_!->#&+....................@&#*&%%&&%#&+.............+@&##*****==*=>***$#&+..............................................+@**-99'c-->$%&+.............+@*=,,-cc3-=#&+......................................................+&&#%&@+.................+@#>>;_(_!--,$%%+......................................................+&&&%##&@...........@#=-;_((_!-->%@+...............",
|
||||||
|
"................................................+..+.................................................+@#,-3cc_db_d_0!;-,*@+.................@#=-9;3-=$%+......................++++.+@@++.................++&%%%%%%#%%%&&@@@+................................................+%**>>,,=**%@+..............+@&#*$>>>**%%@..........................................................+@+....................@&*=3ccc9,>*#@+.........................................................+++@++............+%*39ca_cc,=*&.................",
|
||||||
|
"......................................................................................................+&**=,,3993,>>==>*%&..................+@%*>=>**%&+..................................................++@@@@@@+++@@.......................................................&***$*#%&+.................+%%#%#%%*%&@+.................................................................................+%*=-9c->=*%@+............................................................................+&#>3999c,,*#&.................",
|
||||||
|
"........................................................................................................&#*$$>>$#&&@%#*#@.....................+%***#&@+.......................................................................................................................+&%%#%&@+...................@@&@%&&@++....................................................................................@&*$>>>*%#&..............................................................................+@&#$>>==**%@+.................",
|
||||||
|
"............................................................................................................++++......+...........................+......................................................................................................................................................................................................................................................+.++++++..................................................................................+.+++++.+....................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
".............++@@@++..........................................................++@@&@@++....................+@@&&&&&@@@@@+.......................+@@@@@++...................++@&&&%@@@@++........................+@@@@@++................++@@&&&&&&&&&@@++....................+@@&&@@@++....................+@@@@@@@@+...........................................................................................................................................................................................................",
|
||||||
|
"..........+&&#*====####@+.................+@%#######@+...................+@####==,=>=*##&+...............+&#*$===>===**%&@.....................@&**$*$*#%@+............+@###==>>,,,>>=*##%@+.................+@#****===###&@........+@###==>,,,,,=,,=>=*#&+...............+@#*====>$**&&@.................@%%**$>$=**#&++................................................................................................................................................................................++@@@@++...............",
|
||||||
|
".........@#=>-;!~~)!!;-,$*%@+..........@%*$>-;;;!;;;>$#&@..............+&#>-;;;)){)~!;;-,$%@+..........+@$>-;!){{))~!;;-,=#+.................+&*,-;;;;;--$#@.........@#$,-;!)){)))))))!;;-$#@..............+&$=-;;!!~))!;--=%+....+&$>;;!')){{{{))){)~!!;,=%@..........+%*$-;;!)))~';;->=#&+............+%$,-;;!~~~!;--$$%@+...........................................................................................................................................................................+@#$=>>,>$****&+.........",
|
||||||
|
".......&%#*-;!))]F]])~!;--=*@.........%#=-;;'))))()~';>*&@............@#*,-;'){]//F]{)'!--=*%@.......+&#=,-;'{F//^F]{)~;;->$%+..............@%=--!~))))';-=*&.......@#=;;~)]F///////F]{)';-=%............@%#=,;;!)){]]]]));-=&....@#>;!)]FFFF////F///]{)~!-=*&........@#$--;~)]F/F]{)~';->*%@..........+#*,;!))]]]]))!;--,*&.........................................................................................................................................................................@&#*=---;-;-;---=#&........",
|
||||||
|
"......+&#*$>;;~{]1]1(~;;,>**@+......+@%$*=-;!))(({{);,$%&+............@**=--~){]}/}]|)~;-,>$#@.......@&#*>-;!)]1F}F:{();-,=*#@..............&#$,;!~)~)~!;,*&@......+&$=-;')(F}:}11F:]|_)~;-*&...........+&#*>>-;!)(]F1]()~;-*&...+&$=-')({:F}F}F}F}F}]_)~;-*#@......+@&#*>-;!~(]1F1{)!;-,>$#&.........+&**>-!)({{]|)~!;-=>#%+.......................................................................................................................................................................+&&*$>,----;--->=>*#+.......",
|
||||||
|
"......@%**--;(_:}[}211_!-=>$#+......+&**,-;!((1}2}}(~3=#&+...........@#$>--!_|}}[[[}}2(~;-,=*@.......+%*>-;;_|}}[[[}}:(!;-,=*&.............@#*=-'_((111(!->$&+.....@%*>;!((}}[[}[[[[22:1(!->%+..........@%*$=-;'_(}}[[}21(!-=@....&*>;_(|}}[[[[}[}[[}}:1(!->#+......+&%*,-;;_|:}2}21(_';--=*&+........+%*>-;_(}}2}:11_'-,=*#@......................................................................................................................................................................++%#*=,;;;!!!!;;3-=$*#@......",
|
||||||
|
".....+&*>,cabff77hk77ebba9,=*@......&#>3;adbeggghigeb;,*%+..........+&*=9cabf7ghhhhhhg7bda;,>&......+&$=3cabf7g7h4hh4g7bda9,=&.............@$>-cbegggg7eb;,=&+....+&#=,;abfghhhhhh7k77eeba-=*+..........@*=3;0befgghhh77fba;>%....&*3cbef77k7hhhh7hh774ebd9=*@.....+&#>,;adbefgkh7k74fbba;3=*@........&$,cabff74k74febba09=*&........................................................................................+..................................................+@++.......................+@#$,3cdbbebeebbb0;,=*&+.....",
|
||||||
|
"....+&=-cabegmmmVVVVmpm7ebac>#.....+%=-'b47kmmoononm7d9>#&..........%*>cd:47lmnmVlVVXnml7eba,#+.....%*,0(e77lpmnVVVmXmmh7eb03$+...........+#=cabgijjjjji7b9>*&....@%$-0de7lpnXlVVlVVVlkk4b0,*&.........@#>9abgipppoonXVVk4b0,#+..+*,c{4hIhlVVVhVVVlVVVllkea9=&.....&#>3abe4hmmmmVVVmpml7eedc>%.......@#=9dgiimlVVVlVlkk7}d0,#+....................................................................................+@%%#%%@+.........................................+@&%*%#&@+.....................&#>90bgippjjppppi7bac,>#+....",
|
||||||
|
"...+%>;)FrzyHvvvHCHHHDGtysrF~-&....&=;)/sABHvEuEuEuvs^);,*+.......+@=-~]zytHGDvvHCHGvvvHBAsr{-%....+$-)FzyBBvDLDGCHGDDvHAys/)-%..........+#-;{^swEEuEEEDy^{;-%....#=-)]rstHDEDHCCCBCBCCAsr{!-%.......+&$-~{^syuuEvEvDGCCBy^]!=+.+%-']zxCCCCCCCCBCCCBCBCCts/);=+...@*-!]rsAAHGDGHCHHHvvGCtsr]!>.....+%*-'{rxDvGCCCCBCCCCBtz]',&.................................................................................@%*$>----->$*&.....................................&#*=---;-->*#@+.................+#-!{/zxDuuuuEuDuHtsrF);,#+...",
|
||||||
|
"...@#-;)/zstHDLvBCBCGLDCtxz/);#...+&=;)ryBCHDEEuEEEuA/{;,*@.......+#=;)/sACBGLLGCBCHDLvHCAyr];*....@*;'/sABHGLLvHCCvLLGCCBsr(;#..........@$;~]rstuEEEELDA/{!-#+..+#,;)/zsyHLLvGBCCCCCCAAxr{;-%.......@*,;)FKsHEEEuLLLGCCBxr]!$+..&>!]ryBCCCCCCCCCCCCCCBCBs/);>&..+%=-)FzyACGvLvHCCCvDLGCCAz/'=@....@#,;'FIAGvvCCBCCBCCBCBs/);*...............+@&&&@+............................+@%%&@+.....................+&##,--;!~~!!;->%..........@&&&&&&&&&&&&&&&&@........&#=--;!'!~!;-,=##&...............&$-!{^sADEEEuEuELEAsz/]~-=%...",
|
||||||
|
"...&*=-!(F[QPJwJJKKJJwOPI/F|;>#....+#=;)2/IPOSNSNSNOQ|!-*&+........&*=;)F^IKJwwJPKKJJwwPKI^]'-&....@%>-)F^IKJOwJPKPJwwOPKr^]!-&..........&*>-~:[6YNSNNwO<1;,=@....&*,;~][QPOwOPKKKKKzrr^F);,*&......+&*$-!)2Q6MNNNNwwJKI^F);,%...+&=;{FrIKQKKKKKKKKJJsKKr});>&....@*>;)F[rIJJwJJKKJJwwJKIrF(;*.....&#=-;(25wwJKKKKKzKsKKK/(!-#..............+@%###%&@..........................+@&&##%&+..................+@&%**=--;!!~'';->#.........+@&&%%%%%%##%%%%%%&+.......@%*,--!'~'!;-,=**#@+.............%*,-!(25OwNNNNNSwOP[2]);-*&...",
|
||||||
|
"..+&*>-'(}[QQ66<Q[[QIPP<[[}(!,&....+%$>;_1:[<88RNNS67(;-=&.........&#=-_}[Q<5665Q[[Q586PIQ[1~-%....@%*-'_}[Q<55<[[[<K6PI<Q[{'>%.........+&*>;~|2<6ORMRS8<(;=*&....@$=-__1}<6JPI[[2[[[[}|(!-=#@.......@#>-~:7<88OOO65<Q}}|_;-*@....&*,;_|}}2}}}}[[[II5KIQ[:~-=%+...&#=-~|[Q<I6P5QQ[Q<K6IIQ[}(;*+...+@%>9~(}<66<Q[2[[Q<6JP5[(;,&.............&%*$*$*##%&........................+%*$$$*##&+................@&%%$>,-;!_{2ee1_c-$+.......+&%%###$$$$$$$$$$###%@......@#>-ab1e:1(~!-->**#&@+..........+&*>-!(1Q5O866868O8<[21(',*@...",
|
||||||
|
"...&*,;de7khhh77ebef4ghhhhhed9%.....@**3c~abffgjqUWjgbc-*&.........@$=-aehhhh77feebe77ihlhhea3%....@#*,0df474eeebeef7hllkh4ba,&.........@#=,0behhihimjZqgb9=*%....@*=3abf4hhik7eeeeee:bba;->*@.......%*,;agpjjmiig44febda93=#&....&*=3c0a_dddbbbee7hklkh4e03*@....@*=3de7hhlkh4fef47hhilkh4b;%....@#*-cdbehhl4eeebe4ipqZpiba9#...........+@%$*>,,>=$*#@......................@&$*==>,=$#&+..............+&#$==-9cabfgjjjpgd9,@......+@&$$>>======,=====**$*&.....@#,cgipjpg7bbacc,,=$%@+..........&*,;abf7hihgffghhlihh7e09>%...",
|
||||||
|
"...&*9a|kVVVlhk4eebe4khVVVlkbc$+....@#*=,90adffpqUWqgb03=%.........@*>3d4klhk4f1b|eekhllVll4b;#....+%$,cdef4eebee1e7hllVVVl4d3#........+&*,;aehlVVV6XoZqibc3>&+..+@$,cde7kllVlhk444444e|d!9=$@......%#30dfioZoV5l<k4ee1(a;3>*@....@%$=,3c090!a(b14klVVVlkea9=%....%$30_7VVVVVhk4ee4khlVVVlke0>+...@*,0de47lVlk4e1ee7loWWqm7d9*+..........@*=33aadd09,=#@....................&*=39cadda93*#@...........+%*==3c'd(147hmoWZjifa9#.....@&#,3c0c0aadadadaaaa0c9,$&....&*3agqqZnXlk4e:bdcc,=$#@.........&=3ade4kVVh7fe4klVlVVl71a,*+..",
|
||||||
|
"..+$-'FrtCBCBBxszrrzstBBCBByz{,+.....%#--!_|/QsGLEuDyI{;-#+.......+&=-!{rsxszzrrrrzstACCCCCxr(>....+#>;)]//rzrzrrzsxAHHHCCAs^)=.......&*=-~]rsAHHBCBHvLDAK];-#+..+&,;)/zyAHGGGGGGHHHAAysrF);-%.....&>;)FQxGuLGGBCBAtxsz/F{!->%....+&*=--;;!'){F^rxtBCCABxr{'-*+..@$-;{rsCCBCCAtxsssxCACCCAyz];&...#-'{^zxtCCCtsszzssCvEEvts^(-.........+%$-~{/rxxsz/~;,*@.................@#>;~]/rsyys/);-*@........+%*--~)]/rsyyAACHvGGHsrF!*....@*-;)F/rrrzzzsszszzzzr/F{;$+...&=c1KAGGGCCBHtAAsrF{!;->#@......@#-~]^zstACtxsssACCCCBCAr]',@..",
|
||||||
|
"..+*;~]zyCCCBBysrrrrzyABCCCxr{-+......@#--!){^KtLLELxr)!-=&........&$-;'{F////^^//rsABCCCCAyr)=+...+@#-;)){]F/^/rzsAGvGCCABs/)=+......&=-!)/ztvvGCBBCGLLtz]~-=@...#=;)/zsACLELELLLLLGHAxz/{;-#....@#-']^zxHvLvBCBCCBAyzr/]';,#.....+@**>-;-;''{/rsACAABts^)!,#...+#-'{/sBCCCACAysssAACCCCCtz];%..+#-!]rzyABBBAszzrsstGLELHs/{=@........+*-!{/ztHLLtK]'-*#.................@$-;]/sxGGDAK]!-,%......+@%#-;!)FrsxBABCCCCAAysrF)-#...&*=-!]rsyAAyyAAABAAAAtAsz/)-%...@=-!{^zsyBCCLLLvAxrF)!;--=&+....@*-!]/rzyAAAsszsytBBCCCxzF'>&..",
|
||||||
|
"..+&=-!][KzKI^/]_)({]F^IKzK^|;*........+%*=-'(25SwwOQ|;-*%+........+@#$=--;;;;!'~){F^IzKKKr2(;*......@%*=,--;~)(|12IJwwJKK^F)-%.......&*>-!(2KOwJIQQIJwO<1!-=&....@*>;)][IPwwNNNNuNNwJIQF(!-*&....+&=;'{2[PwwJKKIrKrQ/2()!->*&.......+&&#$**>-;~{FrKzr^FF~;=$+....@*>;)FQrKKKrQ/FF/^rKzKIr^1!$+..+&*-!{F/rIKK^2]1112IOwwO52(;*..........%$-'{[<wwwO[_->#@..................%=-'|[POwwO4_-=*&.....+@&**=--!{F[rKzKzKKI^}}1_;>%+...+%*>-)F//rrrrrrrKrr^rrrQ/(;=@....&==-c(]}QKJwNNwJQ}{~;;,=$%+....+&#=;~)]FF//}]]2/^rKKKK^{~-#...",
|
||||||
|
"...&$-!([QIIQ[|(~';_(|}[IIQ2(;*+........@%*-9_1<YSR84_;,$&+.........+@&%*===>,,;;'(|}QQIIIQ1~-%......+&%#*==-;'_(11<6OOPIQ[|!-%......+&$,-'(|<6O8<}}[5O8<1'-*%+...@%*-;(1[6MNSNNSNNNY6Q[}(;-*&.....&*-'_|[<OwO<QQQQQ[}:((;-=#@..........@&&%*=-!_:2QQ[2:_'->@+....@%*-;|[[QQQQ[}1:12[QQQQ[}_;*....&*,-_(}}QIQ}:|((1:<6RSO<:~;*+........+@*=;(2<OSR84~-=%@.................+&$-;(}5OSR84~-$#@.....@&%$>--;!(1}QIIKIIQ[}((';>*@....@%$=-_:[QQQQQQQQQQQQQ[Q[}(!,%....+&*=-;~1}Q8YNNR8<}((~;-,=*%....+&#>=;!_(1||((((:2[QIIQ2(;>%+..",
|
||||||
|
"..+&*3cb7hkhk4ba!ccadb44hhk4d;#.........+&#=30biqWWjgdc,*@...........+@%%#*$=>,;aab17khlhh4d9=&.......+&&%*=,;abffgiqqomk7fd9=&......@%*39abfipomh77gpqjib09=&....@%*,;abeioqWUUUqWqopih7fa;=#....+%=3abb7pqqomikhkhk77fbd;,*@...........@&%$*3cde75h7b|a;=$@.....+#$3cb47khikiggeggiklkh7e03#....&*,;abe4hkh7bbbbbfijWWqifa3*.........+&*,cdfijZqpga9>$@.................+&*-0bfijZqpea3*&+.....@#*=9aadbf77hhhhhh7fbaa;9=#+....@#>-9df7<k<kh<kk5k<k5kh77ba-&.....@%#>,9ae7ijqqqpg4febba0,=#+....@&*>99aadbbb(bbe77khhk4dc=&...",
|
||||||
|
"..+*=9_e<VVllk41a00d14klVVVke0*+........+@*=9afiqUUjib03>#+...........+@##$>>-ca|e4hmnnVlk4b0=&.......+@%$=-9dfgijjqWUZmlk4ba3%......&*-;be7klmmmh7klnZqiedc,#....@%$30db4hmMnppjoonZXopmib09#+...+#=c(e7hmZWZooonmVlmmpigd9,%..........+@&#*,c_b7mnmhfda3=*@.....@#>9~b4khmnooojjjjoomlk4ed9*+...@*>0d:4hmnnk7ee47hpZUTqpgdc*+........+%>3ab7hXnnm7d9=%&.................+%*3a14lnnnm7a9>$@.....&*>;de77hmpXmVVVkk41d0c9=*&+....@*=9deklVVVVVVVVVVVVVVVVk4d9#......@#$=900e7ipppmVVimiigedc>@.....@#=,9c0_d1ee4hlmnXVVh4bc3#...",
|
||||||
|
"..&=;~/ztCCCAAsr/F]/zstCBCBxzF,+.........&>-_:IAEEEvyQ{;-$@............+%*=-;~{^zyAAvvvAAszF);&........&*>-~]rsHuuuuEEvGtysrF'$....+#>-)]zyBACCCBBAAAGLDts/]!>@...&*,;)F/zxBGHtAxtHBGLLDDtKF',&...%-!{^sxCGDEEELLDGHHGDvvyK]!=+.........@&#>;~{/zxGvvtz/{;-=&.....&>;)]^zxtGuEuuuEEuEDGHxxz^(>+...+=;{/zxAvDDHysyyBBGEEEuDs^(-.........&#-']rsACHHyr]'-=%+................@*-!]rsABHHxK]~-=@....+*;~FzxCAHGvDHBCBxs^F{!;;-$@.....&,;)/ztCCCCBCCCBCBCCCBCCBs^(>......@%>,;~{FrssAAHHHHDvDHxz/~$.....+%=-;!)]/zsxttGDDGHCts/)-*+..",
|
||||||
|
"..@=;'FzACCCCtsrF]]/zsABCCBAr{,+.........&=;)FKxLLELyr)!-=%.............&*>-~)/rxABHGvvAsz/]'>&.......+@*,;~]rJxuuuuELvAAxsrF)=+...&$-')/sACCCBCCAAtBGLLHsr]);%...@*=;!)F^stAxszsyxCCGLLDGzF)-#...&-;{rsAAGLELLvvGHCHvLLEtz]'>+.........+%>-;)F/syHGGyz]);-#+....+%>;)FzsABHGvDLuDLLLGHAyyz^{-+...+%;)FzsAHGGHtAABCHvEEuuGs^),@........+*>;)FzstAts/)!-*&+................+%=;)/zsAAxs/);-#@....+=;)FsACCHLLLGCBBsr/]~';-=#+....+#,;)FsAACBCCBCCCCCCBCCCCBxr)=+.....+%*=-;']/rssxACCGLLLGAs/)=+.....+%>-;)]/zxBCCGGGACAyr]'-*...",
|
||||||
|
"..+%>-']QKKKr[F|_;'_]/QzKKK/:!*..........@%=-!:5wNNOQ|'->#@.............@%=,;~:[6OOJ8P<[1)'-,#........+@&#>-;_:4h5lPPJPKIQ/})-%....+#>-!:QJwOJJzKrIIKOww6[})!-&....@&$=-;'){]:|(1]F[IJwww6}(;,&..+@=>;)F[IPwwO6PPIQIKOwww5[_;*...........@%>-!(:}QPPI}(;-=*&......@*,;)}^IIKPJ66P6P6JJPKr^/|;$.....@=-')12IPJOJJJJPJJwNNR5}(;*.........+@%>-;~){{{)!->#@+...................&=-;~){]{)!-=#@.....+%-;)/IKKJwwwPK^/F|';-=$%&+......@*=;)F^IrKKKKKzKKzKKKKzIr2);%.......+&%$>-;_(]2/QKJOwNwOI2{;%.......+%*=-'([IJJJ6PPQ[F{);,*&...",
|
||||||
|
"...&*-'|[QII[}1_;-;__:}QIIQ2(;*+.........@$*-0(<OSR64(;,*&@............+&#$,!_|58MR85[:(!-=>%@.........+%#*==9'_b124<<IIIQ[|'-%....+&*,;(<OMwOPIIIQI5OYY5[:|!-&.....@%#*=,-;;;;;!_(|}5YSY6f~;>%...@%>,_(}[6YM6<[}[22<6YSY51~;$+..........+%*-'(:}[Q<[1!-=#&+......@#>;_1[QQ<II<[[}[Q<II<QQ}(;*+....@&$,c~|}<6YRRRO6P8RSNO5:~;%..........+&%*=------>$#&+....................@&*=------>*#@+......&=;~1QIKPOYO6[}}|~;;==*%@.......@#>-!(2[Q[QQQIQIIQQQQQQQ[:~-#........+&#*=-;'~|:[IPOSNS8<:_-%........@%#=-_28YRO6<}|(~;,>*&+...",
|
||||||
|
"..+%*,cd4hhlk4bbaccad:77hlh4b;#..........@$=30bgqWWjgd;,$%@............@#*=9abfiqTUqigba;,*$%@.......+&%*$$>=,90abbe7hhllkhea-#.....&$-cbiqUqomhhhhlmjqqpkfba9%....+@%*$=>,,,,-39aabfiqWqp7d0,&..+&$>90bfgmqqjffbfbf7pqWqpfd9=@..........@#*3abe77h47bc9$*&......+@*=3dekhlhhhhefff7hhlllk7bc$+....@&#$-cdfhiqTTTqpmnqWWqifa;#..........++&%*$>>==**#&+.....................+@%*$>>=*=$$%@......+&=cae4lVnoqomg4fbbc;,$#&@.......@*,cabf7khhhhhhhhhhkhhhk4ea3#.......+@&$*=3cadbe7hmoWTUjiea3%........+%$>3agjUUqi7bdcc,=*&+....",
|
||||||
|
"..+#=9~ekVVVlk4:dd(bb4kVVVVk|0*+.........@*>3aeiqWWqiba9=$&+..........+#*-c_b7ijqTUqm71dc3>*&@.......+%*>=,3-3c0dbe4kVVVVVl7b9%....+#>caepqUWZXXVVVVXZWWolh7b0*....+%*>,,3--3,-90_bbhpZWWpgba,%...&*-0(e4lpWqjif4eefhpZWZpgb03&..........&*30(47khllk:a3=#@.......%*30(7VVXVVVhk444klVVlVVkea,@....+&#=,cd4kmqTTTZnXXZWWZi7d9*+..........+@%#*=,>=>$#&@.....................+&%#$==>>$*%@+.......#>cd4hVVXZZoXlh74:ba;3>*%+......&*3cbeQllllVVVVVVVVVlVVlh4d9%.......+&*=,90dbe44hVXoWUWoi4d9#........@#*,9bgqWWZp7edc-,$%@.....",
|
||||||
|
"..&=;)FztCBCAAszr/^rzxACBCBtz],+........+#-;(FKtEEELtK/);=#&.........+%-!)]rstGLLELGtsrF);->#@......%=-;)){))~)]//zyACBCCBBs^{=...+%=;{^KtEELvCCBCCCGLEEvHByz]-...+%>;!)({~~~'!~{/rzyGEEEvyrF!*...%-;)^sxAvEvvtsssssyGEEEHsr];%.........@$-~FzxACCCAyr]~;=#......+*-~]ryCBCCCBAyssstCCCCCCBzF;&....@%$-;)/zyAGDEEEGHvLEELHK^(>+..........+&#>,-;---=$*@....................+&#$=,---;-,=@........#;)FzxABHGvGGHHBAyzr]{!;>*&.....%,;)/stACCCBCBCCBCCCCBCCBsr(>......+*=-')F/zytHAHBHGvDGGxzF!*........@=-;(^yGvDDCsrF~;-=%+.....",
|
||||||
|
"..&>-~FzyCCCCByzr^^rzytCCCCyz{,+.......@#=-!{/sALLEGAs/);->*&.......@#-!)F/KAGvGGHHBys^]);-,%+.....+#>;)]//^]{{]/^zsxBCBCCAy/)=+..+#,!{^sABHHCCCCCCCGLELGCBtsF-@..%>-!{F//F))~~){/rKxGLLLDxz]'*..+%>!)/zyBHLvGyszzssyGLLuGyr];#.........&>-)FzABAACBxr]'-#@.......*-!{rxBCCCCBAxsssyBCCBCCtz];&....+%#>-!{^zsAtHACBCCGLLDts/)=+..........+%**>--;--,*#%+....................&#*>---;---=%........@=;)FrzsxACCvGLvHBBsrF{~;-=%....%=;)/zACCCACCCCCCCCCCCCCBx^(=+....&#=;;)]ryAGLLGHCCBBtssr/)-%........+%-;)}sAHHAxs/]~->%+......",
|
||||||
|
"..+#=-~]QKKKK/[F|{(]F2/IKKK/]!*......+@&%*,-!_25wNNO<1(;-=*%@......@&%=;~(][8wwJPII[2]~;-,**@......@#*-!):]|(~'))(]F/rIzKKr[);#....@#,;_][IKKJKJJJJsJwwwJPK/F)=...&*>;~{]|(~'';!'(1:Q6SNS8[|!-#...+#>;):2IPwYPQ}2F:}Q6wNw6[|'=+.........&*=;)F^rKKrQF(;=$&+.......&=-;(^IzKKrr//FFFF/IzKKKr:'=......+&$>,;~1:22[[Q^QPwwww5}~-%...........+&$**=>=,>$*%&+....................@%#$>>,>>=$$%+........%=-;!)(]2QIOwwwwKK^])~;-,*&....&$=-']^zKzKzKzKKKKKKKzKrI/);%....+%*=,-!(FQPONNNJPI[2]_~;;-*+........+@*,;_:QIII2{!;,*%+.......",
|
||||||
|
"..+@>,;(}QIIQ[}:1((_:22QQIQ2_-#+......@%$>,-0_15YSS8<1_;->$*&+.....+&$>-~(|}5YR6<Q[}:(~;->>$&+.....@#>-c(|:1(~_~__(1:[QQKIQ2~-%....+%*,c_:[QIIQKIPKPPOSROI[[1'$+..@*=-__|:1(~~~___(1[8YNR8}(;=@....&=-!(145YY5}1(|(:48YSY5e_;*+........+@*>3!|[[QQ[2:~->%@........%*,;_}QIQIQ[}||||}2QQIIQ[1;*+.....+@**=-;_((||:2}[56SS87(;=#...........+%#>>-,-===$%@+....................@%**=>--->**%@........+&#>,-;~(:<6wwwJPQ[:(~';,>%....+%$-'(}[QQQQIIIQQQQQQQQQ[{~-#....+%*>-;'_:[5OSNS8<2:_!c-=$*&..........@*$-!|}[Q2|~->*%+........",
|
||||||
|
"..+@*,;de4hhhh7feb:bf77hkh7ea,%.....+@#**,;cabfiqTUqiebac3>=#@.....@%*3cdffgjqUjih74fbba;3==%@.....@*=9abf7ff1bdbdbf4ghhlkkea-%.....@#=9abe77khlllmmoqWqjihfb0>...@*=3_beeeebbbdbbffgjqWqpfdc>@....@*,;abgiqqigebebfgpqWqmed9*..........&*,;af75hhkfb'-$%@........&*=caekhlhhg7febf47hhllh7bc*......+&*>=3cdbeeef77gmjZqogd9=%..........+&*=-;0a0!c3>$%@...................+&*>,9;a~c0,=*%+........+&#*>39ab7iqqopmkh7fbd0;,*+...@%*,;a:f44747777k4k74774fba,%...+@$,cabbf7kmjqqqp7fd03-,*#&+..........@*$9cb77k4ba3>#&+........",
|
||||||
|
"...@*>9aekhVVmmikkkhlmmVlhkb03#.....&#*-0ad:4gijUTTqph7e1dac,#+....&*,0bgimjqWWomVlkkk4ebdac>#+...+#=-aeimmmikk4[4khmXXXVVh4d3%.....+%>-0dbe7khllXVXZZUWoVlk4a$+..&$-'b4khilihk7kkimpnZoqifa9=@....@*>cad4pqWjlkhhklmoUWWpgb0=+........+%*,cbgmXnmh4bc3=%@........&*-c(4hVVXXmmh<khinnnlVlk:a$+.....@#>,0a1477kkhlmmnonomgbc>&..........+%>9abeggged9=$%@.................+%*,;_b7gigedc>%&.........@%#$>90df4iimVVVVmmiifbc3#...+#*=3adbe4e4e44e4e4e4eeeba;>&...+#>0bgiiihlVmjjihfba3,=*#&+..........+&*=3_eklh7:a;=*#+........",
|
||||||
|
"...&*-!]^sxBGGvGBBBHGvvHAxs/{;*.....#,;)/zsyBBHvuEuEvHABxsr]~,&...&$-~2swDLLEEEGHCCCBCAtsz^]!,&...%>;)/sHDDGHABCCABHvDvGCCAzF!*......&=;!)]/rzxBBBCBvLELGCCAs]*..+#-!]zxACHvGHHBBHGDDGGHHAI]'-&....%=-;_FItEELvCACACGLEEvtJ/{-&.........*-!{rxDDvvyz/);-#@........%>;)/sABHHLGvCCACHvDGHCAxr{,@....+#,;)]rsAABACBHvGDGBHAz2)9$.........+#-!{rsAvDvwV]!-=%................+#>;~FzxAvDDwz1;-#@........+#*=-;~|:/rKsxAHGDDGGyzF'*....%=-;!)]F///F/////F//FFF{!;-&...%>!2yGDGvHHBtysKr/{~;--$#@...........+#,;~FzxBBxzF);,*+........",
|
||||||
|
"...@=,;)/zstAGvvBCCCGGvAAsz/);*+...+*-;]/zyABCCvEEEDGCCBAxz/);*...%>;~FsHGLLLLLvCCCACBCBAxzF)-#...&=;)}swGLvGCCCCCCHGvGBBtxr{-#......+*$;;)]FrsxBCCCCvLLHCCyr)*..+#,']ryBAHvvGBCCHGLvGCBAs^)!>@...+@#=;;{IyGvvHHHCCBHGGLDAzF),@........+%-;{QyvLvGs^{~-=#+........@>-!]ryABBvvGHCCCGGvHCBysF)>@....%$;'{/ryACCCCCHvvHCCtxr{!-&.........@#-~]rxtGvDHy/)-=#+...............%=-;{/sAGHDDGsF'-=%........++&#*>-;){F/rstttGGDGyzF)$+...+@*=;;'_)){{){({{{){))~;;-*+...#,'FJtvvHCAyszr/F)~!->#&+.............%=-!]ryBByzF~;>%+........",
|
||||||
|
"....&%*-;~(:[<PPKKKKPPIQ2{)!-#@....+&>-'{F/QrIKPJOOOPKzrr/});=%...+#>;_2<8JOwOJJJzKzKzzr^/F);=&...+%*-~1QI5PKKKKKKKPJPPI[F{'-$+.......@&#==-!)]/^IKKJJJJKKr[];#...@%=;~{/[IPJPKKKKPJJIQ[F{~-$%.....+&%$=-_1<IPKJPKKKPPPP<[(!-%..........@=,;([PP6I2_;,*&...........@$=;~]F[IPJPPKKKPJPI[/]);-%.....&*-;!)]^rKzKKKKPPIQ[F(~-=%+.........@%$-~1[IPJJI4_;=*@...............+&$,-~2I8JPPP<2_-$&+............+@#*=>,;')12[<<<}:_;,@......+@#**,-=,-,->>>->-,,==*#@....&*,014<<[Q}:(~';;->=*@+...............@*>-!{//r2{!,=%+.........",
|
||||||
|
".....&#*=-;_(2[QQQIQ<[21_!->*%......&*=;(:2[QIIIIPPPIIQQ[}:~-$@...+@=-c|[<IKIPIIIIIIIQQQ[2|~-=&....@*=3~(:2}[QQIIIIII<[:('-->&.........+%%==-;_1}[IIIIKI<Q[2(;#....@#$-;~(}[QIII<II<Q2:__;-=%+.......@#>>3a(:}QQIIII[Q}}:(!-=%..........@%=3!|[<<2(;,>#@...........+&*=-;!(1[QQIIIQI<Q21_;->*&.....@*>;!(|}QQIQII<[}1(_';,=#&..........+%*,;(1[<<<[|!->#@...............+%*=-_45O65Q4:_;=*&...............+&#$>=,,;cca_a_9->#+.......++&%%%**%**$$$%$#%%#%&@+....+&*,90_____;;->=**%@++................+@#=-!:22}_->*&..........",
|
||||||
|
".....+&#$>,3abe4hhhh7ffdc9,**&......@*=9(ee77hhlkhkhkhk77f:a3$&...+&*90b4khhhhlllhlk5kh47f1a-*&....+%*-9adbf7hhhkhhhh4eda9-=#&..........@&$$-0_b47khhlhhk77eb3%....+#$>-9ab47hhlhhhh4bd03,>*@.........@#=-cabf7hhhhh74bbda9,*&..........+%*,cdf74fdc=*&@............@#*=39ab47hhhlhhh7e003>*%@.....@*=90dbf4hhhhkk7edcc-=$*&+...........&*=cdb47hh4b0,*%+...............+%$=9agjqpk7fb03=#@.................+@#**$>-33999,$*&..........@+++@@@@@@@&@&@+++........+@#=,399333,==$*&&@....................@#=3a14fb_3$*@..........",
|
||||||
|
".....+@%*>,9cde7kllk74:dc3=*@.......&*-0be7kllVVVVVVVVllk4edc=@...+%=-cb4hlVVllVVVVVVIl<k4ea9=@....+@#,9ab1e7kllVVVlkk4dc-,*%+..........+@%*,9d:4klVVlVVlhk4bc#....+@#*>9a|7klVVVVlk7|ac9,*%+.........+#*=3ade4kklllh4ebd03**@..........+&*,cde44e0;,$#@............+@%*=90d4klVVlllk7|a33=$#@.....@#>3cd:[klVllhk4ed03>>*%&+...........@*,cae4kkk4b;,$&@...............&#=9afioZol7e|a3>#@...................+@***===,*=**#&............++.+.....................@&#=9993,,,$**&@+.....................@*>3ab44ea9=*&..........",
|
||||||
|
"......+%#>-')F^zxxtxzr/]'-=#+.......#=;~FrsstttBAABBtAAyyzr]'-&...@$-')/zxtAAAAtBtBABtAysz/]!-&.....@*9'{F^rsxtAtAAAyzrF~;3$@...........+@*=-~]^zsAtBttAxszrF~*....+@#>-')/zsttAAtAxzF)!;-=%...........%=-;)]rzxtAtxsz^/]_;=*@...........#,;~F^zr^{'-=#+..............@*-;)FrsxABAAtyz/)!;-#&......@#-')F^zxxAttysr^F);->*&@............+$;)]/zsxsr/~;=#+..............+*-!{FztvvHtsz/{;-=@....................+&%*$>,,=$$%&@.....................................@#*=----->,=#&+......................+&$-!{/rr/{!-=%..........",
|
||||||
|
"........@#--!)]F/rr^F{{~;=#+........+#-!){/rrzszzzszzzzr/F]);$@...+%,-~)Frzzszzszszszzzr^F]';*+......%$;!){{Frzzszzzr/]);->%+............+@*-;'{F/rzzzzzr/F])-@......@%>-~)F/rzzrrr^F)'->*%+..........+&%*-;){F/rrr^/F])';-*&+...........&$>;'{]]{~;,%+................@$;;)]/rrzzzr/F)';-##+......+%=;!){Frzzrr/FF));;$#@+..............&>;){F///]);-$@...............@$-']/syBBtz/F{';$%+......................++@%&%#&+++.......................................@%%*=>=*=#@+.........................+%>;')]])~-=#@..........",
|
||||||
|
"..........&**=--;;;;-->=*@+.........+@*=--;''~~))')~)!!;;-->*&.....+&*>--;~~~)~~~)'~)~'~;;-=*&........+%*=---;!~~)~~!;-,=*%+...............@%$=--;'~~)~'!;;-,%.........@%$>-;;!~';!;--$#@+..............++@*=---!;!;-,--$#&+..............@#==---,=*&...................@#*>--!!~~!!;--$#%+..........+##---;'~';;;--=##+.................+@%=---;-->=#@+...............+%*-'(1}[[2)!--$#+...........................................................................++.+@&@++.............................@#$>-->=$@+...........",
|
||||||
|
"..........+@@%%%**#%%%&@++...........+@&#**=,,,=$>$>>,===**%&........@%*>>=,-,---$$=$==$=**#&..........+@&##=>,>-,>>=$#&&@+.................+@%#====,>>>=**#%@..........+&***$=$$**%%&@+..................@@@%*%***#*%%&@..................+@%%%*#%@.....................+&%*=>=>$*#%%&@+.............+&%*>>=>>==**%%&.....................@&#**#%%%&@@.................+**-;;~((!;,=*&+...................................................................................................................+%#*%**&+............",
|
||||||
|
"...........+..++@@@++++...............+@@&&%#%%&++@@&#%&&&@+..........@&%#####%%%&@+@+@%&&+...............+&&%%&%###%&&+......................++%%#%%###%&&@+.............@%%%#%@+@+++.....................++.+++++++.+......................@&@@@++.....................+@+@@#&&@@++++.................+@&%%#%&&&&&++......................++&@@++.+...................+@&*=>,,,=*%%&+.....................................................................................................................@@&@@+..............",
|
||||||
|
".............................................++.....+++...+.............+.....++........+.....................++....................................+....+..................+...............................................................................................+..+............................+.+++..............................+.........................+++.+++++++++..........................................................................................................................................",
|
||||||
|
"...........................................................................+................................................................................................+.+.................................................................................................................................+..............................+................................................................................................................................................................................",
|
||||||
|
".............++@@&@@@@....................................................+@@+.+.........................................................................................++@@@@&@@@@++...................++@&&@@@@++@+.....................................................................................+@@@@@@@+........................+@@@@&@@+................................+..........................................................................................................................................",
|
||||||
|
"............+@%#&%%&&%@...................++++.........................+@&+&@@@@@@+.........................++++@+++++++++.............+@@@@@+@+.......................++&&@&&&%%&&&@@@+..............+@@@@&&%&&&&&&&&+.......................++.+@+....................++@@++....+.+@&@+...............+++@&&&&&&&&+.......................+&@&&&&&&++...............+@@+@@+++++++@++@@+................++@@@+++............................................................................................+..@+..............",
|
||||||
|
"..........+@&%#*$*###%@+................+@&&%&@@&&&@+.................@&%&%&%%&&&&&%&++....................++@&%&%&&&&&&&++.........+@@%&&%&&#&&&@@@+.................@&%&&%%&%%%#%%&%@&@+...........+@&&%%%###%%%%#*#%&@+..................+@&&%%&&&@@@++............+@&#%%%&@@@@&%&&&%&@@@.........+&&&&&&&&%%%%&&&&@+...................&%&%%&%%%%%&@+...........+@&&&%%&&&&&&&&&&%&&%&+............+&&%&%&##&@@@@+...............@@@+............@&&@@@+..........@@@@@@+.....@&@@@@++..................@&&%@&@.............",
|
||||||
|
".........+%%#*$=>===$**&+..............+@&###$****##&@..............+@%#$$*$$$$$****#%&@+.................+&%%#$$$$**#####&+.......@%#%*$*$$*$*$**#*&@+.............+@&#**$$$**=*=*$$$$#%&++.........&%###*******$>$=****#%@+.............@&%%##*$$$***#%&++........@&#*$*$*#$#%#%#*#*##$%%#@........@%%#$$****$*$*$*###@@+..............+@&*#******$$*#%%&@......+@@%##***$#$###$####$#*#&+..........&%*#**$**$$*%%%&+.............@%%%#%&@+......+@@##%%#%+.......+&#%#%%%&@@+@@&#%%#*%%@@.............+@&%$####*&@@..........",
|
||||||
|
"........&**=,990aaa0c9,**@+...........+&#*==,3333,,==#%............+&*>>33c9cc0cc33,,>*$%@+.............+@#*=,>,,3933,,=,>$*&.....+#=>3339ccccc3933=>*#&+..........+&*>=3393c99c;ccc9933,=*&+......@%*=,,-39ccc0009c9cc933==#+..........+@#*=>,3333333,,>=*#@......&#$=>=333-,=,=>>>,,,3,-,=*+......@%*>>,,339cc9cc333>=$*%&............@##>>33c9ccc939-3>>*#+....@%$==,,3933,,,>==,,,,,,>=*@.......+%*=,3399cc93,=>*#&+..........+%*=>,=>==##&@@@@%*$=>,,=*#+.....@#*=>,,>***%#*$==>,,,>=>#&...........+&**>=,,,===$*%+........",
|
||||||
|
"......+#,;'){]/rrzzr^F{;-$#@.........@#>;;~))]F]]{{~!--&+.........+#=-!){]FFF/^^/]]{))!;,$#&+.........+&#>-;')){{]FF]{{)))';;#+...#-;))FFFF///FFF]{)~;--*&+.......&*,;~)]FFFF/F/^/^/FF]])~;,#+....@*-;~){{FFFF//^^//FF//]{)!-$+......+&%$-;'~){{FFFFF]{))~!;=@....@=;'){{{F]]{))~~)){{{{{{{);$+...@%=;;)){)]]////FFF{{))!;,=@..........&$-;~){]/F////FFF{));,#...+#-;~){{]]]]{))~~)){{{{{)'-*+.....&*-;~)]FFFF^/]])~;-$%.........+#,;!~{{{)~;->=*==--')){{)!-*...@%=-!)))))';;---;'){){{))';=@.......&#*=-!!)){{{{))!;>$%@+.....",
|
||||||
|
"......%=-')]/zxtBHHAxr/);,=*&........@=;~{]F/rzzrr//{'->%.........&$-;{Frzzzzsssszrr/F{~;--*&........@#*,-~)]F/rrrzzz///FF]]~-&..@>']F^rzzzssszzzrr/F)'--=%+......%=-']/rzszszszssszzzzr^F~;$&...+#>-)]//zzsszzssssszzszz/F]),%......@#==;!{]//zzszzr///F]]);=+...#-']F/rrzzrr/F]]]F/rrrrr//]-@..+**-~]F^/rzzzssszszr//F]~;=#+........+#=!)F//zzzzssszzzr/]]!$...+$;)]//rrzzr//F]]F//rrr//]'-%....+%>-)F/rzzzzsszr/F)!-$#+.......#>!)]//r//]);;,-,-;~)F^r//F),&..%=-!{F/^/F])~;;!)]F/rr//F]);%......&#*,;))F/^rr^//F)!;-=*#@....",
|
||||||
|
".....+&*=;!(F[KJwwwOI}{'-=#%@.......@%*-;)(]}}/2/[F]~;-**+........@*=-)]}/2/[/^/Q/[/2{)';,=*&........@#$=-;~_F}/2^Q/[/}]1{_)'-&..&=;){F/2//Q//[/[/}/|);-=$#@.....+&=,;)]}//Q/Q/Q^/rQ//[/F{!-=&....&*-;(F//[//Q/Q//Q//[/[/F])!>&.....@%#>=-;)_F}/[/Q^[F]1]_)~;$@..+%,;)(]}//[/2F|_)|]}//^[/F]_-@..+%*,;)]F2//Q^I/Q/Q//}]|);-*@.........+#$-~{FF[//[/Q/^[//]|~-*...@#-!):F[^[^[}]|(({]}/[//]);=&....+&*-;(F/2^/[/Q/[F_~;,*@+.......&>;~(]:F/})';->>>,-!)]2/2F(~-&++%=,;)]}F:](~!;--!)]1F[FF|);-%.....+&**=-;)(FF}/2F1{~;->$*#&+...",
|
||||||
|
"....+&$*-;~(}Q56MSSO5[|_->*%@.......+*=-'~|:2[Q[Q[[1(;,>#&........@*=;_1[[Q[Q[QQQ[[[}1(~;->*%+......&**=>-;~1:}[[Q[[[}1}1|((!-%..@,'_(:[Q[[Q[QQ[[[}}:(!--,$*%.....%*-;(1}[[[[QQQ[Q[Q[2[}1|~-=%....&*,!(:[[[QQQ[[QQ[QQQQ[[}|(;-&....+&*$=--!_12}QQ[[[[}}:11(_;=&..+#>;~1}}[[Q[[:|(((:}[[[[2}|(-@..+%$=;_|}}}[[Q[QQQ[[}}1|(!,*%.........@%=-~(::[[[[Q[Q2[[}1(~-#...&$-;(1}2[[[[21(|(|:22[[[1(;=&....+&*>!(}[[Q[QQ2[}}1_;,$%+.......%=-~|:}}}}|_'--=>-;~(1}2}11~-&.+%*,;_122}1|(!;-;'_|2[2[}|('-&.....&#$>,-!_|:}[[[}21('--,$*%+...",
|
||||||
|
"....@%>,;adb4hloqWqqpgfbc->%@.......@$>-adee77hkhgheba-=*%+......+&>,cdf77hhhhh7hh7k74bbba;,*@.....@%$>9;adbf77kkkhk7h77ffeba;%..@>adf47hhhhhk7hhh77febaac,=*+...+#>3abf7khhkhhhhkkhhhkh7fdc=#....#=9aefhhhhkhhh<kkhkhhhh7fba-&....&*=,9cabbf477hk7h7777ffbb0>&..@*30de77hhh74febbbe7hhhhh7ed3@..+&$-cdbe77kkhhghhhh77fbdc9*%.........&*=3a:f7hk<hhhhh777ebd9#...&=9ade77hhh77febbe7ghh77fba,%....&*=,0bf7khhhhh774bd0-*#@.......%,;abf7g77fbdc;9-;ade7gh77bd,&++#=3ab7g77febdac0dbf7gh77fba-&...+&**,9c0dbff7kkk74fbb~c03>*&...",
|
||||||
|
"....&*,cde4khllnoZqqoml7b03>#+......&*30(e4klXpppnpm7bac>*&+......#=9d4klVVmXmVllVVlliligfbc,#+...+%=-!d:e7hilllllVlVlmimlkkea$+.&>de7hmpXmVVVllllllhhhg7fdc=#...+$,0|4<llmpnmlVlVVVVmjmmked9$+..@*-!b4<hlVXmXVVVllVlmmmmVh7:0*...&*=;~b:fkhillVVlVVVmimllk4|c%..&=9_e7kmmmmVlk42e4khhVmmmihe0%..+#=9ab4kkllVmnnpmVlVlk[ed9=&+........&$,0b4khllVmmpmVVVlk4ba$+..#>9de7lXppmVlk4447ippmVVk4dc*....&*,c(4<llmpmmVllk7:a9>#&......+#3a14hmnpmh7eb_a~db47mmppl7bc#.@$;abhlXXmmihebb|e7hlmmmiked9#...@#=ccd:f4hihllllVllhhg7fa9,#+..",
|
||||||
|
"..+%=-!]ryBACCCHGHHGGvGxz/{;,#......%>!]rxtBGDLEEuEvAyrF~-$@.....+>;{^sACAGGLGHCCCCBCGGvvAJF),#...%-;{/syBHGDvHBCCCHHHGvvvHAx/-&.&;/stvDLvvHBCCBBBBCCHGvGwzF'>@.+%-~]rtCCHvDLGHCCCHHGvLDDtJr];%..&,~FzyCCHvvGGHCCCCHHGLLvGCtsF-..+*-~FrsABGGGGHACCCHGvDuvGAAs)*.+*;)/stGGLDvHCBxssyACHGLvDGtsF>+.&=-~FzsAACCGvuvEDHCACCxzF);$@........%-;{ryBCCCBGDLvGCBCBxz{,+..$!]rstGLDLDHCCBAtBvuLvHBBxr(-...&$3~]rxACHGLDHHCCAsz/~;*#+.....+=!]zxBDELvGCAsr^rzxAHvELEvAz(=+@-{/ztvuDDvGtyzzzstHDELLGAyr(>..+#-']rsyBHGvGHBCCCCHHDvGwz]~,&..",
|
||||||
|
"...%>;~]zxBCBCBCCCBCGDLAs/]~;*+....+%,;]rsAAGGLLELuuvts/);,%.....@>!{rxBBCGvLvHCBCCCCGLLDvs^);%..&$-!]zxCBGGvvCCCABCCGLLLvHBy^;+.&;/sBGLLLGHCCCCCCBCHGDDDts/{;#..%,~FryACBvLvGCCCCABHvEuEGyr];#..&,']zyACHGLLGBCCCCCCGGLvGCBsF-@.&>;)/sBBHGvGGBCCAACGvDDLGHAs)%..%;)/zAGLLLvCCAAysxBCCvLLLvHsF-++@$-']rsABACHvLELLGBBBAyzF'-#+.......+%-;]rsAAACCGGLvHCCBByr]-+.+$;{/sAGLLLGBCABABHGLuvCBtsr)=+...*-!]ryBCHLLLvCBBAsrF)-$&+.....+>~FzyGLuELHBAxzrrsyAGLuEuvtz]$+@,(/JAGLDuELGAszsyBAGLELvHsr)=+.+*-)FztCCGvGGCCCABBCGLDvtzF);#..",
|
||||||
|
"...%*-;)FrIKzIrIrQIIJwOP}|';=#......+#=;)][QIJOwYwwOPI[{~->#.....+#=;)FQKKJJwJPIIQIKKJwwwOQ(;,%..@*,-_2KJJJJJPIQQQQQQPJOOJPK/)=..@>_}QPOwOJKIIrIrIQrIJwNw8<|'-&..@#>')/QKKJJJPIQQrIIIJwNSP[|'-&...#-!{/IQKJOJPIQIQrQIJJOJJKIF~#+.&*-!1QPJJJJPPIQQQQQIPJOOJKI};&..@=-~:[PJwOJPK^/FF2^IKJOwO8<2_$...@*,;){F/[QIJNNNOII^/F]);-#+.........+#=;)]F/[QKPJJJPKIr/F_;*...%>;(2QPOOJJKKzrIIKPwJPIQ/:);#....@*-;)F[/IJSwOKQ^/]);-*&........*-~1[6YNNNOKI/F]1/QIJwNNN8<1!%.+$;)2<JOwwww8I[2/[QIJwNNOI2{;*..+#,;1[KPJJJPPQQIQrQIJwww8Q(;-&..",
|
||||||
|
"...&*=;(2[QQQQ[[2[[<8OO5}(_;,&+.....+&*>9!(|Q<PPP6PPIQ}|;-*%+.....&=-'(:[Q<5IQQ[}2[}Q8YSR84(;,&..@*-9([6OO6<<}}:|(||:[<<5IQQ}!%...#;(1Q<P6IQ[}::1:1:[5OSY6[|_-#...&>-'(}[QI5P<22:::}[8YSY64(c=@...%=-!|}[Q<P5Q2:1:::2[Q<<QQ[|-@..@*,01<OOO85Q2:||||:2<<I<K<[1-@..@%-'_1[5PPIQ[}1||:}[<<PPP<2(;%..+@&*>-;!~|:[6YSY8<:|(!;->*@..........+@**-;~((:}QKPQQ[[2_~;>&...@$-'(}QIP6K<QQQQ<I<K5[2{(!-$@....+&*,;!(:25OO8[21_!3-*%.........%>;_1<MNNNOPQ[||1:[<6RNNM82(,%++%-c([<P6OYY6<2}1:}[6YSY871~,%..+#,;1<6OO8<Q}::1:1}[5YSR84|'-%..",
|
||||||
|
"...%$,;d4khhh4k777hipqoi7bbc9*+......@*=-cab7hhlhlllkh4bc3=%@.....@*>;_b47hlhh4eeeefgmoWWjgba-&..+*>cbiqqqpg7bbd_0aade77hhk7e9@..+*9ab45lmi74bb(ddbbgiqWWoied3%...@*3cdef4hlihf:b:bfgpqWqpfd;=&..+@*,cdefkhlk7e:bbbbef7k4h74b,+..&*3agpqWqmgfbb_a_adbf7hhhk7e3@..@%=9ab4klllk74:b|be7kkllhhed9#...+@%$=,39abfiWUqpgbd0;>=*#@...........+%#=,9c~db7hhhk4f:d0-=&...@$39df7llmih4hlmmVlhhfdac-=#+.....@&$,30dfiqjpfbdac,=*&.........%,cafgqTTTqik7eb1fkimqTTTjfd3@.+*3ab7hlmoWqji774ffgiqWqjgba3#..@#-cfiqWqpgfed(ddbbgiqWqogfd3%..",
|
||||||
|
"..+&=3cekVVVllQkkkkmnWopk4ea9=%......&*>90de4lmXXXVVVlhed03$&+...+%*,9de7klVVlk74444hpZWWoiea3%..&*9afpZWWoV7ebd_000ae4kkhhh49&..+$cdekVXXml74bdddde4pZWWomkb0#...&>9'bekkllXlk44e44hnZWWpgb0,&...&=30bekhlVVl7e}eee4khkhllk13@..&=9dgoWWZnl4eddaaad:7kllllke9@..@$>cdekhVVVlhk4ee4[klVmVlh4d;#....+@%$,9cdbgpWUWjg:da3,$$&+...........++%$>,90de7lVlhk4ed09$&...@*30d4lVXXVlllVnXXVVl4d03,>%.......&*=90dfmoqmgeba;,$#@........+#-0dgiqTTTWnVk774klXoUTTUjgb9&.+*;aekVXXqWUomlhk74inWWWohed9%..+#3afpZWZnl7eb0addb7nZWWomke0*..",
|
||||||
|
"..&$;~]zyCBCCCCBCCHHvEDGAyz/);#.....&*=-)]^zxCHHGHHCCCBsr])-$@...+$-;)/ztBCCBCAAtAtABHEEELtsF'%..*,)FKAEELGAsz/{))~){/zsxyxxz)@.+&-)FzxCCBCBysr/]{F^sHDLLGHtzF=..+%-!{rsACCHHAtxssxtAGLLDAK/'-%..+#-!{rstCBCCAxsssyxyABAAttyr;@.+*;(^xDLLvGtsr/{)){FrstAABAy^'@..@>;)FzACCCCCCtyxsxAACHGHBts/)*.....+#,-;~FrsvuEEvyI/('-=*@.............+&$-;!)/zxBCCAAxzF);-&..+*-;(/stCHCHCCHHHGHBCts/(;;>#+......&=-!)2KALDGsz^]_;>*%........@,!]rswEuuuEvHAAABBCHDEuuuus/;&.+=)FzxCCHDEEGHBCCtytvEEEGAz/)$..@>)/JtEEEGtsr^]{)FrsHvELGHts/-+.",
|
||||||
|
"..@=;)FztCCCCCCCGvGLLLLHtxz/);*+...+@*,;']^zAHGGHCCCGGCyz/);,#...+#-;)/zyACGvGCBBBBBCvLLLLAz/;&..#;)^sHDLLvAs^F)'!;!'{F^^rrrF;&..%-)FzABCCCtxz^F{){/zAAHGBCBs]-@..%-!]/syACBCCAyxABHGHHCAs/{!,@...#-;]rsAABCAByyxytCCAAtszrr{-@..*;FryGLLDHyz/]))')]^zsyyxyz/;@..&=-~FzxCBCCBCBBBBBCCCBCCCBs/)$......&*>-~{^stLELGsrF);,*@+..............@#=-!)]ryACCBtszF);=%...#>;)/sABCBCGvGGvGvCtyrF);-=&.......+*-;)/KtGLtyr]]~->$@........@$!]^stEEEELLHCAAACHvEEEEDGs/;@.+=!FzyCCHvGGCCCCABAAHLLLLAsF)$+.@-(^sGLLvGyz^])'){FzACHHCCBsF-@.",
|
||||||
|
"..+&=-):rKKzKKKJwNNNNNw8Q2]);=&.....@%*=-'|}PJwJIQIKJwOQ1(!-=%....+*=;)]/IKwwwJKzrKKJwNwNO<}~>@..%,;([6www6Q:);->=>>,-;;;;;;-*+.+&*-_]QIKKr^F|);;--!(2IIKIIr[)=...@*,;)F/QrKKKQ^[I8wJKQ2}(!-=%....@=,;)F^rIzKrQ/}IPOJI/]()!;-*...%-':<Owww5[]_;---;!){]]F]{)!>....#=-~:/KKKKzKKrIrIzKKJKKKI2)-%.......&*$-;_26wNS6[_'-=%@................+@#*=-;)/IKzI^F|'-=%@...&*=-'FQKJJwwwwvwwwK[]);-=*%.........@#,-_:5OwP[1~;>*#&+........+%>!(2<ONwNwwwPI^IKJwNSNNYP[_$..+#-!]/KKJJKJKJzKzI[Q6wNwJ<:_,%..@,!(46www6[:';-,,-!(}IKKIIr2)=..",
|
||||||
|
"...%$-!|[QQII<I8ONNNNYO5[}(~->%....++&$,;~(}<OO5Q2}<6O6[:~';=&....+&=,!(1[<OYOK<QIQI5ONNRY<1~>+..@,9_15YSY6}_;-=*$###$$$>>>$*#...@*-;(}QIIQ2|_;->=,;_:}QQQQ[}_$+..@#=-!(:[<I<Q<[<<6YO<}(_;->#@...+@#=;_(2[<K5<[4[<8Y8[1~;-,>*&...%-0|[8SSO5:_9-,--3;_((|((~!-*+...@$-;(2QIIIIIQIQIQQQKIIKI[:!=@........@*=-c15YSY5}~-=$%+.................&%$$>-~|[QQ221(;->#+...&*>-'(}IIJwNNNNNSO<1(!-=#%+.........+%*-;b<8O<:(;-$$%@+.........%>-a:[ONNNNwO6<[<<OOSNNSY5:!#+.+%>;([QIKIIIPPJP<[[[8YNM6[_;-%..@$c(26YSO5:_;->*=,9_12[QQQ[:!*..",
|
||||||
|
"...&*,0b4hlllllppoojoomi4fba3=&.....@&$-0dbfkmmkgffgipmgfba;,#+....%*30bb7ijWqplhlhVmjUUUjgfa>+..&,cdfpqUqpfd9->#%%%%%##$*$$&@...&*30b4hhh74bac,,==3cbf7kkh7fd$..+&*=9abe7ijqjjjjjqqqifda9,*#@...+@*=;_bf7iqqjjjjjqqjgbac,=*&+...&3abgjWUqibdc-,,;0dbeeeebda3*...+@*30d4hlmmllklhllhlVmmlh7e0$+.......+@%=90biqWqpea9*#&..............+@@@@%*$3c_e4hk4ebdc,*%....@*=9ab7hmmZZUUUUWqifdc-$#&@.........+&*,cbijqiea9-**#%+.........&>9abgjWUWqoppjjjppooWUWqif0*..+#3;b7hllhhhmjoopi7gpqWqjgbc3&..@=cbfpqWqiea33>$=,3adf77kk7e0$..",
|
||||||
|
"..+%=9~ekVVXVXlXXXXnXXXVk4edc=%....+&$,cd14klVVlkkkhlVVlke:ac=@...+#=;a:4hmZWZoXVVXVXZWUUqp7b9&.+&3ab7pWUUjgdc9*#%&&&%%%#$*%%@...@=ca:kVVVlk}d;3,>33a:7khlll7b>+..&$3c_e4ijUTUUWUTUWqifb09,>#@....&$=0dekijWUTUUUUUWoiea9,$#@...+%;afioUUqp4bac99a14kkkhk74|a,@...%=9_bklXXXXXVVlVVVVXnnXVhea>+........@$>3aepqWWpgd;3*&...........+@&%#$*$*$,9ab4hllk7eba9=&+...@#3;dekVXnZUTTTUUqm7bac,*#@.........+%*-0eioqp7ba9,>$##%@+.....+#,9d4ioWUWZXnoqUUqnnoWWUZp7a=+..#,a1kVVVhhlmZWZonlmnWUWogea3%..+>abhpWWZpfac3==>,3a:4kllVl7d=+.",
|
||||||
|
"..&=;~FzABHGHHCBHHGBGGGHAys^{;*....@*-'{^sxBBHCCBAtACHCBAys/);#...&>;)/zxtHvEEGHBCCBHGEEELGxz(%.+*!]rsGDEEtJ^]~-,*%%%#$#*$*$$&...#-)FztBBCAAs^{~!;;)]zyACCCAx^;+..%-;{/zxHDEEEuEEEEEvGs^]);-,%...+%-;{/stHDuEuuuEEEELyI{'-=%+...+=)/ztDEEDAJ/]))]^sACCBCCByz/;&..+*;)/ztBHHHBCCCCCCCHCCHCCtz];@........%,;_:KHuEEGs[{!,#.........+&#>---;--;-!)]rsABBBxsr]'-*+..+&=;)/stCHvLEEEEEELGys^{';=#+........%>3!{ItEGGszF(!;----=*&+...@='{/stDuDLvHGLEEEEvGvLEELGJ/-@.+>!]zxCCCCBBGLEEvvHHvLELvAKF~*..@;FKyGLELGs/_~;;;')/zxtCCBCx^-@.",
|
||||||
|
"..&>-)FzACBCBCCGBLLLvLvCCBxr{;*+..@#-;)FzsAACCCCBtABCCCCBxs/{;*+..&=;)FzsAHLLGHCCBCCCvLEEGHyr{#..*']IsGLELHsr]~;,$#%###*$*>*%&..+&;'FzyCCCCxs/{!;;!)FzxBBBBCy/;+.+%-!)/sttGEuEEEELELLtsr/)~;-*+...*-!]^sytEEEEEEEEEEGx^)!-=&+....>~[sAGLELAs^]{)]rsAACCCCAxz/'*...%;)FzyCCBGCCCCBBCCCBGBCCAsF-&.......+%>;)FItELuHs^);-%+........&$--;!)~~';;')]rsBBCAysrF~-*....%,;)FzABCCLLEEEEELHtzr]~;-$@........%,;)FKyGLtyr/{~;;;----=&...+*;)^sBLLLLvCHLEuELvBGLLEvts^;@.@>!FryCCHCCCCGLLLHBBGLLLvtzF)$+.&-FrxGELuHs/{';-;~{/zABACBAy^;+.",
|
||||||
|
"..@*=-_]QKKJKKPJwNNNNwwJKr/|'-&...+&=-!)2^rKKJJJKKPPJJJKK/}{;-%...&%=;_]}[IOOJPKIIIIKJOwOOPI}'*++%-!([8www6Q|!-=*%&&%##*$###&@...@=-~FQKKKI/F(;-,,--!]/rrrKr/)>...@*-;)1^QPORSMYwwwNOK[1{~!-,%....@*,;(F[Q6YRSMMMSwwOQ(;-*#+.....#;~:<Owww5[|''!'{/IKKJKKKQF|;#..+&=-~]^KJJJJKKKKIKKKJJsPKr})>+........@$=;_25SNw6[(;-$&.........&*,-!!)~!;----!{/IKr^^F|'-=%....@%=;)FQKKJJwwSwwwO8KQ1);->$@........@#>-~:5OO6[|)';->--;--=&....%>;_:IOwNwJII6wOYOPIPwwww6[)=+..$-'F[KKJKIIKJJwJPKPJwNwJ<2),&..@=~1[6wNw52);->=,-;)F^rrKzI/_>..",
|
||||||
|
"..&#=-;|[QIIIIIPOwwNwwOP<[}(;$%...@%$>;(2[<I6OMYYYOYMRY6KQ2|'-%...+%$,!(:}Q<PQ[2:}}}}[I56IQQ1_$..@=;(15MNM8}(!->$#%%##$$**$$#&...@>-!|}QIQQ2|~;->>,-'(:}[QQ[2'*+.+@$=;_1:[<PP6P5<5OYO5}1((~!3*+..+&*,;_(}[<PP55<55OR8f~-*$@......%>~|[6SSO<:(_!'_|}QIPOO8PQ}(;%...&*-;(}QIIIIQ[22}}[[<IQIQ[:!=+.......+&*>-~15YSY8}(;=*&+........&=-;_1:}(!;---;_1QQQ[:|('-*%+...+$,-!|[IIII5I55686665[(!-=*&........+%=-c|<8O51(~!---;~~!;,#+..+&=,a|7OSNY8<[<58P<[[<6SSO5}~>+.@#>;(2QII<QQ<<I5II<POSNR84(!,&..+*;d}8YRY52_;->$=-;_:}QQQQ[2~=+.",
|
||||||
|
"..@#=-0b4hhlhhhVmpojjomlkh4bc$@...@&=,cb7hlmoqUUUUqTUUqjmlhfd,%...+%*-0bef7hhhf1bbbbe7hhhkhkfa,++&=cafiqUqpfba3,***#*==-3==>*&...@=9cb4klhhf1a0-,,-9abf7<hh7:0*...@*=3abe44hkhh47imoji7fbbbdc>....&*=9abe4khlhk77ipjpg0-*#@......%,0bgjWWqifbdaaab4hmoqZqpi4ec*..+&*90bfkllhh74eb:bf47hlhhkea,%.......@&*=9cfiqWqifd;3*&+........%,;de4hk7ba;;9cdekhk7eba;-*%+...+#=cab7hmmlhh<hh5mnqjieda9=#........@#=90biqjpfbda00a_bbbac>@...%>9abgjWUqige7khkh7fijWUqif0>..+#30d7hhlhhkhhhhhhlpoWUqjgbc,+..+$0dgiqUqieba;3=,3cde7h5hk7e0*..",
|
||||||
|
"..@*>3a1kVVVVVlVVVXXXXXVlhk:a>@..+%$,cdfhmnoqWUqUUUqUUWqnmVke0#...&$,9d14klVVk7e:e:e47<llVVlkb>+.&,cbfpoZojh4bdc;,>,9cdddda'0>+.+&>c_ekVVVhk4ed~c;0a17hmlllhfa$..+@*-cde4klVVlhkklmonmhk[44e(,@...@*-01e7klVlVhQ4hmppfa,$#@......%9dbhjWWqmhee|b1e4lVnZZZnVh4a*..@#99d:kVVVllk44eee4klVVXlhedc%......+@$>3cdfpqUWjgba9>$%@.......%9ab7lmml7:bb(bekm6Vkke|03$%+...&*3cdekVXXmlhhhklmnonmh4|dc$@......+#=3cdfmoZphebb{de7hhhfd9*..+&-0(fmoWWZpk47khhk44ioUTqp7b,+..#-0:kVVVVlhkhkhlmXnZWUWohfa>@..@>cbgpqWWphe1d!09~dehVmmVVke0*+.",
|
||||||
|
"..%>;~]ztCBCCCBCCCCCBCCCBCyz/!$...*3)]rxGDDLvDDvvvvvvvDvDvvts]>+.@#-')^zyAACCByszzzzstCCCCCBy/;++%;)}stvvvHCAsr/])))]/zxyyszF~&+@*;{^zACBCCAxsr///^rstGvDGAxz{-..+%-'{/sxACCCAByxABHHBBCCBAAz~&..+#-']rstACCCCtyxxAAs[(;,*&.....+*;FrxHGDHHAyszzrzstCCGGBvCAs]*..#>'{/zACBCCCtxszzsxACCCCCAsr{=......#$-;~F^sHEEEGxr/{!->$&+....+>)/stGGvGtszr^rsAGvGBysr]!,*+...#-!]rstCHBCBCAtytCHGGBBAsr];#.....+#=;'{/KAEDHxsszzzsADHGyI{=+.+$;{rsALEEDGysssssssxtDEEEGs/;+.+='FzxCCCBCCBxxyACGDLEEEvyKF;@..%!{^zAGGGHCxsr/F]/rstDGvHByz]-..",
|
||||||
|
"..@$-)FzyBCCCBCCCCCCCCBCCBtzF'$+..#;)FzyvLELvCCBBABBCCCvLELGz]=..+*-!]^syBCCCBAyzzzzyAAACACBx^-@.#-~FryCCCBCAAz//F]F/zABBABxz~&+@*;]rstCCBCBysr^//rssHvLLvAy/{=+.+%-!]rsABCCCCAxyyytABCACBBAz)&...#-)FrsACCCCAAxssssrF~;=*@......*!{/sACCCBCAyszzzssxCCCCCCAs)%.+%-!]rsACCCAAByszrzytBCCCCAsr{-+....#>-;~{/IsGLEuvyr/{)'->*@....+=)/sAvLLvAyzzrzstvvvAxzr]!-#+..+#;~]rsACCCCCBByxyxCBCCBCtzF'=+....&$-;){/JAGLHAszzzsytDLDtz{-+.+$!]rstvLLLBxszzrzzssBHLLvGs/;@.@=)FzACCCCBBxyssxALLEEEuvtzF;%..%-)/zyCCCCCByz///rzxHLLLvAsr{,+.",
|
||||||
|
"..+%=-~]QKKKKrIrIrIrIKrIr^/|!-&..+&>;_:<OwNwJII/[^^QQQKwNNS8[!%...@=-~{F^IrKKr/2F:F1/^IzKzKK/(>+.@>-'{^KzKKKr//|_({(F//rrrr[];@.+#,!{FQKKKzI//1|{1|}QPwwwJI2);%..+&=-']/^IIKPKQF//2/^^rKrzIr};&..+%=;)F}^IrKKI^F2::1)!-*%@.......&=3_]QKKKKKr[F1F:F2/rKKzKIr};&..&$-;)F/KKzKr^/F]]]/^IKKKKI/|;*...++%=,-;'_:[6RNw8Q1(';-,*#@.....*;_25wwww<Q:2]2[5wwJI[]_',*@...+&=;'{/IKKKKr^/FFF/IKKKrIr}{;%.....&*=-!~{}POOPI[}}}2<8wwwP[_=+..#-'1[5JNwOP[:]|(({:2IJwNw6[(=+.+*;']^KJJKIr/F}2[PwNNNuNOQ:_>@..+*-':^KKsKKr^211||2[6wNwJ<2)-%..",
|
||||||
|
"...&*-;(}[QIQQ[[[222[[[[}:(~-=&...%>-_1[8SNRO5[[2}}}[<5OMNR5e!&..+%>-!|}[Q<I5<[2e1e:2[<<IIQ[}!#..@%=-_1[QIQQ[[2::1|1}}QQQQ[}),+.@&,;(:QKPI<<[}2:11:275OYO82(!-%...%=-_|}[Q<PI5[4}}4[}QQ<<<I[};@...%=3_:2[<I5K<[2:||_!-=$%+.......@#,c_}QIII<Q[}::}:e}[QQQQ[2_,+..@*-;_:[I5PI<[}||(11}QP6PP<}(;#...+%*>-;~(b:45MNR872|(~;->*%+...+&,~|<8SRO5[2e:1[56O5[|('-=%@....&>-'(}QIPI<Q[}:1|:2QI<<<<2|;$+...@%*-9_b175OY6<[422f<6MSY51~>..+%>;_2<OSSO5}|(_~_~(:78MSY5}_>+..#-~|[IIP5<[2:(12<OSNSNR87(;,&..+%=;_}[<QQ<<[2:1:e2<5YRY52(!$@..",
|
||||||
|
"...%*>3a17khh<h4ffef474f:bd0-$@...%>9afiqTTUqjmg7f47imjWUTUjg0%...&=;dfipjjqqjjijiijijpppmhf|9%..+%*,0be47kkhiiiiiiiiikhh7eea-+.+%3abgijqqjjpppiiijijjjpmiba9>@...%>9bgipjjjqjpjijijipppppi4f9@...#>9bgipjjqjjjiigebac=*@........+%=9ab47himmiiiiipiiiihh44ba>..+&*9abgijqjjpigfbbfgipjZojpge0*...@#*9adbfgijqTTTqjigfeba9=*@...+%,0dgmjojpjpiiiippmieba;,*%@....&=;aegpjqjjpigebbee7lmpjpied=+...@*=9afgijqUUqjimippjqUUqjf0$...#3cbgiqTUqig:bacade4iqUUUjgb,+.+%3abgjqojjigfbbfgmjWTTTjgbc,&...&*30be7himppiiiiijjpppmgba;#+..",
|
||||||
|
"..+@*>-0b4kllmVl5ihhihh7f|dc3#@...%-afhjqTTTWWZmhk7lpZUTTTTqhb#..+#,0biqqUUUUUTqUTqUWWZWZXifd9#...&$,cd1e4hlVnqqUUWqonmVll7|a,@..#;b4mqUTTUWUqUTUUUUWonmlhba9$+..+#3afiqqUUUUTqUUUUUWWWWWonl40%..+%9afpqWUTUUUUUqoifbc,$&.........&$9!be4hmoWWWWqqUUqXXllk410$@..%,cd4ioUUUWWZph447moWWUWWqp4b=+.+&*-a1khiqqTTTTTTUZpmhked9*&....%>9afkmXnqqUUWWZoXmked03>$@+....#,ab7pqTTTUWom4e1e4hioWWWqm4c&..+%$9agjqUqTTTUWWqWqUUTTTUjg0=+.+%,_ehjWTTUol7ed~ab7hjqTTUqmf9+..$9d7pqUUUTqjhfefkljqTTTqiba3#...&$,9de4kmoZZWWWqWqWomVl7bc3*+..",
|
||||||
|
"...&=-;)/zsAHGDvvvvvvvHtsr/{!>+..+$!FzxvEEEEEEDGAxxBGDEEuEEEA^-+.@=;|IwEEEEEEuuuuuEuEEELEvxz:'$...&*-!{^zzxACGDEuEEELvCCAxs^{-@..*)rsGvEuEEEEuEuuuuuEDCAts/(;>+..+>~2stEEEEEEEuuuuuEEEEEEvHts]*..@=~}zGuEEEEEEuEEvAs/{3>*+........&>;)F/zsHvEEEEEEuEEvHCBxz/(-+.@*;{^xBDEEEEELHxssxGvEEEEEDHxF>..+*-)FsABGDuuEEuEuEEGHAAs/)-*....#,'{rxBHHDEuEuEEGCBsr]);>=@.....$;]zxGEEEEEEvAJrrrzsADuEEDtsF=..+%-!1VNEuEuEEEEEEEEuEuEuuZz:-..+>~FsAGEEEDDHxz/]F^sAGEEEEDts)#.@>~/zHEEEEEuGJrrzytGLuuuuXI];*...&=;~]/rstDDEDEEEEEvvHAyzF~;=@..",
|
||||||
|
"...&*>;~{/zytvvvuLuLLvvAsrF);#+..+$;{rsAtDvDGHHtszsxAtGuvuvAx^;@.@=;{/JtvtHvvDvDvHGGGGHGAAz/]!*...+&>;)]/^zsxBtHGGGAHBAyyz/])-@.+%!FzxyvvGDAGDtDvHvtCBtyz^]~;$+..@=!{rwtGGGNvDDDGGGvtHHAHBtsr(=+.+$!{IytGGvGGvvGHwsr])-$@+........@#-!)F/rsxGtGHGGGGBABtsz/]~=@..&-)/zxAHDvGHGxyzzJytHGHHHBtz]>+.+*-~]rsxttGDDEuDvGGBBAsr]!-#+...%-;)FzsxttHHHHHGHAxz/);,$&+....+%;{^sytvvNGvAsr/F//zsxGtGtyz(*...#>;]zXHvDDGuGGHHHGGDDDDAy^(=+.+$;]rsAHvvGAxs/]){FzyAtDHNAyr)%++>;{^JtvNvHGxz^/^zyytGGGxzF{;*...+%-;)]/rsytGtHGtHGAAszrF{!-#+..",
|
||||||
|
"...+&&$,-!_:Q5JOJOOOO66[|_;-*+....%=;~(:}e}}}}::{(((:}}4}2221~=+.+%=-~{e2442}4}}ee}e2}2}:1(;-*&.....&*=-;;))1:2e}}2}22]()~;;>%+..+*;'|ee24[44[eee24}e:{();-=*&...+%=-'{ee}4}4}}4}4}[4}2}}:](~-&..+&=-!1e}f[}4}}e2:1~;,$@...........+#=,-;!(|:ee}4}}}2:{))';-=%...+%-'(|}42}}e2:1(({:}f}}}22:);%...&*,;)1]2}e:}424[4[}F]{';,#@.....%=--~)1:e}}4[[}2:(~;->#@......+&=-~{:e4[}}}e1~;;;'~(|e1e:|_-@...@$>-~{:ee}}}}[}2}4}4}}}e1'-#..+%>;~{::e222:(~;;;;~(1ee}}:|'>+.+#=,~{e}}ee2:(~!~)({:e}e|_;-=&.....&=,-;;)11:e}24}}2:(~'--=#@...",
|
||||||
|
".....@%*>,-0_::4[[[[22:_;->*&+....@*>-;0____(__!;9;c'_______'-%...+#>3c~__(((((_((_(___a!;-,*%......@%##*>-9;;'_d____'!;-,=**&...+%*-3c__(((({((d___!!;->=*$&+....@%=-c~__(((((((((((d____';-*+...&*=-c__((((d(_~!9-**@@............+&**>>-9c_~_(((_'!;--==#%.....%=-9a__d(__a!;-990__((_(_!;$+...+%*,-c~~__|(((((|((~!;-=*&+.....@%$>=-;!___((|(~;;-=*%&........@*=-9~__(d__~;-==>>-9;00~!;-#+...@&#>-9'___d((((((((((__~;-=@...@*>-9!____~';-===--30'__~!c-#...@$>-c~___'_!;-,--3;!'_~!-=*&......+@&**=--cca_____~;-,==*#@....",
|
||||||
|
"......+@**=-30aabbbba009,,*#+......&$,3390a00cc93>-339000c9c;,%....&*=330c00aaa000c009cc3,=$%@......+@@%#$==,39c000ccc3-=$$#&@....&*>-39900aaaaa0c0c93->>$#%@.....+&*,39ccaaa0aaaaa000909c;3$#....@#$>9990a0a0a0c9>>$%+...............&&#$=-,99cc090c93>>$$&+.....@#=-3900a00;39,>33909000993#+....@#$,-9cccaaaaaada00;3>*#@......+@%$$>3390aaaaac-=>$#@+........@*$-339cacc9c-,>*$*>>,9993,=&....+@%*-93900caaaaaaaaaacc;3=#+...+&$=,339ccc9->$**=>,-39cc3,=&...+%$>99c0c993=>*>>=,93c93,*%@.......+@%$*>=-,999cc9;3,>$%&+.....",
|
||||||
|
".......+@**=,3300a00039>=$#%@......@%$>9933099-,==>=>3333999,$&....+#$=3,9339993,3cc999,>=**&+.......+@@&#$$>,,333399,==**&@+.....@#*=,999cc90ccc939->,***@@+......&%*-93990;99990c33393-3,=*&.....@*$,-93ccc9c93,,*%@.................@&#**,,99999-3=>***&+......+&*>-93999333==>==399,3393=#.....+@**>3,9999cc0ac0c-3,=#%+.......+&%**>,999cc0c->=*#%@..........&#*,99ccc9-,,**$#$*===-3,>*&.....@&**,93339990c000;cc99,=*&+....@%$,,399,-,==*#*$=,,-9,3,>*@....@&==9339-3,,*$**>*=,,,>$$&.........++@%*$=>3993-3,=**%&.......",
|
||||||
|
"........&**>-3;!'__'!9->*#&&+......+&$>--;;!;;,>>$$---;-;;-;-*+.....@#$>=>----,----;;;--$$%#@............@#=>--;-;;-;-$*##&@......+%*$,-;;;!!;!;;;-;--=$#%@+.......+&*,-;;;;;;;;;!;;;-;,-3-,*&.....@#$=-;;;;;;;';-,=%+..................+&*$=,-;-;---,=##%@+......+&#>--;;'';--,=,,--;;-;---$&.....++#*>-3-;;'!!'~!;;;--=#@.........+&#%$=,;'';!;--**%@...........+%$>-;;;;;--=$%%%##==>,-->%+.....+&#$-->-;;;;!;!;;!;!;--=$&.....+%#>-,-->-=**##%#$=-,----$%.....+&$,--;---$$*#$*=>>=-,>=%&............+%=,----33->$##&@.......",
|
||||||
|
".........@##*$===>----$%@+++........+&%*==$=>**&@@@&#*$=**=*#&+.....+@&@&@&@@&&@@%==$#*#&++.+............+&&%#$>-,>>##@++.+.......+++%#$$$>>=>===*=$**%+............+@&$=>--->=>=>---,==**%%&@......+&%**$==>==$#*%@+.....................+.@#$=-,->=%@+...........+&%**$$=,=>***##%*$=-,>$%&+......+@%#*>>=>$>>---->,>*&+.............++%$>>--==$#&++.............+&#*$===$*%&++++.@@#%%%*&+........+&**#%*==========$*$%#@+......+%#==$%&@@@++++@&#%**$$*%+.......+%*=$-=*%++++@%&%%%%#&&+.............+&%**=$**%@@...........",
|
||||||
|
".............++@+@%&&@+................+..+.........+..++++++.....................+.+++......................+.+@&+@......................+++@++++.+....................@@&&&@.+.+@&&@+..++..............++++@++..............................++@@&++.................+...+@@++.....++++&@++.............++.++@&#%&&@&@@...................@+@@++....................+.+++++++........+...+.................++++++.++++.+.+.............+............++................++@@.......+.++......................+.....+.............",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"...........................................................................................................................................................................................................................................................................................................................................................................++@+@@+@++.................++@&@++............................+@@&%%*#*##%&+...........................+.............................................",
|
||||||
|
".......+@&&&&%####&&&&@+....................+@&&&&&&&@+................@&&&&&@+++@&&@@+.....................+@&%%&&@++..+.............+&&&&%%#&&&@+++@&&@+................+@@+.......+@&&@+..............+@&@+.........................+@&&&&@+.....+@@&@+..............+@+...+++...+&%&&@@+..........+@&&&&@+...+&&&&&&&%@+.............+@&&&&&&&&&&&&+................+%$--;-;-;---$*&+..........+%*=>>-,$#&@+........................@#>-;!'''''!;-$&+..................+@&%*#**#%@..........................................",
|
||||||
|
".....+%#*==$>===$>$=>=*#%&@...............@%#**=*=*=*%&@.............+%**=**==$*#*=*$*&@.................+&#$*=*>>==##**%#@+.........&##=$>$>=>==*$%$$**$#%@+.......@%##*#$**#%%#####$==*$##&.......+%#*#$==*##&@@@&%####*##@........@#$***=**&@@@@&&*=**$##&+......@%##*#$#*##*#####$=*==*#&+.......+%*=>=*=######*===$>**#@..........+%#==$>=>=>====*$$##&+..........@#,-'){]]F{{);;,*%+........@#$--;;;--==*&@.....................+&*,-!)]FFF]])~;-$&+................@#*=,,-,>=*%&.........................................",
|
||||||
|
"....+@%*$$=**=$===>*$>**#%%+............+&&%*$$>$>*$$##%@+..........@&%$$>>>=>=>=$>=*$#&+...............+@&%*$=*=$=>=$$**$&@.......++%$$**=**=>>>>>=$>>$$*#@+......+@%*$**==**&&%%*****>$**%%+.....@@%#****$$#%%&%&&**==$==*&+.....@&&%*>>$$*$%%&&&%%$$>$=*$%@.....+&%*$=*=$=******>*$>$$>**%+......+&***$>*>=**#$$*$*=*>>**&........+@&**$=*$=>*>>$>>$*=*$#@..........@#=-!){]]1](~;->$%@........&*=---;;-->*#@+.....................@%*>-;){]}F({)!-=#@.................@#$>=,-->$$%&+........................................",
|
||||||
|
"...+%*$>==,------,-,,=>***%%+..........+@&%*$===,=,,=>**#%@........+&#$=,,-,---->,=>>***#@.............@%#$$>=>-----,,=>=*$%&......+#**=>,>--;-------====$$%@......@#$$=>,>>>$$$*$*>=>>==>=$#@.....&#*$>=,>===*#$##$*>>>=>>>=@.....&#$$>===,>***#$#$$====>==*&.....&#$>=>>>,>,=>>>>=>==,,=,=*%.....&**=,>,=,=>>$=*=>=>>,==,=#+......+&%%**=>--,--,---,,=>=**%..........&*=;_|}}[221(!-=*%@.......+&*,;_((~~;->$%@.....................@%$=-;_|}}}2}|_-,*&+................@#*,-;';;-*#%@........................................",
|
||||||
|
"...@#*=39cc00c000cc9c9c3,=*#&+........+&#$>,3cc9cc9933>=$*%@+.....+&*=,3ccc0c0;9cc9993>=$*&+..........@%*==39cc0c0c0ccc93,=*#@....+&*>,399c;0aaacaac0ccc33=$%+....+%*=>3399933=>=>,9399c93,==&....+*$=339cc9933=*>*>=33c39933%....@%*=339c9393>=*=*=339c9c93=#....@*==9ccc;999933339c999c993=%....@*=,399c99c3939339c39cc993=&.....+@#$$>339c0c0c0c0ccc9993=*@........+%>3abgiimk7fba;>*&+........%*3abe7ebdc3$%&+...................+&*>-;0bf7iiiigb0-=%+...............@%$,;a_bba0,*#%+.......................................",
|
||||||
|
"..+#=c0_bbeeeeeeeeeeb|bdd09>#@.......+#=,99adb|eebe:bdac33>*&+....@$3c_bbbeeeefeeeb|bdcc3=*#@........&*=39ab1beefeeeeeb:bda3=#+...@#-9db:eeeefeefeffeeebbd03=%....%#3c_bb:b:bda9c!a(b1eb1da09$@..+%=-'db1beb{b~0c39c!d|b:b|b03&..+#>c'db:be1b_acc9c~db:b1bbdc>@..+#=9~d|beeebe|bd_db|be1be1b0>+..+%=cadb:b:eb:b(ddd1be1beb1b0,+....@%*,cc~dbeeeeeeeeeeeb:bd03%.......+@*>9bgoqZonVl4bac>$&+......+#,0|7kkk7e{03>*&...................+#*,ca14<VXnoopibc3*&..............+&=3cde777eba9=%&.......................................",
|
||||||
|
"..%-~FzyHtGtGtHtHAAHABtyzr]~;$+.....&$-!)F^syAtHHtGAtyr^F{~-,%...+$;{^sxBHAGGtGHAHHAAsz/{';-=&......@*;~{FzxHtHAGAHAHtGGtyr{!,&..@>;{^stAGttGtHHGHAGtGAGty/{;$+..@-;{/sAtGtGtsz^^rzyyABGAtszF;#..@=']rsABtHtAys/]{]^zyAAGHAAsF,+.@,!FrytAHtAtsr/FF/rsxBBHAAyz],++#,)FzytHtAGtAtsszsyAGAHtGAyz)&..@-'FzytBGtHtHyszzsxAAGtGtAyz{=...@$-;)/zsxxtHAGGAGHtGAHHAx/{=+......&#-;{rwvuELGHBxr])->%@......&>;{^sCCCAys/);,=@.................+@=-'{/zyACGvEEvxI{'-$+............+*-!{/zxGGGts/{'-*&+.....................................",
|
||||||
|
".+*;(/xGLLELuEuLEELELHCBAs/{!>@....&*-;)]^zyACGLLLELLAxzrF)'-*+..+$!FzyCLLLLuLEELLLLHByz/{);-$+....&*-!)/ryHLLLLLELELLLLDHs/);*..&,)FKALLEuLEELLLELELELLLts/)-+..%-)/KtDLELLGCszrzyBBGDLLHBxr)=+.%,)/sBHLLLGCByz/F/zxAHDDLGHyr;@+*-)/sAGvLLvCByzr/rsACHDLLvHy^;@+#;)/stHLLEEELHAxsxHDLEELLGAx{#..@-(ryBGDLEELvHtssxGLELLELGCx/-+..%>-!]zyBCHLLLuELuEELLLLLAz];@......@=-~{IxEEELGBBsr]~;>%+......&$;)/zyBBCBxr]'-=&..................&$-!]/zyBCGLLLDAr{!-#&............%$;~]^JALLLGyrF~-=*@.....................................",
|
||||||
|
".+%-'1<OwNNNwNNNwNNNwJKKr^]'->@....&*=-;){FrKJwwNwNwwPI[F('-=&...+#-)}QPwwNNNNNNNNNwJKQF_~;-=*+...+&*>-!|}<OwNNwNNwNNwNww8[_',%..&=;_[6wNNNwNNNNNNwNNNwNw8[_;>...&=;([8wwNNNwPQ1FF[IKJwNwJP^]!%..%=;(/IJwwNwJI^F_)|FQKJwNNwJIF-++&,;{[IJwNwwJK^2]{F[IKJwNwwJI]>+.&,'{[KOwNwNNwJI[[IPwNNNwNwK[~&..+*;{[IOwNNNNwJI}[QPwNNwNwwP/(=...&*--~FQKKwwNwNNNNNNwNNww8[_-@......@%>;':<YNNwJKIF_!;=#+.......+#=;)]//rrI/]'-=$@..................+%*=;)(FQKJwNNO5}'->%+............&*=;~:[8SNw8Q:);,*#@.....................................",
|
||||||
|
"..#=c(<OSNNNNNNNNNSwROIQQ21_;-#...+&*--!_|}[<POSSSNSO8Q}1(~;=#+...%>!|Q5YNNNNSNNNSSO8[Q11(!;>*&...+&*=;~(1<8YSNNNSNNwNNNR67(;,@..&=c_e5YNNNNNNNNNNNNNNNNS841;*+..&=3a28YNNNSO5}1(|}Q5OSNSO<[|;*..@>-~}<8YNSOPQ}|___1[<PYNwO6[(,+.&*;_}<8SNSOPI[}1||}QIOwNSO6[(>+.&=3(}<6SNNNNR8<}}46ONNNNSOP[!&...*;(2<OSNNNNY8[22[6ONNNNSO5[_>+.+&*>;_1[IIPYNNNNSNNNNNNNY84_,@......+%*-a1<OSSR5[1_;-=*&........+@=>'_:2[QQ[('->*&...................+%$>-!_:}5OSSO<1!-*#@...........+&*>-~_[5YNR6[|~;>$&@.....................................",
|
||||||
|
"..#>cbfijqoooooojojojpih574ba;#...@*=3abbf7hhmpjqjqojpiiieba3*+...#,0b4iqUUWWoqqjjopmhh4eeba3*@...@#>3abe7hpoqjqjqjoqqWUWjgbc3&..&=0dgmqWUWqqTTTTTUqqWWUWjgdc$+..@>3aepqUWWqmgebdbe4hjWUWji4bc$..@>9afgpqUUqi7fbd0dbfhpqUWqmgb>+.%=3dehpWUUomh7feeefkipqUUqigb>+.&=3degjqUUWqqigfegijqWUTUji4c&..+*;dfgjWUUUqqigff7ijZWUUWjif0>...&*=;deklVmoqqjqqqqqWUUUqpfd=+......@#*-cbgqUWqgfd03>$&@........+&$=;a|e4iikfa3=$#+..................+&%$=39degjWWqibc9$#+...........@#=3;dfgijqqpgebc3$#@.....................................",
|
||||||
|
"..&,cdeimXnnnnmmVlmlmmVVVVhkea$+..%=9d1kklllllmlmVmmmnoqojhba>+..+%-cd7ioWUWonXmmmlVVVVllh710,%..+&*,c17klVXXXmmmmXmnZUUUqhfa9%+.@3cb7pZUWqojqTTTUqpnoWUWogea>+..&=9d7pWWWZml7eb|be7hnqUWol4bc%..&=cdehnWWWom4ebddb:ehpWWUZmh|,++&>cdehnWWWomhkkkkkkklnWUWZm7b,+.&>caehoWUUWonVk444lnoZWUUoi40&..+#9aehjWWWWonlk74klXnZWUUolfd$...&=30bklVVXmmmmlmmpooWUWWjgd,+......@#>90eiqUUqifdc3=#@..........+*>30aehmomgea03=%...................+%$>-0aeiqUTqifa3=%&...........&=-9deklXnnXXVk4b03=%+....................................",
|
||||||
|
".+*3':rxBCBCBCBBAAtACCBCCCCAxF=..+$!{^sBBCBCBCBAtyAACHDEEvAs/;&..+$!{/stvELLGHBCABBBBCBCBCBs/'$..+*;)/sACCCCCCBAtBBCCvEEEDyK/'$.+*!]ryDEELvGHvuEEEEGGDLELGxKF-@..%;_/sGEEDDHtsz^^rrsyDDEEGts^)>+.%-~FzyHDEEGByzr/F/rsyBDEEvHs/;++%;)/sAGEEEDHABBABBBtBGEEEvHs^;@.%-~]^sGEEELGHBAxAtAHGLEEEDtz0%..@-)]ryGvEEvvHAtyytBHvDEEEGAz(-...#-!]rxCCCBCBCCABCCHGDEELGs2!&......@$3)FKtEEEDts/{'-=@..........+*-;~]^xGDvtsrF);-#+.................@#=-;{FzxvEEEAKF~-=%.........+&$-'{rsACGvHHCCByz]);=&....................................",
|
||||||
|
".+%-!)^sBACCCCBtyyyyABCCCBCCxF$..+>;]zyCGHCCBAxyssxytHGGvvAsr~%..+*;{/zAHvGvHCCtAxyBBBCCCCBy/)=+.+>;{/sACBCCCCAAyxxtBHGLvHxzF'*+.*!FzJGLLLvHAGEEEEGCCGLELvyz];@..*;)}zAGGGHCBsr/F/rzxBLLLvys/)$..@>'FrsBGGvGtsz^F{FrzyAGGGGtsF-@.*-)FzxHLLLGCBACGGHBBAvLLLLAsF-+.&>!{^KxGLvvvHCBBBCCBHvvGvHx^~&..@=;]/ztGvvGCBCBxyACCCGGGDAs/)$+.+%-!]ryBBCCCCBABABBHGvvvHtzF-&......@$;~FKAGLLLAz/);-*&...........&=-!)}stGCByzr]';$%+................+&*,;)FItGLEEtzF~;=#+........@*,;)]zACHHCCBHCHBzF);-*&...................................",
|
||||||
|
"..@$,;)][IIzKK^FF]]]F^rIKrKzQ~%...$-~2IOwwJKQFF1{{]F[QPPPPIQ};@...&=-~|[KPJJKI^//}F/^IrKzKr[{;%..+#,'{/IKKKKrQ//2FF[/IPPP<2{~-&..&-;1[6wNwJI<PwNNw6IIJSwwOQ1'>+..@>;(:IPJKIQ/2)';!~1[Pwww8Q:);%...#>'(1IKJPKQ[]_~!'(12QPKJK[:!*+.&=-~{[PwwNJPIIJwwwPIIJwwNOI2)>@.+%>-'{}[IPJwwJJKKKJwwJP<<[:'=+...#=;~1}Q<IPKKrQ^^IPwwJP<Q4:~,@...@*,;)FQrIr^Q^/[^IJwwJ5IQ[('$........&=-!:<ONwO<1_;=*&.............%*=;':QIIII/});,*&+..................@%*-!|QJwwO51_-,*@.........@#=-;)}IJOPIIIKJOP[_!-=&@...................................",
|
||||||
|
"..@%$-;(}2QQQQ}:(((_(1}[QQQ[2~%..+%-~1<YSSO<}1~';;!_|}QIIIQ[};&...@*-c_}[IIIQ[[211||}[QI<QQ2~-#...%,-_:QIIQQ[[1|111|}}QQ[[|~;=&..@=9_}6OSY6[[5RSNR54[5RSY64(!$+..&=9'|[QIIQ21(!--;c(:5OSY621!-&..+&$-'(}QIQQ[|(_'9;~(:[QQ<Q}_,%..&*-c(15YNSO<<<OSNM6<78MNS8<1!*...@*=-c_|2[<OYOII<KJYM6[}1|~-*+...@#=3c(|}[QIQQ[}}[POO5[}|(!-#+...@#=-'_:[[}}212:}[<OY5[}:(!-%.......+&=-0(<ONR8[_;,$%@.............+%=-c_:[[Q[[1(;,$#@..................+&*=c_e8MSO<1!->#@.........@#$,!_:<OO5[2}<6O6}(;-$#+...................................",
|
||||||
|
"..@*$9cd144hhhebbdddbe477hhh40&..+*9afiqUWjifda;9-90bfhhllhkfa*...+%>3ae4hlik44ebb:bf47hlhhed3#...&=9de7hlhh47ebbbbbefhk74bcc$&..@>;afpqqqpggiqUTqiggpqWqpfd0*...@*30b7hhhkfbd;3,-cafiqWqpgdc3&..+%*,;dfhhhhfedacccabe4hlh7eac#..&*30dfiqUWqigiqUTqjiipqUWjgbc*...+%$=90df7ijWqpllmoqqpgfbdc,%....+%*,9abb47hhk4f7gppqmgfba9-&....+&*,cdbf44eeeeefgpqqpgfba9>%.......+&*3abiqUUjgd3,$&@..............&*>cab77h47fba9=*&...................@*>9dgjUWqib0-=%@.........+%=-9dfiqjifffipjpfbc3>*@...................................",
|
||||||
|
"..&#=9ab4klV6lk4:bbb:4klllll7d#...*cd7mqWUoi4bac399c(4lVVVVlkb=+..&$=9aellXXmlkk7447hklVVll7d9%..+#>9dellVlVVhhk77447kllh4edc,%..&*3abioZZm7gpqUTUjghmoZqpgdc$+..&=30ekVlVlk4bac99cd4mWWZjhba,#..@#$30d4lVVVk4f1dd_be4lVVVl4d3%..@=9cb4pZUWoXVjqTTUjmljZUWZifa*....&*>30de4moZZnmmnqWZphfbdc>%....+&*=3abe4hVllhhhlnZomhebdc>%.....%*,cd|4f444447kloqoj7fbac=&........%=caeiqTTqib0,=$@..............+&=30b4kllVk41a9>#+.................+&$,cbgjWTqjfa9>$@.........@#>90b7moom7e4inopgbac=*@...................................",
|
||||||
|
"..@=;~FzstACBBxszzrrzxtCBCCCyF$..+-{^sHEEEGts^{~''~)/sACCBCAxr;@.+%-;)/sACHHHBBCBtACCHHCCCAs^)=..+$;~FzyACCHvGHGHAABAAAAtsrF(;%+.#-;(^JtHGtxywEEuuGyxAHGAsQ{~>+..#-~FztCCCCAsr])~~{/JtEELvyKF'*..@=-;{^sBBCBCAxzr^rzxtCCBCts/'*++#-~]^sHvEEDHGvEEEEEHHGEEEvAz}-....&=-!)F^stHDDvGvDvDvAsz/]~;#.....@$-!)/rsACCHGGvvDvGtsr/]'-%.....#>;!{F^rzzsxABCBHGvtsr/{!-&.......+$;~FKtEEEDxI{;-$@..............+&=;)FzsACCCxsr]';#@................&#-;([JDEEEwz4);>%.........&=;_]^ztHHtszzxCGAsr])3,&...................................",
|
||||||
|
"..@*;~FryABCCBAxzzzzsyBACCBBt]*..+-(/stGLLGAzF)!;;;{/ztCCCCCAr;@..*-!)/sBBBCCCBCACCCGLGHCCAz/'*+.+#-!{/sABHGLLuEELGBBBBAyzrF~-*..@>;~)/rsssssGLEEDwxssssz^]';=@.+%-)/zACCCBxs/]~'){^sAvLDGxrF'$+.+#>;)/stCBCBBAsrrrzyBBBCABzF'*..#-~]rJtLLLLGHLuEuEGGCGLLLLtz],+..+&*=-;{FrsACGLLELvGBxz^]);>%+....+@#-~)/zxBBHLLLLvGAyz/{~-$&....+&*-;')]F/rzABCCCBCByz/{~;$@.......&,-~{IyLLEDyr)!-$@...............@%-;)/zAABCBts/]!,$#@..............@>-;{^sHLDDHz]!;,#.........@$-']/zstxszrrzsAyz^]~;$&...................................",
|
||||||
|
"..+&>-~{F^IKKKIQ2[2[^QrKrKzIF~&...$'([6wwwOQ|';,>,-;)][/IrIrQ]-+..@*,;)}rKKKJsKKKKKJwwwJIr/]~-&..+&*=;)]FQIJYwwwNwOJKr^^[F(!-*&...&>=-;'(1::[5ONSwP4:|((_!;,*@...@$-)FIKzKr^F(~---!(26wwYP[|~-%...+#=-)F^rIzIr^/]1]F^rKKzI/F~-@..@=-!{[PwwNwJJOSNNNwJwwwNwOK2~*.....&*>=-!(F[IPwNNwJPQ2]~;->*+.......+%$-;)}IKJwNNwOPI2(!->*@.......+#$,-;~)|F^KKJKKKQ}(!;>$#........&*>-!1<OwwO<(;,*@.................+%=-!{/rIzIz[]);=*&@..............+#=-!|Q8www51~->%@.........+&=-;~((F1(___(]1](~;-$%+...................................",
|
||||||
|
"...&*-;(|}Q58O85<5<5<<IIIQ[}|-@..+*3_:<OSR84(;->,>=-!(}[[QQQ2),+..&#=-~:QKIIPPOJJ8PJ6PKQ[:1~3*&...+*=-;'(|[<5888O888855<<f|c-*@...+&$*>-9'~(|[OSRY5:('!;-,=*&@...+#-;|[<QIQ21~;---ca15OSY84(;>&....@#-;_:}[[QQ[:(((}[Q[[[2:_,#+..@*-c_:5OwNwOO86M86OJOYNNSO7|!*.....+@*>,-~_}QP66O65<[1_'-=*&+........+#=-'(:Q5YNNM6Q:(!-=*@.........+%*=,;~(1Q6JJ8I[}1~;,>*&........&*==cd<OSR87~;=*%..................@%*-;(|}[<<5}~-,*%+...............@$-c(46RRY51'-*#@..........@%*,--;;;;----;';;-=$%@....................................",
|
||||||
|
"..+%*9cdefijWUUWqWqqqpmhhk4:d,@..+*3afiqWWjgba;3-33cabf7kkhkfd=+.+&*=3ab7llmnqqWWWWopmh4ed00-*@...@#=>30abbf77h5imnqZqqqqifc9$&....+%#*==99afgqWUjib_09->$%&+.....%-cb4hh54fba9->3;afiqWqpfb0=@....&**3a|f44hkhfebbe7hk4feda-#....&>9afiqWUWWqjmgiipqWUWUWjgba*.....+&*=-9ab7hhm6m6lhkfdc9=*%.........+&*>9abfiqqUqifba;,$#@.........@&#=-;ab7ijWqjifbda;3=*%........@#>,cbijUWjgdc,*&..................@%*,9adbeijjgbc,$*@+..............@*,;bgpWWqibc9>#@..........+&%*>>,-=>,>==,-==>*#&+....................................",
|
||||||
|
"...&=3ae4kmqUTTTUTUUWZXXVl7ed,@..+*0d7pqUUql7:da'00db[kVVlVhkb,+.+%$,9_4hVXXZZWUUUUWnll41bac3=&..+@*>330d|e47kklVXoWWUUWWjga9=&.....+&#$>-cdfiqUUqpfdc3>$#%@.....@$3~ekVVVlke(c9399afpZWWpgea3%....@#>3ab44klV<k4e4klVlkke|a3#+..+#30b7pWUUUUWZm6hmoWUUUUWqmf0>.....+%*,9abeklVVVVVVVl4edc3=#+.........@*=cab4iqUTqpebac,*&+........+@#>>3a:7hnZWUom4e|d03,=#@.......&*=9abiZUUoibc9=#+..................@*=90d:7moomfdc3>*+.............+#*30dgjWUqjfa9=*@..........++&%#*$$$$*$***$>$#%&+.....................................",
|
||||||
|
"..@$;~FryAHDEEEEEEEEELCCCAsrF-&..&-(^sGvEELHxszr///rsAACCBCAxr'&.+*,!)/stHHHGEEEEEEEGHAAsrF)'-%...#>;~{F^zsxytCCCBGLELEELGsQ{;#......+#>9')FztLEELAK^{~;=$&+.....%,~FzABCCBAsr]{~)]^stEELvyzF'*...+&=-!]^sxACCBAxsxACCBtysr{!,@..@=!{^stEEEEEELGBBADEEEEEEGAK]-...+%$-;~{/rxACHHHCCBCCxs^]);-&........+#,-~]^sGuEEEGK^]~;,*+........@*,;')FztAGLEEvHssz/F{~!,#.......&=;~FKAuEELyK]~-=%..................+#-;(F^stGvAs^F{!-$@...........+#-;~{rxGEEvAKF!;>%............+&#%#**###*##*==*%+..........+++++&&&&%@+++&&&&%@+.......",
|
||||||
|
"..&$;)FzxtHvLEELLELLGGCCAAzF)-@..@>)/KyvvGHHHAssrzzsxCCGGCCCsF;@+@*-'(^sBBHHCvvvvLvLvGCAsz/]!-#..+%-;{FrzssyxABABCCvGLLLLvyr]'*......+%>-;_]IyLEEEts/]~-,#&+.....%-)FzyCCCBtsr/]{{F^JHLLLHxrF'*....@#=;)/zsACCCAyyABCCCysr/{!*@..@>;{/sAvLvuELLHBBCHLELLLvvxz]=+..@*>-!)]rzyCHCHCCCCCCBsz/{!-*.........&=;!{^KtLEELts/]~->%+.......+#=-;'{^sBCGDLDvAxszsr/])!$+......+*-~{ItLvEDAr]~;=*&..................&$;;{/ryBCBsz/]);-#...........+#-;)FKyvDEutz]~;,#...............+@@@+.+++@@@&&@.........+@&*#%##$$$**#%##$$$**####+...",
|
||||||
|
"..@%>-~1//IPKJ6KI5I5<Q[2F]_;-*+..+#-!|[IPJJJJJI[[/[^IPwwwOI[]_>..+&$-!)2IKJJKJKPQKPPOwJK[F|~;=%...%>;'F[Q/^/F/F^[QIIPJwNw8<1~-#.......@*=-;~:<OwNO<}_!->#&@......@=-~]QKzKrQ/F__~~(1[Pwww8Q|~-%.....@#=-!)]QPJJK^^QKJJK[])!->&...+#=-_:QPJJwwNwPIQIJwNwwJPP[{;%...@$=-;)(F[IJwJPIIIPJwKQ/|);-#.........&#=-;_:<ONNw52(!-=*@........+&#=-;'|QPwJJKPIQ2}/Q/}{~;%........&$-!1<wNNO<1~;,*%@...................@*=-!(2IKI[F|';,*&...........+&=-;_:<OwwO5}_;>%@......................................+@&%#$$$*=*$$$$>$==*>>$**%#@...",
|
||||||
|
"..@$=-!(:2QI5I<[[[222|(_;;-,*%+..+%=3'|[QI5OOJ5Q[[QQ<6YSN6<:_;%...&*-;_:QIII<Q[42}[56OO<[:1_;,&..+#-;(1Q<Q[2111|:122<6YSY84(!-&......+&%$=;_|<OSNO5|_;-**%@......@%-;(}QQQQ2}|((_((|}5YSY5}(;=@......@#=-;_}5O85[}[5OO5:~;,*&+...+@*-9(}IIPOYY6<[}[5YSOPPIQ}'-%...&*>-'(:}Q5OY8<[}Q6OOP<}2|'-$+........@%>-!_1<OYSO5:~;->*&.......+@%*,-!(:<OOO<<<[2}2[QQQ}_;=+......+&*-;(7OSS6<(_-=$#@...................+#$=-_1[[[21(_;,*&...........+%$=-0|78RSY5b!-=#@......................................+%##$*==,---,==,-,,--,,>$>*@...",
|
||||||
|
"..@*=9ab44hiVih777ffeda933**%&....&*=9affhimqomiiikhipqqqjgf09#...%$90bfhmmmi44feffipjjphg7ba;%...%3ab4immh7eeeeeeffgpZWWjgbc3&......+%*=3;dfijUUjifac9>*&@......+&=;dekhhk74febbbbfgiqqoifd;,@......+%$>-0fippmiiimjpgbc3>$&+...+%$-cdfhlmmoophf77ioqqmmk7ea>&...&=-cdfgiijqqpg7fgiqqpmigfbc,@........&*=9abfgqTUqifd0->$#+.......@*$90dbgiqqjmhh74f7hmlihfa,+......+#*30bgqWWjied0->*&+...................@*>-0b4474eeda-$%..........+@%>-9abgqWWqiba-$%+.....................................+@*=,339c0aac0c;9000c0cc99,>#...",
|
||||||
|
".+%>;a:khVmnonmlhkk4ed09,>$#&@....@$>9ade4lmXoZqoqoXVmppppi4b0*+.+#-0b4inooonmh74efhmonoXopifa>+.+=9bfmoqqjmkhkkkkklmoWUWniea3%.....+&*>30begjWTUWph4dc3>$&+.....+#=90eklllllhkkkhkhlmnnXifa9=%......+@*=3abhXnopqooXmkea9=#%+....%*30b7VlXonnmhk4kVnoonXXlfa3&..@#30bfijqqqqnmlkkhmnoooqqphea*.......&*=9ab4ijqTTUjgeb03,*%+.....+&$-a17hmjWWomVllhhlmoZom7b9%......@&$3cfiqUUqmh4{a3>*@...................@#=3~b4klllk7|a3#+.........@#=-0dekmqWUqpea9=#@......................................#,;ad(b1ee2ee:e:eeee4ee:bdc>@..",
|
||||||
|
".+*;)/stCCHvDvvCCCtxz/('--#%+.....&=3~{FrsxBHDEEEuvGCCCCCAAsrF=+.&>!]rsADEEEGHAtszsxAHGDLvvts/;@.@-]rJGuEEuGCCCBACACCDEEEDyKF'*.....%=-~{/zyBvuEEEvttzF{;-$&+....+*-~]rxACBCBCCCCBBBBHHHCtz]~,&......+&>;~FryCGLEuEDGBxrF_;=%....+*-!]ryCCGHGBBBxsxBHBGGHCts/!*..&,)/zxuuEEEvHBtAttBHHvEuEvAsF-.....+&=-;)/zxADEEEEGBxz/)'-$&.....%>;~/stBCvEEDHCCBCCHGLvDHxr{*.....+%=3'{ItEEEEGAtz/{!->&..................@*-'{/zxACCByz/),#........+$-!{/zytGLEEEwz:~;=&.....................................@-)FrzsyxAABtxtyxtyBtBBByxz/~#..",
|
||||||
|
"..#;)/sACCCvLLGBCABsz/);-$#.......&=;!(/rsyBCvLELLLvBGBCCCAyr{,@+&-!]rxHGLLLGCCAszzsBBHvLLLGxr;@.@-{rsGuEELGCCBCCCCCHLEELGtr]!*....+%,;)]^stCGEEEuvCxz/{!->*@....+$-']rsAACACCBBBCCCCCCCCyr]',&.......@$-!{ryABvEELvHAs^{~-=&....+%-~]ryCCBCBCBysytBCCCBCCBzF!#..#-)/sAvEEELGBBAyytBBCvLEuDAs/-+....@#=-~{/sACDuEuLvByz/{!->#@...+#>;)^sBCCHLLLBCCCCBHLELDvyr)=......&*-!{IAvELLGCAsrF);-*&..................%=;)FzyBCCCBs/);%........&$;)]/zyCGLLEDtzF~-=@.....................................#;(/zyyABABCCBBABBABBCCABysr)>..",
|
||||||
|
"..&=;_FrKJJwwwJKKr^}{';=$&+.......@&$-;)12KJwwOOJOwwwwwwJJI[]!*..+*-!{2IJwwwJKI/F|]}^IPJwwOP[|-+.+$;([6YNNwPKKIKrKIKKJwwOP[(!>&....+&*>;~{FQKJwNNSJKQ/(~;=*%+.....&*,;)]/^rKzKzKKrIKKKKKI^|'-%.........@*,;':QKOwSwOKQF'--*&@.....&=-;{/QKsKKKI/}FFQzKsKKK/F~>@..@=-_1<6SNNwJKI^//^IKJJwNwOI[)$.....+&*,;!)2^IJwNNwOKQF_~-=#@.....&*,;)FQKKwwwOPKKzIKKJwww6[|;&......@#$-;1<OwwwPKQF|);,=%@..................@%=-!)/IJwwKQ_;=&........&*,;)1}QKPwwwO<|!-=%+.....................................%-~)F//rrrrrrrrrrrrrrrzrr^/|;$..",
|
||||||
|
"..&=-':}QIKKJPI<QQ}|('-$&@+........@#>;_(}<6MMOPPJYwNSSYYO<}(-&..+%=;_1<P8OJPI[2((((:2QP8J8<}~,+..%-a128686PIQQQQQIIIK565[1!-#+.....+*=-!_1[<66OO85<2:(~->#&@.....@#=,;~(1[QIIIQQIQQQQ[[}|~-=%.........@&*,;(}[P8OO5[}_;=*%@......@#*-!|[QQIIQ[:((|}[QQIQQ2(;*+..&*3!12<OOOOPI[211}2QK8OO88[1'$......&$=-'(|[I56OM8P<[}(~;,*&.....@#$,;(2QQK6O8IQQQI<I66O6<1~>@......+%*>,_25OOPPQ[}('-,$%+..................+&#$-0|4OwY84_->&........@*>-'(1[QP68O6[d;,*&......................................&-!(1}[QQIIIQIQQQQIQIQQQQQ}:!*..",
|
||||||
|
"..&=9ab4hlllmVllhh41ac,$@+.........@#=3abfijWqqmmpZWUUWWWjied3&...&=cdb7kllmlhkfdaa_dbehhli7fd>+.+%>;dfg5i5hkllllhhhhh74fba9,#......+%>-0a:7hlm5mPlh7eda;,*%+.....+&*$,-c_e75hlhllhhh74ebd;=*&........+@&*>9ab4h5l5hfba9>#@.......+%*=cde47777ebdade777k77e0c*...+*3abfh5mmllh4:bb:7hlllmlh7ba*......@*,30be7kllmmmlk7fba;>*&.....@#*-cde47hlmllhlhlhlVllh7ba>........&*>9abhhmlhhkfba;=$#@..................+&%$=9dgpWWpga-*&........@*,90(e4hlVllhea3>*&+.....................................&3abe7h5lihl5ll5h5l5lk5khh4e0$..",
|
||||||
|
"..&=9d:kllVlVVVVVh7ed0,*&..........+%>c_bfhqWWoXXnZWWUWWWom7b3@...%>cde4hVlVVhked00c0b:7llkked,+.+%-9de7khllVllVlVVVlk4fbba9=&......@%$99dbklVVVVVVlk4ba9,$%+......+%*=-9abkhVVVlVlVhk4eba9,*@.........@%$=9abfkllh74|ac=*@.......@&*>9de4k7k4ebaaab47774eba3%+..+%3~bf4hVlVllkebbe4hVVVVVk7b0*......@#=;adekVVVVVVVlk4bac3*&.....@&$,0de7klVVVVVVVVVVVVVl7b0$+.......@*-9aehVVXVVkke(09=#@...................@%*>9agoqZjga9=&.......+%=,cd:4lVVVXVl7d0,$#+.....................................%9(eklVXXXXVVVVXVlVlVXVXVVl4d$..",
|
||||||
|
"..%,!]/zsAytyAAtAsz/]);=&..........@*-~{/rxtvvHABBHvLvLGvtJrF-&..+*-~]/rzyxtysz/])~){{^zsssz/{,+.@$9_{/rzssxxyAAtBBtysr^F{~;=#......@#>;'{/zsttBtAtxsrF{~;$%+.......&*--')FrsxAABBAAxsr/]);>#+.........@#>-;)F^zsssz^F)!-=%.......+&$;!{/rzzrr/]{)]F/rrrr^F);#...+*;(F^zsyAAtys^/F/rsxtAtysrF~=......@=-!{F^sxttAtAtyz^]{';=#+....@%=;'F/rsxAABABAABtAAAtyz/)=+.......&=-~FzxACCBCBxz/{~-=&...................@#=-!|IxvGxI{~,&.......@*-!{FzsACCCCBtsF);>*@.....................................*'/zxBCCHCBCBCCCCCCCCBCBCCBsF-..",
|
||||||
|
"..@$;')F/rrrrrrrr^F)~;-%+...........%,;~)FIzsssssxyAAByyyz/])-@..+&,;~){F/rrr/F)~;;;!){]F/F]{!=+..#-;~_{]/^rrrrrrrrrr^F{)!;,=&.......&$-;!)]/rrrrrrr/])!;=%+........+@*,-!)]/rrrrrrrr/F)~'-$@...........&#>;!){F/F/]{~!-*#@........@*,;'){]F]{)'!!!))){{)));,%+..@#-!))]//rrrr/]))){F/rrrr/])-@......+&>-!']/rrrrrrr/F))!;,$&+.....@&=-')]/^rrrrrrrrzrrrr^F);=........@%-;)^yABBBBtsrF{!,*@....................+*=;~F^rzrF);,&.......+%-;)F/sAAABAByr]!-=#@.....................................*'FrstAACCCCCCBCCCCACBCBCAtz{=+.",
|
||||||
|
"...@#=>-;;'''!'!;;;,=*#+.............@#=,-~(|(()()]]]F]:{)!-$%.....@#=>--;;';;--,>>>>=--;-;->*&...+%*,,--;;''!'~~~'!!;;-=**&+.........+%$=>-;;'''''!;-,##&+...........@&*=,-;;'!''''!;--==%+............+@&**>--;-;--==*++..........+&$=,---,-,>====->>->,=$%.....@#$>,-;;'';;;--->-;;;';!;-,%.........%*>=-;;'!~!'!;-->$*&+.........@#$--;;!!'~~~)~'~~'!;;-$&.........+*=-')]FF]]{)~;->%+......................@#==;!__';,=%.........+%*-;!)]F}F2]{~;=*@+......................................&=;~){]F}F2/2//[/[/[/2F2FF{)>@..",
|
||||||
|
"....@%***>>>,>>>=>$$#&+..............+@**=-;;!;;;;'~_'~!'c-=*&.....+@%**=>>=>=>*%&&%%$***=*=#&......&&*$===,=,,>=>,>==**#%+............+&#$*>>,,,>=>=*#%+...............&%%*>=,>,,>=>=*#&@+...............++&*#*$=***#%@.............+@%%***$%#**#&#%**##&%&+......+&%**$=====*=**$**>==,==$%@.........+&%$*$>,,>,=>=**#%@............+&%**=>,,=------==>=*#@...........@%>=--;;;;-,=**%+.......................+@#$=,-9->$&+..........@#*$,-;;;';;-,=*&+.......................................+#$>--;;!!!~~_~~_~_'__~!';;>#...",
|
||||||
|
".....+@##**$***$*#%@@+.................&**=,99->>-9;c9c33>>$%@.......+@%###$###%@..+@@%&%*##%+......++@%#**$***$***$*#&@@+..............+@&%**$**$*$$%@+.................@@&$*$$**$%%%&@+...................+@%&#**#&&@@...............@@&#&#&@+++..+@@+++..........+@&%#####&&&&@&&&##%#%%&+...........+@&%##$*$$*$$#&&@+..............+#**$*$*$*$******#&&+...........@&$*==,-,>>$*#%@+........................+&#$==>=#%@...........+@%#$*,,,-,,=$#&+........................................+%***=,,-33-339-9333,333-,>=#...",
|
||||||
|
".......+@&%&##%%%%&@...................@@%#**>**$*,>,,,>>=#&@.........@%%%&&%%&&+....@+@@@&&@.........+++@@&&%%&&@&@@@+.....................@&&##%&&&&@...................+++&&@&&@@@@+......................++@@@@@@@@..................++@+........++...............++..++++++.+.++.++.+...............++@&&@&@&&@&&@+.................+@&@%&&&%&&&%%&@@+.............+@%##*==*=*#%&+..........................@&%&###%&+..............+&&%*$=$**#%&@..........................................+@%***>$*=$========$=**=**%+...",
|
||||||
|
"..........+@&&@&&&@....................+.@%#&%%&%%#****%%#&+..........+&&%@&@@+@+....+....................++.++..............................+@&&&@@%&@.......................+++++.+.........................+.++.+..+.......................................................................................++@+@+.++....................++++++@@+++.+................@&%##%#*#%#&+++..........................+&&&&&@+..................++@%%*#%&@+.............................................+&%%**#*##%*%#*#*#**#*#%&....",
|
||||||
|
"..............+.....................................+..+..............+++++++..................................................................+..+++++.................................................................................................................................................................................................................+++.++++.................................+.+...........................+........................................................+....+.+.+...+..........",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
".................................................................................................................................................................................................................++++@+++.......................................................................................+...............................................................................................................................................................................................................",
|
||||||
|
".....................................................................++@%%&%@++..................................................................+@&&&&@@+....................................................+&%*#$#$*##&+.........................................++&&&&&@++..............................+&%%%&@+...........................+@&&@+.................+@&%&%&@+..........................++&%%%&%&&+............................................................................................................",
|
||||||
|
"..............+&&%&&@@.............................................@%#===>,>=*&@...............................................................+&*$=====*#%&@..............................................@&#*=,,3-3,3,,=*%@.....................................+&#*=,,3,=*#@+..........................+@#*===>=*%+......................+@#*=>=*##@+............@%#*=,3,=*#%@......................+@&*==,,3>==*%...........................................................................................................",
|
||||||
|
"...........+%$$,----=$&+..........................................%=-;;~){)));->%@...........................................................+%=,;;~){))!;->$&...........................................@%=-;')){{{]{{{)';,$@...................................+#--;!)){)~;;,*&+......................+@*>-;;'~~~;>$&+..................+&$-;!)))!;-,*&+........+%$,;!~){))!;-=&...................+@#--;)){{{{)~!-#@.........................................................................................................",
|
||||||
|
"...........%$--;!~'!-,*&+.........................................%>;~)]//^^])!->#@..........................................................%$-;!{F/^/F]);-=#..........................................+#=-!~{F//rrrr//F)~;=%...................................+#-!))F^/^F)!;-=%+.....................+*=;!){]FF])'-=%..................&$-;)]F//])!--=&+.......&*-;~{F^//F)!;-$%+................+&*--!)]^/r^^/F);-#&........................................................................................................",
|
||||||
|
"..........+%*--;!''!-,$#@.........................................&=;~(2[5<Q:_;-*#&+.........................................................%*,-~|[Q[}}{);>*@.........................................+@*=>;!(F}[QPPP<<Q1~->&...................................+%-;)|}<<<[('-,$%+.....................@#=-!~1[<Q}(;=*#+................@%*>;(4<<Q}('-=*&+.......@*>;~}[5QQ}(!->*&+................+&#=-;(1Q<I5K<[_;=*&........................................................................................................",
|
||||||
|
"..........@$=-!~(((_'-=#&.........................................%,;(}[8OO6<|~3>#&@........................................................+%=,c(4565Q[}(;-*%.........................................+%#$-;(}[QI8OOYYO67(;=@...................................+$-~1[58O652~;,=#&....................+&#>;~:[5Y65e;-$%@...............+@%$-!f58O6<:~;>$%@......+&$-c(<O8O5Q1(;=$%&+...............+@*-;~1<8OMYM651c,*&........................................................................................................",
|
||||||
|
".........+&>9;abe4fbd0-*#+........................................&>cb7ijqqjgfa;,$%&+.......................................................@#=3cbijomih4ea3*#........................................+&*==;ae4iimjqqoqqpgb9>&...................................@$9afgmqZoigbc->*%+....................&*=cdfipqqjga3>#@...............+%#$-agjqqjifdc,*&@.......@*-0fgjqjmi4ba->#%@...............+&=39abgjqqWWqjf09*%........................................................................................................",
|
||||||
|
".........&*,cdegmppi4b09=#@.....................+@@@+............+#30bflXnZnl4:ac,**&+...............................+.....................&*=,cabhmnXVVl4b03#+...................+++.................&%>9cd7hmnnonnnnnpiga3>#....................++@+...........&=9dekmnoXmkedc3>*%+...................#*9ab7lXoYmgdc=*@...............&%=,cd4mnZnl7:a9>$@......+%*30binnXXVk4ac,=#&@+..............@*,0ab7mnZWUWpgdc,#+......................+@++............................................................++...............",
|
||||||
|
".........*-']rsHDuEDxz/);=*@.............+&%%%*%$=*$#&+...........*;{/zxHHHHCxs/{~;->$%%@+..............+@&###*****$**$*%&@..............@%$,-')/KxACBCCCxr]'-&..........+%#*#***%#$*#@+............@#=-!{/ztGvELvGHHBBAsQ{'-*+.........+&%###**#*$*$$*##%%&+....#-)FrsCCGCHAyr]);--*%@+..............+@=-~FrxBCHBHs^{;,&.............&#=-;~]QyAHHBHxzF~-=%......+$,!(/sBHBHCAs/)';,=#$#%%@..........&$3'(/KxADLELDx[{;-&............+%###*#***$=$$****%%%@........+&###****#*#*#*##*&+..................+%##*$*=$#*%&+.........",
|
||||||
|
"........+#-!]rytDuEuAs/{;-=&...........&%#*=,--->----=#&@+.......+*;)/zyBBBCABsrF)';--,**%@+...........@%*==,----;-----,-=#%@..........@%#*,;;~]FryACCCCBAzF),&.......+&&#$>,-------->=#@..........@%*,;)]rxAGLELLHCAAysz/{;-#.......+&%##=>,-------------,*#@..+&-!FryACCBBBxs/{~!---=#&@+...........@#-;)FrtABCCAs/);-#+...........@%*,-!)FryCBCCAyzF);,%......+#-;)FzxBCCCByr]);;-->-,=*&.........@#-;)]rsAHLLLGyr]!-#+.........+%#$=,----;;----;----,*#&......+%#=>-,-,--------->=$%&@+..........@&%%$$----->--,,=#%&+......",
|
||||||
|
".........&*-!1[5wNNw52|!-*#@.........++&%*$>==,-=,,==$$$%@+.......@=;'][rKKKIr^}{~;-->,=*$%&..........+&*#=>=>,--;-----===*%@+.......+&%%*$=-;;~{][^IKKKK/]!-$+.....+@&###$=,>---->,>=**#+.........@%$=-;)][IJwNwwPI^^[F1);=*&......+@&#$$>>,>--;;----->==>$*@...@*-!(FIKzKKr^F|)';-,=*$#%@+..........@%*-;~]2rKKKIF(;,*&............@#$>-;~(][IKzKQF]~-=*&.......&*>-_]}^IKKK^F_;--,,=>>**&+.........+%$-;(1QPwNwO[_!-*@.........+&**=>==>-----;------,>$*@......@%#$=,,,,=>=>>>=>,,>**%&+........+@%%*#==>,,---,,,=$*%%@+.....",
|
||||||
|
"........+&*=3!b<6OY6<2('->%@.........+&%$>---;;;;;;;--=**%@.......&=-!_:QIIIQ[}:((~;;;->$*$#&+.......+&*$>>--;;;!!~~~;;;-,=*%@......+&%*$=--;;__(:}[QIIIQ[(!-#+.....@%#$*>---;;!!;;-;-,>*#@........@#=,-;_:[Q5OOO6<[}}1|(!-=*@.....+@%$**=,--;!!!~~!!;;;;--,$&...+#=;_|[QIIQQ[2:(_~!;--=$#%@..........&$>,;_|}[[IQ[:~-=*@...........@#*=-c!_(:}QIIQ[}(!->#@.......@#>,;(:}[[QQ[|~!;;;;;--,>*@..........&%=-;(}5MNR87_;=*&.........+*=,---;;;!'~!!!;!!!;;-,*#+.....@*=---;;3;-;;;;;;---=*$%&+.......+&#$$=,--;;'!;;;--,=$*%@.....",
|
||||||
|
".........&%$39afgipig7ea-*%@........+&#*=9;aaa|bbbdda0c,>#&+......&*,;de7hllhh74febb_aa;3==$%@.....+&#$==3;aa_bbbbbbbbdda0->*@.....+&#$=,-;adbbeef7khhllh7bc-%.....@%$*>,3;aadbbbbdda0;,=$*@......+%$,cadb47llmXmmhh74eeba9=#@.....@%*$>,3caddbbbbbbbbbddacc3#...+&*30b4hllhh744eebbda;3=$*&+........+&*=30db47hk74ba->*&+.........+&$>3cadbee7khh47fbd9=*@.......@&$=ca1e4kkh4bbda~dad0a03=&..........+&*>9cbiqWWjgdc,*&........@%>9;aadaddbbbbebbbbbbda;,=&....+#,30a~d_ddaaddbddda09==*%@......@%#*=,-;aa_dbbbbb~cc,>$%&.....",
|
||||||
|
".........@%*>90b7llVlh4bc3*@........@%>-cab1e444k774eeda3=*&......@*3cb4lVVVVlllkhkk74ed~093=%+....%*=,ca(be4444kkkkk7444bac,#+....%$,;'a(be47kkhhlllVVVVke_3*+...+%*,;'0_b4444k74k44:da03==%+....@*=cd1ekhVlXXnXXllhkk4ed;,*&....@%=99!ad1e4477kk7k7k7k74:d0$+...%>9_bklVlVllhkhkk74eba09,$@........&*>c0(e7kllll4edc,$%+.........@#>9a1e4[kkllhllkk4ba9=#+......@#*30b44kllVk4eee447ee:ba3$+..........&*,9afmqWWogbc9>%+.......&=9_be44747khhkkkk77474eda3$+...%=9_be47744e4474744e|dac3=*&....+%*,;'a_be4447kk74eedac3,#&....",
|
||||||
|
".........@*=-;~/KxtAABsr{!,%.......&*,;)/rsxAAHBHBBAAAs/{!--%+...+#-'{rxBCCBHHHHHHHBBAAyzr/{!,&...@$;!{/rsxyBCCBBBBCHAHAByzF)-%...&>;~FrzsAtCBHHBHHHHGBCCtzF'>+...&,;)/rzsxABCBCCBBBtxsr/]~;>&....%-']rsxACGHHvvvGHCCBBts^{;,*...+#-;{/rzsAACBCBBCCHACHABtyr];+..+$;)FzxCCCHHGHHHHABBAsz^F)!>&......&$-!{/rytCCHHHts^{;-*&........@#-;{^zxtACACHHHHHAAz/);>&......%=-;{^stACBCByxsyAACAysz/);%..........#=;~]KtEEELyI{!-$@......@=;{/zytBBCBHBCHBCBCCBAAAsr]!#..+>!]rsxABABtAyABABAAAxzrF]~-$+..+%-;)FrzsytBBBBBACCAysz/]);>&...",
|
||||||
|
".........+&*,-')]rzsyxs/);,#+......&=-~]zytBHGGLGLLLGLBs/)!-$&....&>!{^sACCHvvLLvGLLLLGCBts/);*...%-!)/sxBCHvHCCCBGvLLELuGs^{;*..+%-;]rytBCvGLLvLLLLLGHBCAzF),@..+$-!]rytBCvvHCBCBvDGCBAsr]~-*+..+*-!FzxCCHHLLLLLLGBCBCAxr{'-#+...*-~FzyABBvGCCCBHvLLvLLGHts/-@..+$;)FzyCCCGLLLGLGLLGHAyzrF);*......+=-'(/zxBCHvLLHxr{!-=@........+#-;]rxABCCCBGLvLvGHs/);>#......@*-;{rsyBCCCBBABCHLvHBAxr{;*.........+&>;~]IAvEuvyr]!-=&......@=']zyCHLLLLGLLGLvLLLLLGGBxr{>+.+='FzxCGLLGCBCCCCCCvHHAsr/]!>&..+*-!{rytBCGGHCBCCHGGCBtsr]'-#...",
|
||||||
|
"...........+%*=-;'~{]F]);=#@.......@*>-~FQKKJwwNwNwNwwOQ|!->*&....@$=;)/IKKJwNwNNNwNNwwJKK/F!-%..+%=-~F^KKJwwwJJKJwwNwNNw8<|~-&...&=-)F^KKJwNwNwNwNNNwJJKIF'-*...+%=;)2^IKJwwwJsKJwwwJJz/}';,%....&=-~F^IKJwwNuNwwJJzKzr/|;-*&....%>;(/IKKwwwwJzJJwNwNNNwJK[)-+...%>;_]QKJJwwNNNNwNNwwPI}F(;,#.......%>-;)]/IKwONNOI|;-*%+.........@$-;{/rIzKJJwwNNwwOQ1;,*&.......&$,;)F/^IzJKrQ/PJwwJPr2{!=#..........@#>-':5wNwOQ|'-$#+......+#-)FQJwNwNNNNNNwNNwNwNwwPIF~$..+*;)2IJwNNwJsKsKsPwwwJK^}]~-=@..+%=;)FQrPJwwwJsKJwwwJKKr1);,%...",
|
||||||
|
"............+@**>--'_(_;,*&+.......@#*-~1[QPJwwwNNNNNRO41';-*@....@%>-~:[QI6ONNNwNNwNNYPK<[1~-%...#=;_1[<IJYSYPIKKONNNNNRM7b;>%...#,9_1[QPPwNNNNNNNNSOJPP[|!-%+...#=;_1QIPJYSO8PKPOSOOII[:_;,#+...@*='(}QIJwNNNNNROKIQQ[}(;=#@...+#-;(}[IKJYwJPKP8RNNNNNw8Q}_=+...&>-'_}QIJONNNwNwNNNR6Q[1(!,%.......&#--~(}QI8SNNR<1;,*&..........@*=;(}2QQIKJwwwNNSO7_->*@......+@*=;_(:}Q<K<Q[[<ORR8<[}(;=@..........+%$,c_<OSR64_;=*@+......+#-'|[5ONNNNNNwNNNNNNNNwOPQ}~*+..&-!|[PONNSOKPIPIIPYMO<[}|~-*@...#,;_:QIPOwSOPIIPOSYJPIQ2_;=%...",
|
||||||
|
"..............@#*>=3c_a9>$&........&*=9de4hinqZWZZZWZqogeac9>&....@#=3a:7lVmoWUWWqZWqqommlhfd3%...%,;dfhlmXqqqmlhmpqUTTTTjgb0>&...%,;bfkimpqWZqZoWWUWjXmk7bc-#...+#-cbfkmmooWqpmlmoqopmlh7d;,%....@*=;de7hpoWWUUUqpi<77e1a9=%@...@*-ab7himqqqqphmpqUUTUWqphf0=....@*30d4hlmnqWWWZWqWWqmh7f:a3#.......&*,30df7ipWTUqgbc9$%+.........@$=9d1447hlmoZqZWWjgd3>*&......+@#=3ab:4hiVihhiijqqp77bd9>&..........+&*,cbgqWqjgd;,*&........%>cb4mnqWUUUUUUWWUUUUUZjmgea>..+%-0b7pqWUWqnmmmlmmoqoi47eb0,@...%>9bfkimpoqpmhlmpqopmlh4dc,#...",
|
||||||
|
"..............+@#*>999;3=%@........@$3'dekklXnooZooZZWqm7edc3#+...@*>c04hVXnnqZooppnXooonomhea>+.+$9aehmnonZopmhhhmnqTTTTqiea9#..+$9dfhXnonoononnooZooXVVhe_3*+...$9dflpnonooXXmlVXnoooonkfd9*+...@#>cabfklnooZWqqmhk4eeda3>*+...%,cb7innooooXmllmoZZZZZnmked>+...%=3a1kVlXnXZononnnooXVlh4:c$+......@*=9cd:7kjqUTUifa3=%+.........+&>30dbe4khlpnooZWqib0,*&+.....+&*>0_e7klnooXpnjqoolkeba3=&..........@$>9afiqUWqgb03=%.......+#3ab7lnZZZZZZZZZZZZZZZoXVVkb,+.+#,ab7loZZZonXmmllmnnnVVkked,#..+$cdeiXXonZoXlhklXnoonomifdc=+..",
|
||||||
|
"...............+%#>---;-=*@........%,!]/zxtBCCCCCHCDLLvAysrF',&..+&>;)/sAHHvGvCHAyyAHBHGLDDtsF;+.+-{^sGDDLvGHBtxxsAAvLuuuuxKF;$..+-(rsGvLLvHHAtxtCCvCHHCBAzF'=+..+-]rxGvEEDGHHAAABCBHGvDDGxr]-+...%*,;)FrsxHHGGvGCAssr/F{~;-$+...$~FztHDvDvHHtysAAHHGGGHCAs^(-@..+*-~]zABCBCCBHBAtAHBHHBCCxzF-+......@=-;~{/zsGEuEuwz{'-=&.........+%=-'){F^rzsytBCvLvtI]'-*+.....&*-;{^sxBGvLLEvLDvHAys^]);>&..........@$;)FztEEEvxI{'-*.......&=;{FzxCHBGHGHHvCHCGvGGHHBCyr;@.+=!{/ztHHHGBHCCtxtAHHCHCBAs^)$..@-{rsHDEDGCHBxysAACCGvLDHyr];#..",
|
||||||
|
".................@%#$**%#@+.......+#-;]^zsyBCCCCCCCCLLLHxszF)-%...#>;)/stCBCCCCtssssxACLLELGs^-@.+-(/sHLLLvCttzzzzsytGEuEGy/{!*+.@-]rxHLELvBBysssxACCCBCCtzF)-@..&-{IyGLLLLHCBBABCCCCLLEuGyr{-@...@*,;~{/rsACBCCCCyz/F])!;-$@...+$'FzAvLLLGCtyszsyACCGCCCxzF),+...%;)]zyCCCCCCBxssyxBBCCCCAz]-@......+%$-;){^sAvEDvtr]~-=&..........+%>-;!){F/rzsytGLLyz])-#@.....+$-!)^zyBHLLEEEELGAAsr/{!-$@..........&=-~}KAvEEvyr]'-#+......+=;~{rtABCCBCCCCBCCCCCBCCCCt^;@.+=;)]rtACBCCCBAysstABBCCCBy/)=+.@-]rxGLELvBAxszzsytCvEDLGyrF~*..",
|
||||||
|
"...................+@.+............@=-'{F^/KKJJJsKJJwwRPQ2]_-=@...@$>;~/IKKKKrI/2]1F2[IOwww6}(-...$'([6wNwJQ}F{)_){:}QP65<2_;=@..+=!([6wNwJQ[2]1]2^rKKKKKQF)-*...@>'1<8NNNwwJJPJKJOJwwNNR8[|'=.....@%*-;!1F^IrKzKI/:);;,=*%&.....#-_:<JwwwJKQ/}]}/IKJJJKK/|!-#...+@*-']QKJJJKI^2:]:/^QrKKzI]~$........+%*>-;(:5ONwO5|!->*+...........@&##=>--'_(]2[POO<1!->%.......@=-;)F[IJwNNNNNw8Q}|_;;,*%............%>-~:5wNwO<('-=@........&=-'(2IJJsKKKKKKzKKzKKzIKrQ],+..%=-'(/IKsKKrI/F]}F^IrKKKr[);%..+=;1[6wNwPI2]]|{]2}Q8www6Q|~-%..",
|
||||||
|
"...................................&$,;(2QIKPOOP6IKPYSM5[:_!-*@...@%=-~1[IIQQ[21((((|:48RSO5:'=+.+*9_15YNR841_~;;-;~_|1}}1_;,*&...*c(}POSY541(__(_:[[IIIQ[|!3*+..+=;(g8NSNNMYYRRRSSSSNNNR64(;*+.....@#*=;~1}QQQQQ[1_;-=*%@+......%-;(78SNY8<[}1|1}QIIKIIQ2(;,%....%$>;(1QIK<Q2:(_((1:}QIIQ[1;$+........+%*-9'b[OSSO<1;-*%@..............&&#*=,;'_125O8<|;,*&.......&$=;_(}[PMNSNNNR5[|_!-=*#@...........+&=-c|<ONR64(;,*%........&$-;_:QKPKQ[[QQIIIQQQ[QQQQ2)>..+&*-;(:QIIIQ[}1_(((:2[III[:~-%..+*0d}6YSY52((~~~~_1[5RSY84(;-&..",
|
||||||
|
"..................................+&*-0b4hlmoWWqnmmpqWqigfba3$@...@#=-ab7hlhg4fbbaaddbgpqWqie0>..+$9depqWqpfbaac93990dbbbd0c,*@..+$cdfpqWqpfbbdaddb47hllh7ba,#...+=cbgjTTTTUUUUTTTTUUTTTTjgbc=......@%$>9a174hhkk4ba;,$#&+.......@=;dgpqWqnih4fffghmpmmlhfd;=#....&$,;d4hlli4febaadbe4hhlh7b0*.........@%*=3;bgjWWqgb0-=%@...............+@%#*,;0bfpqjgd9,*&......+@*=30bf7pqTTTTTqigba0-$#&@...........&*>90bgqUWjgdc>*&+.......@$=;0ehlmhhk7khhhhhhhh7hhhfd>...&*,;0e7hlhh4:bdadb:47hhlhea3%..+*cdgiqWqifbaacccadfiqWqpfbc,&..",
|
||||||
|
"..................................+#=9~ehVXXZWWZonnoWUWph7:dc=&...%*30d4lVVXVk7e:bbb|fhpWWZpgd,+.+=0b7pWUWogeba09-3cadb:bbac3$&..+=abgjZWZpkebdbb:4klVXXlhe_9*+..@,0fgqTTTTUUTUTTTTTTTTTTqgb0=+.....@%*,cdekllVllked9,=$%@.......&>3a7poqZonpmmimmnZZnnXVkb03%....&=3aekVVlVk4e|bbbe4klVVlh4a>@........+#$39abioWUqpfdc,*&+...............@&$>,cab7pZqib09$&+.....@#$3'be7hnWTTTTUWp74b_93=%@..........+&*,9afiqWWoieac>*@.......&*,cd4hVlVlllllVVVVhllllllkb,+..@*3ab4lVVVhk4ebdb:fkkVVVl7b9*..+=0bhnWWWphbbda_ade4pZWWpiba3#..",
|
||||||
|
"..................................%-;)^stHvvDvDvBCHvLEEGBxz^{;%...*-~]rsAHHGHCAyzrrrssHGEELGs/;+.@,]QsHvELGtsr/])!~){/rzrrF)!-%..@-FryGEEEGAszrrrsxtACHGHts/)=+..@-2IwuEEEEEELELEEEEEEEEuuJr:-@.....%=-;(^sACBCBCts^{'-->#@......#9~FrAHHHGDDuvDEDEDDGGGHyr{!>+..+*-']zxCCCCAtsz^/rzstACCCts/;#........@=-!(/zyEEEDtK^]~;=#+.............+&*=;!{/rsHDvtKF'3$@.....&*-;{^stAGLEEEEEEGAtz/{!;=%+........+#>-'{[stEEEvxK/{;-=&.....+%-;{/sACCCCCCBBCBCCCBCCBCCtr;@.+#-)FrxACCBBBxzr^rzxABCCBCyr(>..@-FIxvLELHysr^^/^rzxGLEEGyKF'$..",
|
||||||
|
".................................+%-~]rxHvLLvGHCCCCHLELGCys/);*+.+#;)FrsACBCBCBxsrrzsxCvELuGs/;@.@-{rJGLELLAyz^])~))F/rzzrF{~;*..&-{IsHLuLvAyszzzsyBCCBHCAsF)-@..@;]rxuEEELvvBHCHCGGvLDvGts/(-@....+%>-!)/sAABCBCAs/])!-=*%&.....%,;{^sABCGvLLDuvELLvvHCBtr]'=+..+*;)FzyCCBCByzrr^/zsACBCBBs/~*.......@#=;~{/KtGDEEAs/]~;-=*+...........@&*=-;){/zJtGDyr]~-*&.....&=-'{rstCBGvLLvvvvGCxrF)'-$@.......@&$-;~]^JALEuvAzF{!;,*&.....*-;)^sBCBCCAACCCCCCACBCCACxz;@.+#;)FryBCCCCtysrr/zttBCCCBtr{=+.+-{ryGLEEvAxzr^^rzyAvLLLGxr]'*..",
|
||||||
|
".................................+&=-~1QJwwwJI[^[/QIJOwPQ[F_!,&...&=;'{/QKKKKzK^FF]2^IPwwNwP}(>+.+$;([PMNNOIQ}|)';'!)1F2]]_~;=&..+>;1[8wNNOII/2FFFrKzKKKKQF_;*+..+>~:QJwNNwJKKIIIQIQIIIIKQ:);*......@*=-!)FIrKKKrIF|~;->$$&@.....+#=-'{F}QI8886O8JOOJJKKK^]!-%...+%=-~]/KKKrQ/F1){(F/QrKKKr[);%......+&**,;!(2<YNww52(~;-=*#@..........+@%#$=-;~(:Q8OO<|!-=&+.....@#=-;)F^IKJJJKKPJJwJI}(!-,*@.......&#*>-;'_2PwNNO<}_!-,=*@.....&=-;_/KKJKKrrIzKKzKzIrKzKK/F,+.+&,;)][rKJKK^2F(((]F^IKzKK^]'*..+=;1[8wNNOPQ/](||}[POwNwJQ|',&..",
|
||||||
|
"..................................&$-;148wSO54}::1}[6OO<[}|(;-%...%=-'_:[IIPI<Q[:||:}Q<OYYY5:;=..+#;_:5OSYO<[}|_~~~__(1111(~;,%..+*c_}5YNR8<[:||(}2<IPIIQ[|_;*...+*9_f8RNSO5I[[[}[}[[QQQ[}('-*+....+&*>-;(:[QQQQQ[2(~;--=*#&......@%>,3!(|2[[<[[[[<<IIIIQ}~;=#+..+#=;~(2QIIQ[2|(__(_:2QIKI2:(-#......&#$>-;'~1<YSSO<:(~;->$#@.........@%$$$=>-;~(1[6M67|;-*@......&*$,;(1}[QIPPI<IPOY8<}(_;-=@.......@#>>-;_(:<MNS8[|(~;->$#+....%==;_}[IPP<Q[QQQQQQQQQQQQQ[_>+..&*-;(1QIPP<[2()_((}}[QIIQ2|;$+..$;_28YNYO<[}:1(1:[QORSM52(;$+..",
|
||||||
|
"..................................&*9cbgpWWqpgf7ffggjqqphffbc,%...%=-0dfhmmpXmihffffghmoqWqib0$...%,abiqZqnmh7ffbbbbff7f7fbba-@...*9afiqqWjikffff7hmmnmmi4fdc>+..+$3afpqWqqmihg77g7ghhilhfbc,#.....&*=,;abf7hhlikh7bbdc09,*#+.....+&*=-30dbffff7777hhhlhhedc=&....#>;db7ilihgffb(dbef7hiVihfd9*....+@**,-0adbggqTTqigbbaa;3$&........+%**,,9;cadbfgmjjgd;,$&......@*=9abf7hhlmikhhmoWqigfbd09%......@%*-;cabffiqTUqifb_ac9>*@....&=-0dfhlmmlh4hhhhhhhhh4hhhhb,+..%=;abehmmmi47bbddbf7hilik7ba=...%3afiqqqjmg4feff7gipWqqpfd9$+..",
|
||||||
|
"..................................&=3aegoWUWommimmmoqWWopmi7d;%...%,0b4hmnoZZooppmimmpooZqjif0$+.+#3aeiXoZoXmmiiiiiiiiimmhkeb9#..+%;aeinZoonmmmiimpoZooonmked,+..+%9afioZZooonpppmXmmXnnmhea9*+...@*=9_beklmjononpmih74eda3*&+.....@#$,c0de4k<khkhlllVVVl7d;,#...+$9de7mooonpmh7ee4glpnoonmhea$....@**3c(e4ggpqqTTUjmi44:ba9$@......@%=-0!d(be44kklnnngb0,*&......%=9ab7immXlVllllmoWUjmii7ed>+....@&=3_be7gijqWTTqjih74eda,#+...%,0d4hmoonmVlllVlnnnnVVVnpm49+.+#,ab4hmnonnmiheee7lmXooonh4b,@.+#3afmnZZonXmliiimXXoqZqifac*+..",
|
||||||
|
"..................................&,']ryDuEEuvLDuvvuEEEEDDHxI(>+.+$!]zABDDEEEuLEuvuDEvDGGGAs[)=..+>;{/yBHHvLvLDDGLvGLDLDGGByr{=..@=~{rsCHHGLLuvvvDDEEEvEEvAs^'&..@>!{rxHHDvvEEDuDuDDDDDvDAsF'=+..+%-!]rxAHGLEuEuEDDDGHtAs^);$@.....&=-'{/rsxtCACCCCCCCCBBs^);$+..@-)^xtvuLuEuvGxssxtDvEEuEvty/;+...%,;)^stBHGuuuEuEuuDHAAxr{-#.....+$-']/rzsyxBBBACHHCs/);-#+....+$;'FsADLDGHCAtxtAEuEEEGGtxz~%...+#-;{rytBvuuuuEuEuEvABts/)-%..+=;FrtHvEELvHCCCCCGvuvGHHvDDJ(@.@>'/ztHDuEEvDGtssstvDuEuEEGtz~@.+>!{rxBHBGLvuvvvDvuDvHGHtr1~,@..",
|
||||||
|
"..................................@>;{^sGvuEuDuLDuLLEEuLGuDyr{-..+>;FrxHGLLELuDDLDDLLLGHCByzF'$+.+*;)FzyACHvLLLLvuDLGuDuDvtxr{>+.+$;)FsxBCGGDLLuLuLLLLLuuvBxr;&..+*;)/sxACHvDvLDLvuLuDDDutzF'>@...*-~]zyBBHvLLEEuuuDGCCAyr);-%.....%=-~]/zsBBBCCBBCCCBCBxzF';*+..+>)rsAGuEuvuDGyssyAvDLvuuDHxr-+..+#>;)^xBBHvEuEEuEEDGHCAyz]!$+....&$;)FrsxAABCBCCCBCts/);>#+....@$;~}zwvGvHCBAtssxvEuuvuDGAz]$...@$-']zxBAGvEEuuEEuvvHCAyr)-*..+$~FzAAGLLLGCBCCCBGvvvHCHvvvx)&.+>)/sAHGDLuuLLAxsxAGvvuEuLHAr~&.@*;)/ztACHGLLLuLuDLvvCCxs/);$@..",
|
||||||
|
"...................................%=-!|[5P666J68O666JO86P<4(;%...#,!1}<588O666686668PIQ[2]_;=&...&*-;):/[<56P8P6K8668P8P<[:~-%...&$-;)]}[I6686JO8O8O6O6P<Q:)=+...&=-;(F}[IP8666OJ6666PP<4|;-%....&=-!{F[IIP6O6OJOPPPIQ/F)-=&+.....&>,;~|/^rKzKzKzKKKr^/F);,=@...+*-(:Q<6O6J65<[::2Q566J665Q})>....@$>;)F[[IP6OOY6O66PII/F(;=%.....&*>;_F///rIzKKKKIQ[|!,$#@......&>-'1QP6PII^/F::4<668OPPI[];&....&$-!{F[Q<66OYY6OO8PIQ/]);#@..+%>!12<6686IIQ^QQQIPPPQQIPP<4;+..%-'][QP66J6PP[}:2[<PJ6J66<[1-+.+%$-;(F2[<P68686888PI[[F);-$@...",
|
||||||
|
"...................................@*=-0(:}}[4[[[[[[4}[[2}1_;=#...%*-;(12}[[[[2[[[[[[}21(_;-=#+...@%$>-;'_1:2}}}[[[[}[}2:1(;-=@...+&*,-'_(|22[[4[[[[[[4[[:(';*+...@#*--;_(|}}[[[4[[[}}111_;,*&+...@#=-!(|:}42[<[[[[[}:1(~;,*&.....@#=-;_1}QQQII<KIIIQ}|_!-=*&@...+%-;_(}[[[[[}1(__~|[[[4[[:|_9%+...@&*=;~_|:e}477[7[[4:1|_!-$&....+&#>;(1[[QIIIIIIQ[:(!-=%@.......&*>-!b}2}21(__~__:2}}[4[:_!>@....@**-;_(|}}}}727[4[21|(~;=#+...@$-!(:2[[[2:11|1}}4}}2::}}}_,@..&=-!(:}[[[[4}:___|2[4[[[}:(;=...@#*,-;__|:}[}[[[[}e1(_;9-*#@...",
|
||||||
|
"...................................+%*,300dbbbbfbfbbbbbfbba0,*&...&*,90abbbbbfbbebbbbbda9c-=*&....+&*=,,390dbbbbbbbfbbbdda;-=*+...+&*>=390abbbbfbfbbbbebbba9-#.....&#>,33cadbbbfbfbbbddaac3=#@....@%>-9addbbfbffffbfbbda;9=&+.....@#=3ade45llhllmmlh7edcc,$*@.....&=3cabbffbbbd000adbbfbbbbd0-&....@#$$3c0adbbb1fbfbebbda09=*@.....@*>cdf7hhhhllllk4ba;>$&+.......@%$-;abbbbdaaa9c0abbbfbbba;*.....+#$,30addbbbbfbebbbbdac3$%....@*,cadbbfbbb(b(dbbebbbbbbbba=..+@*,c0dbbbffbbd000abbbfbbbda9#....&#$,-3cadbbbbbbbbba0;3=>#&....",
|
||||||
|
"....................................&#*,ca_dbbbb:bebfb:bbba9-=&...@$>3;adb1bb(bb|b:bbdac9,=$*@.....+&#*,-9c0bbebe:b1bbdacc3,=%+....+%**>-cadbbb:bbb:b|b:bdac3#+....@##$,,30ad:b:bbebbdaac3,$#@....@%*>c0ab1b:eeeef1bbaa09,*%......@*>c_b4kVVllXXXXml4ed09>*%+.....%*,cadbeef1ba'9c0ab|be:bda0>&....@&%>,9caab1bbb:b:bbdac;3=%+.....&*=0b4<lVVXVVVVh4|a9,*%........+%*=3ddbbd_a0c;99abbb::bda9*+.....&*>3;0adbb:b:bbebbaa0;,=&...+&*>-cab1be1dbddddbb:bdddb:dc$+..@*=30adb:bb:ba0330db:b1bd_0,%....@%*$=399abbfbbb1b003,=>*%+....",
|
||||||
|
"....................................&$=3;_(]//[//[///[///F{~-$@...@$-;~(]2/2F]F}////2]_';3,*%+.....+&#$>-;!)]2//}^//2F:{_';->%......&#*--;)]/[////[//}///](';=@....+&#$33;~(]/}////2F1_~';-=#+....@#,-'))F2/^/rzr^^/F{)~!;-%+....+&=-)F^sxBCCCABCBAAsr]~;-*#@.....%-3!){F/^^/](~';~{F//}//F)!,&....+%#-;'~){F2^/[F[//F{)~!;-#+....+#-;)/sxAABCCBABxzF)!-*&........@%*-!{F/F])_!;;;'_]/^^^F]);*......@*>-!~)]F[/[/////F{)!';>%...+%=-;~(F^^^/F]]]]]F//F{{{]F:)=...@#>;~{F}//[FF{)'~)F}/[FF()~;#.....&#>--;_)]F[//[/]{';;-$#&+....",
|
||||||
|
".....................................&$=-;!))))_){{{{{()))!;=%+...+&*,;!))))))){)()))~;--,#&..........@*>>;;~))){){){))!;;-=%+.......+&*$-;))))_({))){){)~!;-$@.....++%*>,;!)){({){))~;;--$&+......@#--;!))|)]]{F]]{)~;;-$%%+.....&*,;)]/zsysxysyssr/]);,*&+......+#,-!))(]{)~!;;;;!_{){)));;*+......@%=-;!~){){{{_{))~';->#@......%$-~]^zzsyyxyyzrF{~-=#+.........@*>-~)))~!;----;'~)(]){);,%.......@#>,;!~)){){({)))!;;,$%+....&#=-;~){{)))~'~!))())'!!)))-#+...@*-;!))){)_)!;;;!)_))))~;;$@......+&%$,-!))_){)~);-=#*%@......",
|
||||||
|
"......................................+@@&#==-,->-=,>--===##@.......+@#*==,==>=>->>==>*%&&+.............@&#$$>>>>=>>>$**%&&+...........@@@&$=,,>=>,>=>====#&@+.........++@%#$=>=>$>$$$%%%&@+........+%***>>->--,-,->>=##&++........@#=>-;~)))))))));;,=*&+..........&#$=,,>>==>****==>=>==>*%+........+@@##==>==-,>>>===#&+........+&*=--'~))))))';-,=*&@...........+%*====>*$$*#**>=>,->$*%%+.........&#*==>>->-,-=>>=**%+......+@@#*==->->=>====>>>,===$**&......+&**=>>,,,==****>>->===##@...........@##=,-$=$**%@@..........",
|
||||||
|
"........................................++@@@@&@&&%@%&&%@@@+..........++@&@&&&&&&%&&@@+....................+@&%&&&%&@++...................++&@%%%%%%&&&@&@@+..............+@@@&&&%&@+.+.............+++&&&%&&&&%%%&&%&@+.............@%%%**$====>=**%%&@.............+@&&&%&&@@@@@&&&%&@&@@+............+.+@@&&&@&%&@&@@@............@&&%%##$$***$#%&&@..............++@&%&@@@+@@@&&##%%%@++............+&&&#%%##*%#&&@&+..........+.@&%&*#%%%%%&&&&@&%%@@+++.......++@&%%&%@&@@@&&@&@&&&@@+..............@@@@%@+++.............",
|
||||||
|
"..............................................+...+..........................+........................................................................+...........................+........................+++...++...................++..++++++++++......................+....................................+...+...................++++..+++.+++.............................+@@@@@++.................+..+@&@&&@@@.+..............+++@&&@@+@++.+...+....................................................+...................",
|
||||||
|
".....................................................................................................................................................................................................................................................................................................................................................................................++............................+............................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
".................................................................................................................................................................................................................................................................................................................................................................................+@@++..........................................................................................................................................",
|
||||||
|
".............................................................................................................................................................................................................................................................................................................................................................................+@&#*$==#&@.....................+%#***%@...................+@#***##@+..............................................................................",
|
||||||
|
"............................................................................................................................................................................................................................................................................................................................................................................@%%*$3c99>=*&+.................+&#=3999=*&.................@%#=9c;,=#%@@............................................................................",
|
||||||
|
"........................................................................................................................................+@@&%#&@+..........................................................................................................................................................................................................................&**>,30dda9>=*%+...............@%#,;addac,*%...............&*=>3cdd093=>*%+..........................................................................",
|
||||||
|
"......................................................................................................................................+%*=>----=#%&@.....................................................................................................................................................................................................................+%>-!~)]Frr/)';,#&..............+#-;)]/rr/{!-=@.............@*-;')Frr/])~;->%@.........................................................................",
|
||||||
|
".....................................................................................................................................@&*>-;;!'!--$*%&....................................................................................................................................................................................................................%>-!)]F/rzr/)!--*@.............+%$-!]rzssr]~;-#.............@*--!)/zsz/F])!--#@........................................................................",
|
||||||
|
".....................................................................................................................................@%$,-;;'~'-,$%&@...................................................................................................................................................................................................................@#=,;~|F}}/}(;-=*&...............&*>-_2IPIQ|;-*%..............&*>,;)F2/}F|);,*#@........................................................................",
|
||||||
|
"....................................................................................................................................+&$=-;!~(1(!-*$%@...................................................................................................................................................................................................................@#*,'(}[[[}:~;=#&+...............&*=9_48OO5:!,=%+.............+#*=-_|[[[[}1~->#&........................................................................",
|
||||||
|
"..........++@++................................+@++@@@++@++..............++++...................................++++...............+@#>-ca(beeea;,$*#&++................++..............................................................................................+@@+++.....+@@++..................................................+@+++@@++++++++...............%$>;dfhhhhfea9>$&+...............@$>9dgqqqjea-=%+..............&$=3abfhkihed;=*%+.......................................................................",
|
||||||
|
"......+@&#***######*##&&@+...............+&&%###********%##&+..........@&%*#&##%*#%#%%%&&@+................+@&&##*##%#&&&@+........+%*30d:44kkkedcc,=*#&@............+@%%#%@+.....+@&%%@+............+@%#%#%%%%&&%&&%##*%#%%@........@@&%%%#&&@++...+@&%%%%@.........+@%#%**#&&&&&%#%**#&+..........+@&%%%&&&@++..+&%%%%%%&+...........+@&#%************%@+............+&=3abhmonV7:d;=*&+..............+%*,0biqWWqgdc>*&.............@%#>3d:7innXifa9>*@.......................................................................",
|
||||||
|
"...+%%=----;-;;;;;-;-;->$#%&@+........+%##=---;-;;-;-;---,,$#+.......@%*=,-;------;-;-;--$*@+............@%$=,--;-;;-;--->$%@......&$-~]rzytBBBsr/{)!;-=$%+.......+%*=>----$##%%##$----,=*%%@.....+&%$>-;>-;---->--,--;;--;->&.....@%$=,--;-->=*=###$-------*@.....&*$$--;----,->---;--;-$*@+....+%%$>------==#$#$$>-------$%+.......@&#>---;-;;;;;;-;--->*&+.........+%$;'FstEvvHs^]);>%..............+&=-'1KtEEEDxI{!-%.............&*=;!{^stDDDGs/)3,%.......................................................................",
|
||||||
|
"...@#,-;!!~~~'))''~!!!!--,>*#@.......@#*=-;;!!!~'~~~~'~'!;;->%.....+%$>--;''!!!!!!!!!!!!;-,=%+.........@%*>,-;;''~!!!!!;;;--=&.....#,;)FzsyBBCAyz/F{)!;-,=#%+....@*--;;;;;;-->,>$---;;;;--,*#&....@#=-;;!~'!~!!;;;;;!!!!~!!;-=@...&$>--;!!!!;--->----;;!!!;;,#+...&$>-;;''~'';;;;;;'!~';;-==#+...@$,-;!!!!;;---=-,-;;!!!;;--=&......@#>--;'''~'~))~~~''!;--=#@.........%,-~FJAvuvHs/{';=&..............+*=-!{IAGELGyr]!-#+............+&=-')FJALLLGs/);=#.......................................................................",
|
||||||
|
"..+%*=-;'!!~~~'~'~~'';;--=$$%@......+&*$>>-;;'!!'~!!~~~'!';-,#.....+%*,-;;;;;;;;;;!''';;--=*%+.........@#$>,-;!!!~!';';;;--=*&....+%*,;)F/QrKzK^/:{)~!;-=$*%@....@*=,-;;;;-->==>*>--;;;;-=>$%@....@#*,;;!'!!'';;--;;!!'!'!!;-$@...@*>,--!'';;-->==>>--;!!!;;-*@...&*=,-;!!!!;;---;!''!!!;-=$#@...&*=,-;';!;-->===>,-;!!!!;--=&......&#=,-;;!!~~~)_~'~!;;;-,>*@.........@*,-~[6www5}_;-=%+..............+&#>-'15wNwO<('-=&..............+&*,;!2IOwwO[_;>*@.......................................................................",
|
||||||
|
"..+%=-;_(1111|({:1:1(((';--=*%+.....&$*,-;;~((1::111({:1{|(!;*@...+#*>-;~_)|{1)__)(||(((~;->#@.........&*=--!~(1{::|)((__~;->%+...@%>-c|}<<I5P5<[4}e:1_;-,*%@....&*-;0~||b~;-,>=--c_|)(~!;,*#@....&*>;!(b|{b1||_!!!_b{1b1{1_'-#..+&*,;;_(b||(~;;---;;~(1b1)~;-&..+&=-!~(b:1b1)~!!_)|b:1b|~;=#@..+%,;;~1b11(_;-->,-;~({11b(!;,#.....@%*>-!~((1:1e1e:11{1(~!;=*@.........&*,3ae5MSY5:~-=#&...............+@#*-;(<OMR64~-=*&...............+#*,'b5YSR8f_3=#@..................++@@@+++.............................................",
|
||||||
|
"..@*3adeiippghgiijpii7ebda;9=*+....+&>3;aabe4gimppikgiijiigbd9&...@#=,adf7giiiffefgihig4edc3*&........@#>3cabe4iijpig7fffeba-*@...@#>9aeijqqqqqjjjjppigba9,*%+...%,cbegipied03-3cafgig7fba;=*@...+#,;dbgijppijgebdbeipppijigbc*..+#>cdegimiigebaa0adbegipiigbc*..+#=cbgimjpiigbbbfgpijmiiea9*@..+%3abgiipigebac9;0degiijigba;*....@%$=cabf7gijpjpjjjpig7fbd9>@........+#*-cafpqUqiea3=%@...............+&#$9cbijWWjgd9=*&................%=3cbiqUqjgdc-$@...............+@&#&%###&%&@&@@@++.....................................",
|
||||||
|
"..&,cb4ioqWZomXXoWWonVlkeeba9=%....%=3cde47hVXoqWZnmVXqWWomhe0*..+@*>c(7klmoqomkhhmqZnmVh7bc3#+......&*=3cd:4hmoZWWoXVVllkkea,&...&*3abioWWUTTUUWWWWWqmgba9>%@...#cb4ioqqqmebda0dfiqopVhkedc=%+...*9dfkmqqWWWqoi777iqqWWWWomhb,+.+*cdehpqWqomh7eb{b4hhpqWWjmhb,+.+*3agjqqWWWoi7f7ijqWWUWjib9,#...$_ehmpWWonh7ed_db4hmoqWnphea>+...@*=-aeklVoZqWWWqWWWqnVhkea>#........@*,9abgjWUUpfa9>$@................@*=90fiZWWogbc3$%+..............+#=9afjqUUqibac>#+...........+&&#*==>>===>=*==>=**#&....................................",
|
||||||
|
".+$!]zxHGDEEvCGDDEDvDBCAtsz/{;$...%,;{/rsxACCGDEEEvGGvELEDHts/-..+*-;]rtCCHvDvHCCCGDEGHBCyz]',&.....%$-!)/rstBHGvEDDHCBCCBtsF~$..+%-~FKtvEEEEEEEEEEEEEGyzF);-%..+>{zyADEEvGxzr/^^sAEDGHCAy/{;,@..+=)^yBGDEEEELDHxtAGDEEEEEvvAz'@.+-(rxBGDEEDCCAszzsyBCHvEEvHtz;@.@-)^JDEEEEEEHAxyBDLEEEEDwr:;=..+,FsAGvEEvvCAszrrstBHvEEDDAx/;@...%,;)/sACCGLEEEEEEEEDGHCtzF!$........#,;)/ztDEEvGKF~;=&................%,;~FItEEEvyr]~-$@..............@$3~:KwEEEvAs/{;-*@........+%#,-;;'))~)))~~'~~~!;;;-%+..................................",
|
||||||
|
".+*!]zyCGLLLvGGHLvDLHCCCCAyzF~$+.+*-)]rsxBCCCCGGDvGvCvLLLvHAs],+.+%-']rtACHDLvGCCCvvvGCCBAzF);*....+%-!)F/zyBCHvLGLGHCCCBCBs/)$+..#-~]IyvLEEEuEELLLvLvAxrF);$@...>(ryCHDLDHysrr^rKtHvHCCBxr]!-#..@,)/sBHLELLLDHAByAHGLLLLLvHAr;@.+-)^yBGLLLLBCByssstCCGLLLvHAz;@.@=)^sGvvLLLvHAABCvLLLDvGtr{;$+.@-FstHLLLDHCAyzzzyACBLLLLGBsF;&...%-')/sBBCGGLLLLLLLLLvBBAsF;*+......+#-!{/syGLLEAsF~;,%................%,;)FKyLLELyr]~-=&..............@$;~FztLEuLts/]~-=#+.......%=-;!~)]F///FFF]{]]]])~;;,&..................................",
|
||||||
|
"..&>;{}IJwwwwwwJJJJJPKJKJKI[|;*...%>;~2IKKPsPJPJJJJwwwwwwOP[]~$..+@*=;{F^QPwwwwwJJJJJPsKK^F~-=&....+&>-~{F[IKJwJJJJJKKKzKzI/)-%...@*-;([8JOwOOOOJ6PP85Q|~!-=%....$;{2IJwwwP[2{((1:QPJJKKr^{!-*@..+*;)}QPwwNwOJPI[/[IPOwwNNwK[1-...*;)}IJwNNwKIr/Q^^QIKJwNwwP[{=+.+*-_}<6JOwwwPI[QKOwwOJ65[(;,#..+$!:[PwwwwJKI/F:F[IKJwwwwPQF~=....@*-;(FIKKJJJJJJwwwwwJKQ/]'-&.......+&$-!|[5OwNw6}~->*@................&*=-~2<YwwO<(;-*&+..............&%>-_e5wNwwPQ:!->%@.......+&*=-!~)|}[[}}:]_))_]]1)!-$@..................................",
|
||||||
|
"..&$-!|28OwwwOO6<[[QQQIPOO8<|;*...#>c([8Ow65QQQ[[IP6OYRwO6<1_,#...&#>-!(12<OSYSSYYP<QQQQ[}(;-*@.....&*-'|[QQPOOP5<QQIKIKIQQ:'-&...&#=-a|[<Q5PPI<<<[[21d'->>#&+...&,_|[8RRM5[1(_a_(:[QQKIQ2(;,*@..+%=;(15OSwO8<Q2}:}[<P6YSMO<:;*+.+#-~1[6YNS8I[[QQQQ[[QPYSSO<}~>...%>c~:2Q56YO6[}[<OOO6<[2(;-$&...%-'|[6OOOP<<[1||eQ5POOO6<1~-%+...+#=-_:QIII<I5I5IKYSR8[}|_3=%.......@#*,'|[5ORMO51'-*%@................+%$3c(<ONR84(;,*@...............@$>3c|<OSSO6Q1~-*#@.......@#$-;_1145665[[}2||:}[[2~;>%..................................",
|
||||||
|
"..+#,cdfhmppppig7fbee7hpqWqigc>...%-abiqWWoi7fffef4mmpnmni4b0,#...@%*,;abfijWUWWqqmg44774ea3=#......&$3ae7hmnqZpikhhhhlhhk7ba,%...@#*,;df7kkhlhh4eebbba9,*$&@....#>cbfpqZqmg:bdaabb77hhlkfb;,*@...#,9abijqZomk7feef47inqWqjgbc*..+*,cbfpjWWji47hlmhhghpqWqpgfc$...%=9adefhponig4gijopi7fbac=*@..+#>cafgmmmjppgfbeginjXmihfdc,&.....%=-a17hhhhhhilmmoqqigbba-=&.......@**3ae7moWWqiec9*&+................@%*30biqqUjgd9-*&...............+%=30biqWWomhea->%@.......&*>9~bf7gpjopihg77f77kh7b0,&..................................",
|
||||||
|
"..+#,cdfhVVXXVVkeeeee4hnWUWj7b,@.+*9dgpqUWqm441eef4hVVVXVV7ba3%...@#$>9ab4ioWWWqopi4ffeeeda9>&+....+&=3deklloZWonpmmVlVlVh7:c3&...@#$,0dekhlVVVkkeeb_a09,>#&+....&30b7mXoomk4bddbb4klVVVVk1a9*@..+@=;abhXoonmVlk4e4kVmnoZophb0%..+%90d7mXZonVlmmoonmllpoZZnhfd$+..&*,cabeglnoommmmoXXh7bdc3>#@...@=90:7klXnZom744ioZZmVh7ba9=%....+#=9ae7klllVmnjoooqqi7edc3*@.......&$>9dellZWWqpfac>$@................@*>30fiqUWqgb03>&+..............@#>9ceiqWWZXl4dc=*&......+&=3afhmmmnZoononpmmlVVVl4d9#..................................",
|
||||||
|
"..+$;~FzACCCCCBxszrzzsADEEEvy^!@.@-(^svuEEDHsszzzsxACCCCCBs^{;*...@#=;'{/sADLvvHHAszr^//])~;-%....+%=-~FrxBHGvEEDvDvHCCCAts^{;*...@*,;)FzxBCCBCtxz//(~';-,$&@....#;)/sBGBCCtsz^/^rsxACCCAAz]~-%..+#-'{/sACBGCBBxssstCCHHHCtz2~*..@>!)/zAHGHHHBvDuEEGHBHHHGHyr],...+$-!)FrzxHHvDvDGGHBsz/{~;-=@...&$!{^sxtHGvDHtyttDDDHAts/(!,&....&=-!{/zxytBCHEEuDDHHxz/]~;>&.......@=-~FsAHGLEvAJF)3=@................&>;~:QAEEEvyI]'-=@.............+#=;~{rtDEEDGts/~->*+.....%-;{^xHuvvGGHGvDuEuDvHCAAs/)*..................................",
|
||||||
|
"..@$;)FztCBCBCCBszszsyAGLELGx^;&.+-{/JAvELvHxsszzsyCBCCCCBs/);*+..+#=-!)/ztvDDCAxsz^F]{))!;-$%....+*=;'FrsACvLLEuLLvCABAAyz^{!*...&*=-'FryABCCBAsrF{)!;-,=*%+....%-(/ztCCBBysr]FF^zyACCCCxzF)-%...&$;~FryBCCCCBAssyABBCBAysr];*..+#;)FzyBBCHCHGEEELGCCCBCCtsr)=+..+*-;)]/zstCGLLEvHAxs^]);-$%+...+#>~FrzyAGLLvCACHGGHByzr]~-#+....&$-;)FrzsyABHLELLGCtsrF]~;$@.......@#-!{ryAvLEDHzF~;=&................%>;)FKALEuDxr]';*@..............%=;)FKALLLGAyz]'-$&+.....%-']IyGLLLvBCvLLEEELvHBCBs/'$..................................",
|
||||||
|
"..+&=-):^KKJPJJIQ/}[/QKOwww82(-+..#;)25wwwOPQ/[[/QIJJJJKKr[);$&....+%$,-!1QJwJK^}]_~;-->>**#@+.....&#>-'{/^KJwNNNNwwPK^^//F(;-%...+&*>-~{F/rIzI/})!;->==$%&@+....@>;)2rKKKI/F(_')(]F^QKKz[F';=@...+&=-'(]/^IKKrQFF//IzKr^[F);=&..+&=-~]^KKJJKKJYSNNOPKKJsKIF(;%....@*=-;'{2QKJwNNwPI}F~;-->%+.....+@*-')|}I6OJOOJOJJ5[F(!;$&+.....+&*,;~{]FF[Q8wNNwJKQF1~;-*%.........+%=-~:QOwww6}_->#@................+#=-_:<ONwOQ_!->@...............@*>;~:5wNwOQ}(;-$&.......@=-!|<OwNwJPPwwwNNwNwPKI/F'-&..................................",
|
||||||
|
"...%*-'1[IIP6YO6Q[[[Q<POSRY5e'=..+#-'b<OSROPIQQ}[[5OYOPIIQ1~->&.....@**-;d46Y8<}1(';>=*$*$%@.......@#*,;(|}[KOwwSwOOP<Q[[}|_;=&....@%*-;(:2[QQQ2(_;-,>>$*$%&@....+%-'([QIIQ2|(~!!(|}}QQIQ}|~,*+....@%=-!(|}[QI<}}:1[<I<[}(_9-#+...%*-c(}QIIII<6YNNSO6<P6PK2:'-#....@%$=-;(:}<8YSSOI[:(_;-*%@+.......@*>-;_2Q88RRRY8<}(;->*&+.......@$*-;_(|}4<6YSSO5[}|_'->>&+.........@*>-_e6RSO5:;-=#@................+&*-;b<OSR84(;=*@...............+%*,0|<YNR8e(;-$&+.......+#=3_f5YO6<<Q68YOOYO6<Q[:(3#+..................................",
|
||||||
|
"...&=3017hlmjqqjikhhlmpoZqjibc=...%,;bgjqqomlhh4hijqqjmlhkea3=&.....@*=3cbgpqjifbd09,>*$##&@.......@#*,;abefgimVmXmpnjmih7ebc,&...+@%*-;dbe4khk4bd0;-,=>***%@....+%>cb7hhh77ebddadbe4khlh7ba3#.....+%*,;abb7ipmg4ffhppifbdc9=&....%*,;afhhllllpqWUUqqjpmmh7ea,%....@%$,;0de7ipWWWjmkfba;,>$&+.......+%$,;af7ijUTUqigea9,*%@........@**-cdbfgijjjjpmh7ebbdc9>*+.........@#=3afjqUqiec3**@................+%*,0bgqUWjgdc=$@................#*-0biqWqjfd3=#&+.......+&*,cbgggheeffgigihi77b1dc-#...................................",
|
||||||
|
"..+#=9aehVVXoWZZnpnmXnXooXpgb;%+..&=3afinnnXVlVVlmnZZoXXVh4b0,%....+#>,;afhoZoikeed!c3>**%%+.......&*,9abe4kkklVVVXXZZZnVlk4d9#....@#*3ab4[hlVlkeb(a~c09c3>=*&...+*9_ekVVVlk7ee1b:4khVXVVk4dc=@....+@*=3adfhnZomhkhmoom7ba;=$%....&*,017lVXmXnnZWUUWWZoXXVhea3&...@#$,30_e4hVoWWWZmlk4dac,=#@.......@#=99bekmqUTUqmkba9=$&........+&$,9'b:7ioZonXVlh444ee{ac=#........+&*>3afjWUqpfac,*%@...............+*,30fiqUUqgbc3*&...............+#,9aeiWUWogb03=&.........&#=90bbfbbbbbffefff4ebdac,%+..................................",
|
||||||
|
"..+$;)/zACCHHHGvvDvvGHCHtysQ{!*...@>c{^sxtGCHCCCCCHGGCCBCByr]'*...+#,;_]^stDLDAAssr/{);-,*$@.......#-')/zxtBCACBCHCGvLGvHHBy^{=....&=-!{^sxACHHAyszzrrr^F])!-$+..@='FztCCCCCAyssssytBGGGHAsr]-#.....&*-;{FrxHvvHHBHGDDtK/{'-$%....*-!{^xACBGvvLLLLLEELGHBCtzF;%...%>;'{/rxtCGLEELDGHByz/]);-*+......%=-'(/stCGEEEDys^{;-#@........@#-'{/zstCDLvHHCCCAxtyyzr{;*........@*,;)2JGEEEGK/{;,*@..............+%=;~]KtDEEvyQ);-%...............%-;_[VwEEEvJr]~-*+........@*,;_1///}//}/}//^//^F]);-%...................................",
|
||||||
|
"..&*-)/sABCCCCCGvLvvGCAtsz/F)-*+..@*,!]/zsyACCBBCBCCBCCCCAsr]!$+..&=-~]/zyALLGCBtxsz/]~;-,*&.......#-!]rxBBCCCCCCCCCBHGGGLGtr(>+...+%-;(^zyAHGGCBtyyAAyxzr/]!>%..+>'FzyCCCBCBByyxABCCGvLGHyrF~#.....+#=-!{[zABGvvLvGHHAzF);-$@...+%,;{/sABCBGLLvCHGLELLCCAAz{;@..+*-!{/zsACGGGHHHHGGCAAsr]~-$%.....@#--']rsACHGvGtsrF);$#+........&=-~FzyACvGLvCCCCACBBBAtz/~=+.......&*,;)/KALvuts/)'-=%...............%=-;]KyvvLvy/);-*+.............+%>!{/sALELGxrF~-*.........+%$-!~)){))){)]){]]]))~',*&...................................",
|
||||||
|
"..+#=-~FIKJJJKKKP6PPIQ/:{)!;-#&....@#>c'){F2^QrQIrKKKJJJzI}{!-&...&*=-)|}<POwwPK^Q/F|)'-,*#&+.....+&=-~FQzKsKJKKKIKKKPJwNNwP]!$....+@$>;){}IJwwJKIrQrKrI/[]_-=@..+*-!{/KzKzKzrQ^/rIKJwwwwJQ:)-&......+%*=-~:QIPwwwNwKI2(!-=%+.....+*=;~]/IKJwwwPIQIJwNOPI^/{;*+..+&=-']/QKJwwJQQIPJwwKI/2);,*@.....+#=--~{[IIKPKKQ}(;-$&+.........@*=;'FQKKwwwwKKrKrrzzKzr[{;*.........&*-;_}8Mww6}_;->*@...............@#$-;1<POJK[(;=*%...............&$,;)}5OwS8[_!-*&..........+@%#$=>>>>=->-,--,--==*#+....................................",
|
||||||
|
"..+&,-~|[QIQQQ[[}21:|(_~9--**%......&#$>-;!((|11:}2QQIPPI[}_;>&...+$>;~:2[5OYO6Q[[22:(!;>$#&+......%*-;|[QIIPPIIQQQQQI6YNNY<:;*+....@%$-;(|[5OYP<QQQIIIQQ}:_-*@...&*-!1[QIII<Q[[[[QIKJwwY5[(!-%.......+#$-;_}Q5OSNYO5[1~-,*&+.....+@#=;_:}[5YM65}2[5YY6<[}(!-#....%=-_|}QI6OO5[2[<6OOP<[}_;>$&.....&*>-;_1}[III<Q}(!-=*@..........&#>-~|[<IORS65QQQQIQIIIQ}_;%.........@$$,a:5MSY5e_;-*#@...............@%$=3_2<I5[:'->#@..............@&*-9_:5OSR8ea-=#@.............@@&%%&&&@&%*#$$#%%@@+.....................................",
|
||||||
|
"..+%,;ab4hhlhh7ffbbda0c99>$#&@......@%*$=3390addbee44ilmlke0c,%...@*,0bf7kpqWqmhk774ebac3=#&+.....+#*,0|45lllmlhhkhhhipqUUjibc*.....@&*,3adfiqoplkhkhhkk74e03*@...&$,0b4hhhVlih7hhhlmoWWqpgba-@.......+%*,9af4ijWZopl7b0->*&.......@#*30bf7ijqjgffgiqqphfeb;,*+...%=;dfghioqqigf7ioqomhh7bc,*&....&%=3adbe7hilllh4bc-**@..........@#=-ae7hmjqWomhhhh5hllkked9#.........@*$,0fiqWoiedc-*#&+..............@@#>3abkhh7bc3*%@.............+&#=3cdfiqWqpf0-*#@.................+..+.+@@&&&&+.+.......................................",
|
||||||
|
"..+#,a14lVXlllh7e:bdac9,=**#&........+@#$$>-cadb:e4khVVVVl7ba3#...%,9d7kmmoZWqoVlhlmh7ed03=#@.....@&$-c:kVVVVXlXmnmnnnnjqqjgb9%.....+%*=3cbfinonmnmXXVVlk71a9=@...@*,9de4kVmXnmmmlmVXZWWWoke03#........@*>9ae7lnoZZnh41c,*#@.......&%>3a1f4inomh7egmoomk4ed03*@..+*3afkXmooZomk74loWZonmi7bc,%...+#>cdeghimpnXonXhea9>#&..........&*>9deklXnWZqnnmXmnXmVVl4d9*.........@#>3a7pWWWphbac>$#@..............+%$=3aekllkb0,>#@.............@#*>9db7mZWWjgd9>*@........................++++...........................................",
|
||||||
|
"..#-)/zxAHHHCCCtssr^]);-,=#&@.........+&*=-;!{FrzsABCHHHHBAz/)=..+*;(/yvDDuLEvGGCHGGvAs/]~-=%.....&#-;)^xCCCCCHvvDvvDvvvGGxK2)$......%=-;~]/stGGDLGvHCCtxz^]!-@..+%>;~{FrstCHvLDDGGHHvLELDts/'*........&#-!{/zxHHHHAszF);-#+.......%$-'{/zsxAHAyzzzyHBAssr/);$@..+>)/sGDDvvvHAAxxHvvEvvvHy/(;*...&,~]KtDvDEEEDvDDAKF';=*+.........%>-~FstCCGLEvvLDvDDvHCCAs/!$.........@$-!{KAvDDGyz^{!-=%+.............+%=-;{rxtys/);>*&............+#=-!)/zxGDLLAK:)3=&.......................................................................",
|
||||||
|
".+*;)^sAGvLLLvGCBssr]~--*&+............+&*>-!{/zxxCGGvLLLvBtr(>+..*;)^JGGvDvLGHCCAHvGxz/]~-$&+....+#=;)/sAACBCBGGDLvLDGAxsz^];#......+#,-!~FzstGvGvGCBtyzr/);*+...+$-;'{FrstCCvGLvHCBGvLGGAzF!#.........#>-;{/zxBBAyz/]~-$%+.......+%--)]^rsttyzr^rsxAxsr/])-$+..@='1zwGLDHCAAssstGvLLDDvy^);*+..#-'/swvLvuuuEuvutz]~->&+.........&=-']ztACHvLLLvLLGLGHBAxz];*+........@*-;)[sAHBAAyrF~;,#@..............@*>;~]rzz/{!-=#+............+#-;'_rsABAGAyr{;-#+.......................................................................",
|
||||||
|
"..%-;|[PONNwwwwJK[}]~;$#@................@#$,;)F[IPwwNwNNwKQ]'*...@=-~1<56P6PIIQQQ<<<2(!--*&.......&#=-')]F/[[[Q565655<[1();-$@.......@%*=,-_(}Q<85IQ2F{)~!-=&.....@#$=-;)1/[I5P6I<QQI5P5[2(;=+.........@%$=-'(F2/2](!;>$&+.........+%*-;!){{]{)!'!({]1))~;-*&....%,!|[55KIQ[/]1:}<55655[:0-*&...@$-~2I8JOOOOOO8P<1'-=#+...........%*,;)]}^<I88888666I<[/]);,&..........+#$-!(:}2/^[])-,$#@...............@%*--;!!;-=*&@..............&*>-;|2Q[[}1(!-=*+........................................................................",
|
||||||
|
"..&$;_}[POSSSYO5Q}:~;>*&+.................&*=3~(}[IOwSNSY852(;*+..+%*-c_(1|||1((((|(a'9->*&.........@%*,-;;~_(((|111|1(_;--,*@.........@&#$=--ca||1_(!;;-->=&+......+&*=>-;_((|111((((|||_;-,#+..........&%$==-;!'!c->=#+............+#**,--;---->--;---,==#&+....&$>9'_|1((~~';;0_1111(_9-*#+....&=9a14[[2<<[<[}|';=*@............+%*>-;;_(111|||1111(_';->*&...........+%#-9!_((|(~;-**%+................@%#>$>>=$*&@...............@%=>;'||1(_~;-$*@.........................................................................",
|
||||||
|
"..&*3abfgimipi5g4b1a9=#@..................@#=3cdbfgiipipii4ba3%....&%$,,3c00000ccc;c9,>*%&+.........+%#*>,-39ccc;cc0;cc99>**%+..........@&#$>>,39;0cc,,>$*##@.........&#$=>39cc0c0c00;c;993>*&...........+@%$$=,-3,>=$#&..............+%#$*===*=$>>*,,=>$##&+.....@%*>,99cccc3-,,399ccc39=>*&.....&$,0abfbfffffbbd;3*%+.............+%*$>,99c0000c0c0cc9,,=*&+............&%$33c00a0c=>$&@..................@@#%%%%%@.................+&**,9'ac0c9,>#%+.........................................................................",
|
||||||
|
"..&=30d:47hhhkk4ebd03$%@..................@#$,0ab|47khhhh7fba3#....@%**,,-99c9c939,,,=*#&+...........@%***==,,,3>--3>-,,,*$#@............@%%$*=,,,,,,,****&+...........+&#$,,3-399933,33->=**@............+&#$$>$>==**%+...............@@&##$**%*##*#%*#%%@@......@%#*=,3,,,,,>>=>,,,9,,>$*#&....+&*39dbeeeeeeeeba9>*&+..............@%*$=,3,-3-399c99,,=*$#&............+@#*$=>--3-,>*%&+...................@@@&&&+..................+@#$=,3-93,,=*%+..........................................................................",
|
||||||
|
"..#,;)]^zssyyxsz^F])!-*#+.................@#=-~{F^zssysxssrF(;*....+&#$>3,9;;;;-,---->=#+............@%%#*>>--,333-3,---=*#&+............+&#*=>,>,3---=*##&+...........+&*=>--,--;;3;,-,-=$%#+............+@#**===$$#&&+.................+@&%%%%&&&@#%##%&++......@&##*>------>==-----3-,=##@.....%>;_F^rIrrKr^^/{~3$&...............@#%*$------->-;;---$###@............+&**=>------,$%+.....................+.++.....................@#=>--->--=#%&+..........................................................................",
|
||||||
|
"..@*,!)]/^zzrz^/{{~;>*&...................+&*>;~){F^zrzz^^/{'-&.....++@#*$$*#*#$$$**%%@+...............+++&***=$$==$$*#%#&@+...............+&%%%$$*$##@+................++&%%***$****$**&@@+...............+@&%%#%&@.+..........................++.+..++...........+.+&&%*%*%%##%%%#%%*%##&+......+%>;)({{]]]{{()~->#+.................++@&#**$#$=$****%%+................+&&&%*#$***%+.................................................+&**#$$**&@+............................................................................",
|
||||||
|
"...+@#*=---;;;-->$$%@++......................+&#=>--;--;---=$%+............+.+.+.+.+........................+.+..+.................................+.........................++...+...++.................................................................................+.++..+..++..++............+@#*$=$=$>=**#&+.......................++.+..+..+.+........................+.++........................................................+..+.+...............................................................................",
|
||||||
|
".....+++++++.+@+.................................+..+@@+@+++....................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"...+@&&&&&&&&&%&&&&&&&@+........................................................+...........................................................................................................................................................+&*%%%%*%%%@+.......................................................................................................................................................................................................................................................................",
|
||||||
|
"..+&*%#**#*$$>*=*$=>=**&+....................................................&%#%###%&+........................@&&&&%&@+................................................@&%%%@+.....@&%%@+.................+&#####&@+....................@&#$>>---->-,=*#@+.................................................+@&&&&&&@+........................+@@@@+.......................................................................................................................+@%&%%&@+............................................",
|
||||||
|
"...+&&&&&&%#*-,>=>,--==%@..................................................++@%#***%#%@......................+@#%%#%%%@@+.............................................+@#%%%#%%@@&@@&&%##&&@+..............@%**#%##&@+..................+&#*$>==,=,=,>=*$&&@..............................................+@@&%%##%%&@+.....................@@+@&%%&+.....................................................................................................................+@@%&%##&@++..........................................",
|
||||||
|
"...@&&&&%#*=3;;;-;!;c;-,*@.................................................+&#**>>=>**&@...................++&#*$$$$$*#%&@...........................................+&#*$$$$$*##%###$#$*$*%@.............@%#$$=>>*#%+.................+@**>,----;----->=$*&@............................................+&&%####$$#%%%&....................@%%%#%%%&+...................................................................................................................@&%%##$$*$#%@@+...................+@&@@@@@+............",
|
||||||
|
"..+&&&%#$,c0adbddaddaaa0;,#+..............................................+&%$>,3c93,>#&+................+@%**$=,,,->>*$%@+........................................+&&#$,-3,,,,=$*$>=>,,,=>$#+...........+&*=3-c33>*$@+...............@%#>=39aad~dddaaa;9,>$@................+++++++++@+...............+&%*$$>>,=,=>>**#@+................+@%$**===$$*&+...............................................................................................................++&#$*>==,====*#%@+...............@&#*$#$#**#&@+.........",
|
||||||
|
"..@%%*>30_b|447744eb:b:ebd9$..............................................@%>,ca1e1bac,$%+..............+%*=3ccaaadada03=$&+.......................................@%$,9!adddaa0ccccaaadaac9=#...........&$=3~be:bac=*@..............&%$>3'be7giiiiig74eba3=#+............+&%%#####*#*%%@+............+%$=>39;aadaaac;9,*#&@.............+#*-900a00c3=**&............................................................................................................+@%*$-90caaaaa00c3=*#&.............&#**>=3=3,,==*#%@.......",
|
||||||
|
".+#=>-)FrzyxBCCHABAxxxxxsz/~%...........................................+#=-!)FzyBByrF);>*@...........+&#,;'{F^rzzzzzr/{!;-*@..........@&%%%%%@+....+%#%%%@+......@#-;)Frzszszz/F]F/rzzzzr/])>@........+&#-'{rxBAxr]~-=@...........+&=-;']/sBGGDvNvGGABAsr);>&..........+&#=,,-,,,,-----$$%@........+%$>-!)]/^rrzzrr^/]{!;-=%+..........&*-;)]//rr//])!-=%+.........................................................................................................@#>-;')F/rrzzzrr/F{~;->%+.........@%>-;!)){)){))!;-=$&......",
|
||||||
|
"..%==;)rzyAGGvLGLGvGvGGCtyz{>...........................................@#-;)FrsACCtzF)!->#&+.........@*>-')FrzsxAtxxsrF)'-=#.........&#=$>>>=*#%&%##$=>>==#&.....%>-;{rsBAtAxszr^/zsxytAyz/{;#.........%=;'FsABCBzF~;>#............#,-!)/sAHGGDDvDDvHCBAr]!-#.........@&*>-;;;;;--;;'!!;-=#+......+&*>;')]/rssxxyxszr^F]);-$@.........&*,;)]/rzzszrr/{!-$&+.......................................................................................................@*=-!'{FrzssyyyxzzrF])!;,%........+#>-!){F//^^/^F{~;->*&.....",
|
||||||
|
"..%$=-~][IJwwwwNNwNwNwwwK[F~>@.........................................+&#=-;_2IJJJKQ|~;-=*&@.........@%*-;~2QIPIPJKPI[|!;-*%........&%#**=*$$**#**$***=$=$*#+....&*,-~}IJJJJPK[}]2[IPPPJKI}_-%.........%*,;)[KJJK})->*&...........+#=;!~:[PJJJJJJJJJJKKrF~-=%.......++&%*=,-;!;;->-;~~'-,*%+.....+&&$,;;~1}QIKPKPKPIQ}:)';,$@.........@#*-'(F2F/[/QQ[(!>*&+.......................................................................................................@*=-;~):[IPIKPPKI<[1(~;-=%.........%=,;)12Q<<<Q<[1!;-=*%.....",
|
||||||
|
".+&=-;'|[POwNNNwNNNNNNSY6<1(;#.........................................@%*>3~(}5OwY6[1_;-,*#%@.......@#$>-!176OYwOYYOO5}(!-=#+......@@#>,-,--->=>*>=>>,---,=%@....@*,;(78OYRRM6<}:}<8YSMRR8[(;*.........@$>3([OOO84~-=#@...........+*,;~(:<6O85<<<<<IIIQ[1~-=&........@&$$>-;~()!--;_{:(!,$%+.....@&#*,;(12<8OYOMwYYO8<}1(~3=%........+&*>-'|}[[}2Q565}'-$#@......................................................................................................@&$>;__1[58OYOYOMOO6[:(_;-#+........&$-~:[<8OOOYO5}('->*@+....",
|
||||||
|
"..&*,;abgpqWUUWUWUUTUTUWoifbc*.......................................+&#$=-cdbgmqUWoifba;3>*&+.......@#=,;afiqWWWUWWWqjgba9=*+.....+%**3900cc;c3939399;c0cc3*@....&*3cbgqTTTTTqigffiqTTTTUqgb3#........+&*,;bgqWqjgd9=%@..........+%=-;dbgpqojlhhhhhkhll7ec9*%........@&*=-;adbba!c;deee0-*%@.....@#$=;abf7iqWWWWUWWWqp74bdc>%.......+@%*-cde47777ipqjga9=#@...........................................+++....+++++..............................................+&#*30defkjqWWUWWWWqji7ebc-%........+#*9afimqWWWWWqgba;>*&.....",
|
||||||
|
".+&-,0d4moWUTTTUUUUTTUTUqnhfd,@...............+@&%&@+................@#=,c~be7ijUUUomh4|d0c>$&.......@*>3abfpZWUUWUUUWjhed;3*&.....@#*-;d(bb:bbd(ddd(dbb1ddc3#....&$9cepqUTTTTUjhgijWTTTTTqib9%........+#=3abiqUUoib03>&..........%#>cdbehpWWnmlllllVVVVkea-=&........@%$,c0dbee(0cab4ked3$#@....+&*3ca:7klnZWUUUWUUWWnVkked9*.......+%$,9_ekllQllVoZqib9,*%................+@+++++&&@@@@@@+........+@&%%&#%###**###%&&&+........................................@*=9cd4khmnWWUUUUUUWZXhk410,@.......&#,c|7lnZWUWUWqmed03=&.....",
|
||||||
|
".+%-!{^sGDEEEEEEEEEEEEEEEvts^'&.............&&**>-=$$#&@...........+&*-!{FrzyBHDEEEEHAAsz/]'-%......@#-'{FzyGLELLLLEELGsrF);-%.....&>-~]rsssxysxsxsysyyxssrF~;&...%-'1IwDEEEEEuvAttvuEEEEEEAI)=........&$-)FKAEEEDyr]~-$+........@=-!{^zxAvEEDCBCCCCBCCCAz]~;*........&*-;)]/rzr/{)]^sxzF~-=%....&>-~]rsBHHGvLLLEELLLLDHHAtrF-&.....&*=-~{^stACACBHGLvyI{'-=@............&#*$>=$*$=>,,,>==**&.....+@#=,---;;;;;;;;;;;--,>*%&+....................................%,;)FsyCCGLLEELELELLvGHAAs/($.......#-;)^yAGLLLLLLGtz}{!-=@....",
|
||||||
|
"..%,;{/sHLEEEEEEEEEEEEEEELBsF;&............@#>=---;--=*%@..........@#-;)FrsACGLLEEELELGtsrF);*+.....@>;)FrKxCLLGCCCAHAys/{';$&....+#-')/stBBHHGGGGGGGHCCBAs/);*...%>;)^sAGGvvLvHByAHLEEvvGts/)*.......+&=-']KtGLuLxr]!-$&........@$;~FrsyCvLLLCCCABABAAAxzF~-*+.......@%-;))]F^/])))Frr/]!-=&....#,!{/stGGGLCvGLLLLLGHGvGGts/~#.....&*-;){/sACCCCCBvLDAr]~-=%..........+%*=--;-;-;--;;;;---=#&...+%==-;;'!!))))))))~~~!'--=*@...................................+%-!{/sGvGLLLLEELLLGGGGLGHtz{,+.....+#>-)/zyBBCBHCHAsr]);,*&....",
|
||||||
|
"..+#>;_48wNNNuNuNuNuTuNSNw52)=+............@&$>=,---,$$%@+.........@%$-!{/[IJwwNwwNwNwwI[|);,%.....+@*>;)12QPwwPQ[2}}}|(!;=*%+....+&$-!{/rKKwwwwNwwwwwJJzI^]!-&...+#=-~|}QIPOwOPQ[QPOwOKIQ}|!-@........@#>-':<OwwO<(',$%+........+#,;)FQQKOwwOPKrr^/^//FF)!-*&........++#=,--;'!;---;~)!;,$%@....&*-!([PwwwwJJwwwNwwsJwwwwP[(;%.....@#>-;)]/IKzKKKJJwO<1~-=#@.........+&%**,,----;----;--,,>*@...@%$=,-;!!!~~)_)~~)~!;;;--*$@.................+.++..............+%=-~:IJwwwNuwNuNwwJJJwwwOK})=.......+%*-'(]}22[}}22(~;,>$&+....",
|
||||||
|
"...&>c_}5RwNNNNNNTuNTNNNSO<:~=+............@#*=---;;-,*%&+........+&%=-!(}[<POYMOOOOYR8<1(~;=%+.....&*,;(12QIO6<}|(((a~;-=$#@.....@#*-')[QIP6OOwOwOwOOOPII[|!-%....@#=-~|:}<6OO<}}[5Ow6<}:1~,#+........@%*=c(<YSS84(->*@.........+%-9_e[<P6OYOP5K<[222}:(~-=#@..........+%**=>,,=**=---,=*%@+....@=-!(}<OwwOJJJwSwOPPPPOOO64|;#.....+&$-;~(}[QIIIIPOY6<1;->%@.........@%$>--;'!!!!!'!_~~;;--*@...+*=-;_(1b:1::b:1:111{|1_c-*&..............++@@%&&%&&@@@+........%=;_|<6OwwwwNwOwwOJJJOOw8<:~>+.......+#=-;___((___~;-=$#@+.....",
|
||||||
|
"...@=9afpqWUUTTUTTTTTTTTUjibc$.............&$>3caa_ac9>#&@........+%$=;de4hhlmmiigiimmiged0;=@.....@%$,;dbf7imi7fbaa0;93,=#&+.....@#*3ab7hllVnmmmmmmnmmllk7ec3&....@%$3;dbfgpqqmh4gmjqpgfbdc,*.........@%$,9bgqWWjgd;=$&.........+#-0fipjojppjjojpih7e:bba3=%@...........@%**$$$$***>>>$#&@.....+&=9abgkmmXoqqppppmlmllmmmkge0*.....@%>c0bb4hhk77khpqjib09>$&........+%*=3cdbbeeebbdbeefbba0-%...&*-cbgiijijijpijpijpiiigbc,#........+@@&%&%###**#**#%%#%+.......#,0bfhimmnqWqopmmmooommmikfb>.........&*=-,cc;cc993,>**&++.....",
|
||||||
|
"...&=9d4oZUUTUTUTTTTTTTUWZif0#............&%=-ab1eee1a3$#@........@*=9abklVlVVlh744khVl74:d0,#.....+*=3a|4kklVlh4:ba!99,>$#@......@*>9aekVlVXVXVllVVVXlXVVhed3#....+%*>ca|ehnZZpllVXZZnhebac,#+........@#*-0biqUWqgb03=%.........&,0bgpZWZoXXoWWWZnllhk4|dc,$@............+@%%#%%%%##**#&+.......%,017lVmXXoWWZnVVVVlXXVVVlh4d=....+%>-~be4klVVlhhVoZqi7dc3*&.......&#*3;a:4khkhkk4ekklll7eb0*..+%,0biqqWWWWWWWWWWWWWUWWjgbc$@......@%**===,,,,333,,,,>==*%+....+#;_eklVVVnZWWoXVmnoWonmVVlhe9&........+%*=,=,,,>-,,***&+.......",
|
||||||
|
"...#-_/JGEEEEuEEEuEuEEEEELw/!#...........@#,;)Fzzsssr/'-*#+......+%=;)FztBCHCBBtsssxACBxsr/);*.....&>;)/zxACCCCBxsr/{);;-,*&......%>;)/sACCCCCCCCCCBCCCBCBBs^)=....+%*-!{/zxvDDGHCHvDEvxz^]~;$@........&=3c(kAEEEGxQ);-=&.......+*!FztDLELDHGvEEEELHCAtyz/{~-%..............+@@@&%&&%&%&@........*!]zxCBCCHDvEGHHCCCCCCCCCCCxr;....@$-~FrsxCBCCACBHGDDAs^{~-$@....+%>;;)]rxACCBCBAyyABCCCAxr{-..+$!{IxEEEEEEuEEEEEEEELEEDyKF!#....+&*,-;!))))(){]]{)))~';->*+...&,)/sABCCCGLELGHBCHDEEGHCCBAs{#.........&#*$>,----==**&@........",
|
||||||
|
"..+%-_/sHLLDEELEEuuEuEEEEvy^;%...........+#,;)/zssxszF);>*@.......&=;)FzACCCACByszzytBtsz^]);*+...@#-;)/sACCCCCAAssr/{~;-=*@.....+%-;)/sACCBCCBCBABCCCCCCCAs^)$+...+&>-;)/zsHLvvCHCvGvHyz/]~-*+.......+&$-;{rJvLuvy/{;-$@........$'FKAGLLLvCHvLEELGCBCBAxr]);*+...................++.++.........+='/zACCCCCGLLvBCACCCCCCCBCAA^-+...@*-)FrstABCCCACCGLLts/]~;=@....%=-;~]/zyCCCCCCAAABCACAAyr{=+.+$;{kyHGvLDvLDDDLDLvLLLLDAzF)$....@#-;'~{]F//^^^/^/^//F])~;-#...&!{ryBCCCCHGLLGCCCGvvvCBCCCAs{$...........+@@%***%##%&@.........",
|
||||||
|
"...&=;_[6wNNNuSNuuSuSuNNNw<1;&............&*-;~]FFFF|)-,*&........+#=-):rKKKKI^/2F:F}//]_~;=*%....@#>-':QKJJJwJJKII[1);,$%@.......@*--~FIKzKKIrI^rQrIKKKKKr});%.....+%*,;!1[<JJwwwOwOJ<[1)'-=&.........+%*,;([5P6<[_;,$&.........%>!1QOwNwwJPJJOOJJPKJKPI[_;,%...................................*;)F/KKzKJwwwOKQ/QrIKIIrIKr^|>+....&*-!(]/QzKzrKIKJOJ<2{';=&.....%=-;!):[IKJKIrIrrrKzKzK/F_;*...%=;_}<5P6P6J6666JOJwwNwO<})-#....&%=;')|}}<QQ<Q<Q<[<[[}1!-*&...+=']^IrIKKPwwwJJKKJJJJPIQrKr};@.................+...............",
|
||||||
|
"...&$-0}6wNSNNNNSNTNNSNNSO<19*............@#=-;_)(_()'-=#@.........&=-!|[IIIQ[21((((1((~'-==*@....@%=-~15OOSSYSYYY652(!-*&@.......&$=-~1[IIQQ[}}2:}2[[IIIKQ:'-&.....+@**-;_|[I6YMMYO65[:(;-=$&.........+&$>-~1}[[2(!-=%@.........@>9_48SwYOPII<<I5IIPOYO8<1;,#..................................+&,_:[QI<IIPYR8[}::}[[QQQQQQ[(=....+&$,;_(|}QQIIIII5K<[2(~;>%+...+&*-;(1}Q5OP<[[[QQIIIII[}('-%...@#>3_12}[[[[[[[[[Q<6YwS6<1!,%...+&$>!(|2<66OOOOOY8Y6YY6<(3=%...+#;(}QQQQQ5OSYOPIIIIPIIQQQQ[}-+.................................",
|
||||||
|
"...&=9afpqWUUUTTTTTTTTUUWqgb0*............&*=3cadbbbda-=#&+.......+%=3ab7klhk4fe1bbdbbdac9>$#&....@#$9agpqWUUTUWWqqpgba-$#@.......@$>-a:7hlhh74feeee7khhlhhe09%......+%*,3abfhpqTTTqmh4bdc3=%@..........&%>90bffffdc,>#@.........@*30fiqWqjmkhkhhhhlpqWWqiea3#...................................%>0b7hllmmooqpif4e4khkkhkhk4b>....+&*,;a(efhlllmlVlmh7eba;=%+...+#,;de7gpjqoi44775ilhlh7ba;=%...@%$3cadbbbbbebfff7gpqWWjgba3#...+#$-abf7ijqqqqqqWqWqqqjif0,%....*9de4hkhkijWWqpmmlllkhhhkhkf9+.................................",
|
||||||
|
"..+%,0d7jWUUUUTTTTTTTTUUWqmfc*............@*30de47744(0,$%+.......+*=9_}kVVVll<7444444e:dc9,*&....@*,3afpoqqUUUWZZom4eac,*%+......@*,ca4llVlVVhkk7kkllVVVlh4d3%.......&=3cdeklnqTTTqXVk4bac>$&..........@$>9dekhk7eac=*&.........@*,cbgpnnnXmnmpmmmXnWUUqp7b9*+..................................%301klmnnnZZWZpmilimmVVllll7b=+...@%$3adb4hXnXnXonXnXh4:ba9$@...%=3dfimmoooomlllmXnnVllk:d9,&...@#*,30aadddddbbbe4hmZWWqmfd3%...@%>9aeehlXoZoZZoZoZoZojibc>%...+*0bQkhhlVXqUUonnXXVVVVllllkec&.................................",
|
||||||
|
"..&>;(^JvEEEEEEEuEEuEEEELDyI)*...........@#-~FzyBCCAxz]~->#+......&=;~FzACBCCCCBAytABAAsrF{!-*....&$;_2zyHHGDEEEGBCAsrF);-=%+....+%>;)/sACCCCCCABBCABCCCCCAs^)$......@$;)]^stBGLEEEEvCAsrF)!-%.........+#-;)^stCAAzF);,*@........&=9~:^zxAHCHvDDGGGHDEEEDts^{,+.................................+*;{/sAGDvDEEEELvLEGvvvHCCCAsF-+...&*,!{^zxBDLEDvLEDDvAsz^]!>@..+*;{^xGvDvvGCCCCBHDDDCAysrF~;*...@#$,3!~_))_{]]]F^zsGDEEvAK^)=...&$-!]/zsxAACCCBCBBCHBByK2~9$...+=)/sACCBHGDEEDHHCBCCHCCCBBtz~%.................................",
|
||||||
|
"..&-!{/svLEEEuuuuuEuEEELELy^'*...........&>;)/sACCCCBs/);,#@......@=-'FzyACCCCACBBBBACAyz/{'-#+...+=-~]rstCCGLLvCCBxzrF{!--*&.....#-')/zACCBCBCCCCACCCCBCCAs/)=+.....&=;)FrsACvLEEELCCtsrF);-%.........&$-')/sBCCtz/);-*+........@*-;~]^zsxtABHGGGGLLGGGGAzF)=+..................................*;{^sAGLDEELLEEuLEuLLvBCCAAs/-+...&*,;)/ztAvLLLELLELvHxzr]!>@...*-{QyDLLLGCBCCBCHLLGCAxzr])-*+...@#=>--;;;;!'))]F/sALLLDAz/)>+..+#>!{/rzssyyxAAAAAtxysz^]'-%+..+=~/zyBCCBHLLvGCBCCCHCBCCCByr'&.................................",
|
||||||
|
"..@*,;([6NNSuuuuNuNuSNuwNO<|-&..........+%*-;1[KJJJJPQ|!->&+.......&$,!{^rKzKzKzQ/rrIKr/]_!-=&.....&=-'(F[IKJwwJIIQ[]|';-==*#+....+*,;)2rKKKKzKzrKrKzKsKKKr})-%......@*=;!(F[KPwNNNwPK^/('-,*&.........@&*-;_/IKzI}~->*&.........+%=,-;~(]F22[QQIPwwwwJKI[(!-#...................................%$;)}QJwNwNwNNNNNNNNNwJKzK/F!*....+&*=-~(25wwNNNNwNwOK}:)!-%....&=;(<ONwwJKKQrKKJwwJI^/1{!-=&.....+@&%***>$$=>>-'_}<OwwO<1_,%....@#=-'~({]}F}F/2//F:F]{~;,=&...+#-']/QzKJJwwwJKKKKKJJJJsKI/(-+.................................",
|
||||||
|
"..@#=-_}6NNNSTNNNSNNNNNNSO<_-#...........@=,!1<OYYRR6<b'-*%+.......@%*-':}[QIIIQ<<<QQQ[1('-=*&.....%*,c_(}[<8RR8<2211~';-->$%@....+&=-!1}QKIPPI<Q<I5P5PIII[1~-&......&#=-!(|}Q5MSNNO5Q}|('-=$@.........+%$=3_1Q5KQ1~-=#@..........@$>-9'(11:::1[[<ORR6I<[1_-=%+..................................@*-'(}<OwwNwwwNSwSSwOOPII[2(;*.....@%>>;_1[6OwwwwwMO6[1_!;=%....&=9~[8ORY8PIQQQ<6YY8<[}1~;-*&......+.++@&&&%%#$==9_26OO52(;-%.....@*>--;'______(_((_~!!;-=#+....#=;_|[QKPOwSwP<QQIIPPPP6I[1~=..................................",
|
||||||
|
"..@#>9agpqTTTTTTTTUTTTTUWjgb;%..........+&*-aepqWUTTqiec9=@........@#$,9d:f4hhmpjjjjmk7eda9>*&.....%*,;dbf7ioqqpgeebbba~0;3,*&+....&*,cb7khlmpojjjoojopmhk7b0,&......@$=-cdbf7ijUTUji7ebdc-=*@.........+&$-cdgmjjiea9=#@..........@*=;abbfeeeeef7gjqqpik4b03*@...................................+%=9abgmjnpnoXpnnooqomlhh7:a3%.....@&$=3cdfgiiiVimiihfda9,*&....&*-0fgmppjjpih7hippm5k74bc9=&............+@@&&%$=,0bfgggba9=&....+@%*=>--;99cc9;cc;cc9-,$#@.....&*-0de7hmXoWqplhhippnmmlkfb0*..................................",
|
||||||
|
"..&*,abgjUTTTTTUUUUTTTTUUqmfa$..........@*,0a7jZUTTTUjfa9>#+.......@&*>9ad:ekVXqUUUqoml4bc9,*&....+%=3db[klmoWZph44eee:b|bd03=+....&*9aeklVXoZZWZWWWUWZXVlkea,&......@*>cabekhpqUTTqmh[ebac>$@.........@#=3abioZWoib03=%..........&=caekkkk444e47loWZnhkf(c,>&...................................+%=90b7lXXXVXXXXmXnnXXXVV7e03&.....+%*,90abe44hhhhh7fbac9,*&....@=,9d44lXoZoXlhlVVXXVVVhedc=&...............+@%%$,9abfebd;,*+.....+&%#$*==>,-,-,,,3,,==$*@......&*=3dekVVnZZZnmlVXZZnXXVh4d9*..................................",
|
||||||
|
".+*-'FztvEEuEEELEuEEEEEELvtK]-+.........&,;{QsDEEEEuuuz});>@.......@%=-;)]/zyBHDEEEEDCxz/)!->%....@>;)FztCHHvEEvAAxyysxysyz^{;%...@*,']zxBBCGLLELLEELDGHCAyr{;%.....+#-;)FrsxBGDuuEEGAtsrF{;-%.........@*-']rtLEvvyr]~-=@........+$;{rsBCCCAxxsxxHvDDGByz/);,#...................................@#-;)FztBCCCCHCBHCGHCBCBBx^{-%.....+#*-;~)F^zzsssszr^:(';-*&....@$9~FrsAHGDvGBBBCCCBCCCBsr{!$................+&#=-'(F//F(!-*+......@#*>=,-----,-,>---,$#&+......#,;~FzxBCCDDvDHHBGvDvGCCAz/~>..................................",
|
||||||
|
"..*-']IyBLLELLLLELELLELLvHyzF-+.........#,!{[sHLEEEEEtzF~;,#........+@*,;)]^zyBGuEELHtsr]~;-$+....#-!]^sBvLLEEELvHGHGGHGvHAs/'$...@*,;{/sxtABCCCBCAAHHABtys^),%.....&#-!)/rxBGLEEEELLGBsz/]'-*.........&=-~]IyGLLvtr]~-=&........&>;]ryBAACBByxyAAvLvBtsrF);=&...................................+#=;']^sABCCCCCLvvCBCCByxzF),+.....+@*=-;!){F/F////F{)';-$%@....@$-'(/rsxBHCCCBCCACCCCCCyzF)=+.................@#>;')())!;=%.......++&&%####%*#%%#%**%%+........&$-!)/zxyBCCGGGvvvvGCBAysr{;#..................................",
|
||||||
|
"..&=-~1}IPwwNNNNNNNNuwwwP<}(;$..........@*=;_[6wNNSNN8}_;=*@.........+@#=,-!)1QPwNwO<2{);,*%@.....@=-!|<OwNNNNNNwNwwwNwNwwO<|;#....&*=-~{]F22}}}:::11:F:F]{'-$+.....@&$-!(]Q6wwNuSNNNwPQ1(~;=&.........+%=-':<ONNO<|'-*%+........@*-!]^rKzKKKKIIPJOwOK[F(!-=*@...................................+@&*=-~)F}/IKJwwwwJJrQ/]{~;-#........+@&$*=----;-;-,-==*&@+......&*>-;~1}[IKKKKzI^QrKKKK/}_;*...................+&*=,-==#%@................+...+....+...........+@*=-'){F[QKPJwwwwsKI[F{)!-*+..................................",
|
||||||
|
".+%*,;(1}Q<OOwwwwwwwOOO5Q2(!-%..........&#*-0:5SNNNNY51!->#@...........+&#=,;_1<YNR8[1'-=$%@......@#=9_78NNNNNNNNNNNNNNNNSO<(,%.....&*>-''___~~';;;;;;'__';;=&......@%*,;_|[8MNNNNNNwY52(~;-*@..........@*-'b<YNY84(;,$&+........+#=-_}QKI6OOOO8OOYw64|_!-=#@.....................................+@&#=-;!(1}[PONwwP<[}(_;-,#@.........+@@#***>*****$*#%@+.........@%*=-;(:}[[QQQ[21[QIIQ[:(;*....................+@&%%%&&+.......................................+@*=>-!~|1[IJwNwOPQ}:_!;-=%+..................................",
|
||||||
|
"..&*>;_b:f7g5iiiiii<iih7bbac=%..........@**,0fiqTTTTqgb0-*#@............@%$=90bgjqqpfd;3*%@.......@#=3agjWTTTTTUWZWWZWWWWqjgb9%.....+%$=9399ccc39-3-3-39c9-,*&......+%*,90_fiqWTTTTTWqieba3,*@.........+&*,;bgjUWjgd;=*@.........+#=9dfhhmpqWqWWqWqqjgbac,*&+.......................................@%$=-c_df4ioqqomhf|a03=$%+...........++@%%##*#%&&&@@+..........+&*$>30be47k774eef4hhkeba3#......................+@++............................................@#>,30defimqqqpi7e(a0->*&...................................",
|
||||||
|
"..@#=3abb}ef7474477777feba09=@..........@#>9afpqWUqUqifc3>%@.............@#$,cdgpqjifc3>*&........@*>cdfpqqWWWWqZoZoZZZZZopgb3%......@*>>-9-3-,,,>>>=-9;93-$*@......@#$>90bfmoqqUUWWqoi7dac>$@.........+%*,cbiqUWqgbc3*@..........&=cdeklVnZWWqZZZooifd;9>*@........................................+@#$>99abegmpopi4ed~33=#@..............++@&@&&@+................+&#=,9ade444eeb|e4774edc3%......................................................................+%*>330de4imjnmh4bda3,*#@...................................",
|
||||||
|
".+&=-;)/^rrzrQ^QrKrrKrr^])!;-@..........%=-!:rtGvvvDGyQ{!-=&.............@*,9!{rxtyP^|;3=&........&>3~:rxtGGHHGHGHHHHGHHHAtKF'*......+%$------->======-;--=##@......@#,-')FQstGGGvGGAAsK/{~-=@........+@=3c{IxDEEGx[);,%.........+*-~FrsyBHGGvHHHBAxK/{';>#@.........................................+%*,;!)]/rzsKzK/]_~;--#+...............+@@@++...................@%>;!){]/^///FF/^/^/F{~;#.......................................................................&*--;')F/zsszKr/{)~;-*#@...................................",
|
||||||
|
"..&$-;)_]]///FF///^^//F]);;-#+..........@*-;)^stCBCCtsr);-$&..............%$-;'F^zz/{';-%+........&*-!)/rssxsxxxyxxAttxxssr/(;#.......+@&*$$$*$####%&%%*#*%@........+#=-;~_FrssxsxsxssrF])!-#@.........@#,')QyGGLvs/);,#+.........#-!]/zsxtBBBAAyssrF{!;,#&...........................................+@#=;;!){]FFF]{~';->%+..........................................+%=-;;)){{)))))){)))!;$@........................................................................@#>--!~{]1FF]{)!;->%@.....................................",
|
||||||
|
"..+&$=--,;-;;;;;;;-!!;;,-=*%+............&*=-~][^QrQ^F_;,*@...............+@#>,;~~~!-,*&+..........+%=-;'(({{{{]]]]]]]1{()~'-*+............++.@+...+.+.+.............+%**,-;!(({1{1{({~;-,=*@...........&*,;([58P52_-=*@..........@#=-!)1]F////}/1(~;-=*&...............................................+@##=>-------=$$%@..............................................@%$*=>>-->>->,--=>=*&..........................................................................@%$*==>--,3--->$#&+......................................",
|
||||||
|
"...@%#%%%%#%#%%#**$***%%%&@+.............+%$=;_|:}12|~;>*&+.................+&*>>-->>#&+............+&#>,-;--3;;;;3;-;;;--->*&+........................................@%**=--;-3--;---=**%&+...........@#$,c(}[2:_;,*&............@#>-;!__(|(((_~';,=*@+..................................................&&##**=***#%@+................................................+@%%%#&&##%###%$#%&+............................................................................+@&#%#*$***%&&@+.......................................",
|
||||||
|
"......++++++..+++...+++..+................&*$,caa_da09,$&@...................@&*#**%%&&..............@%#*$=,,,,=,,,-,>=>=**%&...........................................@%##*$=,,,>===$$%@++.............&*>9adbbdc9>%@...........+@%#>,339;000cc3-=$%&......................................................++&@&@@&++........................................................+.+@&&@%@@@@+.................................................................................++@&&&&@@+.........................................",
|
||||||
|
"..........................................+&#=,,99399,=*&.....................@&%%%&@@...............+&%#***$=*>=*******#*&@+............................................+@&#****$***#*&@+...............@%=,00bdac=*%@............+@%*$>,,3>,,,,>**&@..........................................................+..................................................................++@+.........................................................................................+@+.............................................",
|
||||||
|
"..........................................++&%=>>-,=>>*%+......................+@@@+..................@@&##%#%%#%%%***#%#%&.................................................@%#%%####%%@.................+&#=-;~~';=*%+.............++%**$$>==>=**##%@..........................................................................................................................................................................................................................................................................",
|
||||||
|
"............................................+++++@@@+++..........................+......................+..+.++.++++++.+.......................................................++.+..+...................+++@&%##&&@+...................@@++@@+@++..............................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................+...++...............................................................................................................................................................................+@&&&&@+.......................+@&&@+..........................+@%%%%%%&@+.................................................",
|
||||||
|
"............+@&&&&&@@+......................................................@&%&%%%%&@+...................+&&%&&&&@++....................................................................................+@&&%#####%*####%&@..................................................................................+@@@@+..............................................................................+%##==,,>$$%@+.................+%%$=,3>$*%@+....................&%$>3-3333=$##&@..............................................",
|
||||||
|
"..........+@#=>333,>*#@...................................................@#*=,3--33=*%@................+@*=>-3333==#@+.................................................................................+%*=,3,39;9c;9c9;33$%+.............................................................................+&%***$*#@+............................................................................#=,ccddddac3=#@................%>9cadddac3=#@+.................+*3caddb{b(a0c,=*&+............................................",
|
||||||
|
"........+%=,;~{]]]{';->#@...............................................@#=-;){]{F]]);->%+............+&=-;~{]FFF])!-$*@+.......................+&&&@+................................................+%$,;')]F/^^^^r^^//F{~-#...........................................................................@%$>-;'~!!;,*&+....................@%##**%%@+...........................................%>']/rsxysr/]'-$%+.............&,)Frzxxxz^F);$#@.......+@+.....+$~]/zxyxAxysrF]~;,##@@@@@+.....................................",
|
||||||
|
"........%=-;']F/r/F]~;-=#@.......................@@@+..................@#>-!)]Frr^//]);-=#@...........&=>;!{]//^//])!-=*%@..................+&%%##==*#@.............................................@#$>-;;)F^rrzzszzszzr//{;=+.........................................................................@&*,-!){{])!;-=@.................@%#*$=>,>,==##@........................................+%-)FrstBAAxrF);,*&+............&-]rzxBBBxzF]~-=*@..+@&%##$#&...@,{/zyBBCCBBxsr/]~-,*$#%%*#*&..................+@@&@+...........",
|
||||||
|
"......+&*=,-!)(]]{_);-,=*@...................+@&@&&&@+.................&*=,-!){]]F]_);-=$%@..........+&$=-;~{|F1]|)~;-$*@@..................+&%#$$$>*#&+...........................................++%$==-;!)]F]FF/FF/}FF]_'-%.........................................................................+&#*>-;!)))~;=*$@................+&#$$=>=,,-=>**%&.......................................+%=;)F/rrKr/F_'-=#@++....@@+....@$;{F/rKr^/|!;=*%&@+@%%%#***%+..+$;)]/rzzzzK^F]_~;,*#%%%#$$*%.................@@%&%&&@+.........",
|
||||||
|
"......@&#=-;!_(|||1(_;->*&+..................@%#*$$*#&+...............+%#>-!_(||::11('-,**&+.........@%*>;~((|::||((!-,$#@+................+&%***===>*#%+..........................................@%*=,;!~((:}}4}44[}4}}:1!-#+........................................................................@#*$,-!_|||('->%&................@%*=,--;;;;--,$*&&.......................................%=;_|2QI<<}|_;=$%&@.@+@&@%&@...+$!(}[QI<[:(!->$%%&%##$==>>=#@...*!(:[QQIIIQ[}|(~;,>*$$$*===#+...............+&##$#$#%&+........",
|
||||||
|
"......&*$-0dbeeefeeebd;,>*@.................+%*>333,>$&@..............+%*=cdbefeef4eeba;,=%@.........&*=9abeee4444ebbc9>*&+...............@&*>339cccc>*%@.........................................+%$>90abefgipjjjjijijipigb;#........................................................................+&#=-cabfgiigbc-*#+..............+&#$3;adbdbdaa;3>$#@......................................%=3ab7ipmphfd0,*#&@@&&&##$$*+...*cbfimpmi7ba;=$##%#*=,9cc09=@..+$0be47hhkhh77eedc->**=339cc-&..............+&**====$$%@........",
|
||||||
|
"....+&#>-0|7klhklkklk4d03=*@...............+#*3caadac,$#@.............@#$90ekkkkhklVk4edc3>%+.......+%*-c|khlkhkllhk2bac>*&..............+&=>;ad(bbedc3$&+........................................&*=3_e7hlmoqqqTTTUUUWWqqpgd,@.......................................................................&#>30degmqUqjgb9,*&+............@#*=3!be7kkkk4ebac,*%@.....................................#,0beinZZomke0;,$##%#*>>333,*..+>_bkmoZZXh4b0-==*=>3;adb4ebc#..+>dek<lllVVVllhked0-33;0d|eba=..............&*=-0'a0c=*&+.......",
|
||||||
|
"...+#=-;)FztACCCBCBCAxrF)!;$&............+%$-;)Frzzr]~;-$%............&=-)/sBCACCCCCCtz^]~;=@.......@=-;{rtABCCCABCAyz/]~-*@.............%=;~]rzzssszF~-=@.......................................+#-'{/sACHHvLEuuTuuuuEEEvvx[;#.......................................................................%>-~{/stHDuEuw^{'-#@..........+&=-;~{^stBCBCCAAsr]);,$@...................................+*;{/stDEEDHtz/);-,---;!){FF]-@.+-FzxHLELvAs^{';;;!~{FrzsAyz],..@;FsxACCCACCCCCByrF{))F/rsxsr;@............+*-~]zssrF)-=%.......",
|
||||||
|
"...@*-!)F/sACBBAABBCCAz/]);-#@...........&=,;!]zxHAxr{;->*%+..........&=;~FztABABABCAAs^])-=&.......&$-']ryBBACBCHGByz/])-=&............&*-!)/zyAAtsz]~-=&..........+&%%%##%&@@...+@%%##&+.......@$;']rAGGvLvDvEEEEEEvvGGvtsF;%.......................................................................&=-;)FzyCDEEDtr]~-=&..........@*>-~{FzxBBABBABBts/{~;=#+...................................#;)FzyBHHGHyz/);;--;')]F/rr/;@.@-]/stGGGHAsr]~;;')]/zsyAyyz{>+.@-FrytAACCCCBBBAsz/F]/rzsAAxr;@............&=;)/sAAx/);=*@......",
|
||||||
|
"...@%>;!(][rKrr//^rKzQ/()~->&+..........+&*=-;(Q6wwP[~;,*#&@..........@#>-~{/^^/^rIzK^F)!->*@........&*,;)F^^rIKJwwKQ]_;-*%@............&#=-~]/rrr^F(!-$%+..........@&%#%#*%%%%&@@&&%&%#%&@......&*,;)}6wNNw6IPwSNSwOPKIIQ4:~=+.......................................................................+%*=-'(}<OwNO51~->%@..........@#=-;){/rKr/^^rrKr/]);-=&............+++.....+..............+&=-'([IKPKI[F~;>>=>,-~(]F[^F-@.+$;_:QKPKKQF_~;--;~)F//^//F{;$..@=;)]F^QKJwwJK^/F](_({F//r^/(=+............@#>;_F^^/(;,#%+......",
|
||||||
|
"...@%*-'(12QQQ221}[Q[[}1(~-*&+.........+@#$>-c(7OSM64(;->*#%&.........@#*,;_11222}[QQ[(~--*&........+@*,;_|2[2QQIOO84_!-=$#@...........+@*$-!|[IQ[1(~->*&+.........@&##*$=$$*####*###$$>$$%%+....+&>3_b5MNNM5<5YSNSO6I<Q2:1!-*+........................................................................+%$,9~1<6SwO<1;-*%@.........+@#>-!~|}QQ[2222QQQ}|~!-=%+.......++@@@@@&@@@&@&@@+...........@*-;_|[IQI[}(_;->>=,;_|:}}[1-@.+*,'1}QII[[}(!;--;_(:[QQQ}1_-%...#-;(|}[QPOO8<2::(((|:}2[[[2~>.............&*,-_|221~-=*&+......",
|
||||||
|
"...@#>9adefkhh7e1f7hh74bda3$@.........@%*=,90dfiqWWjgba;9>*##+........+%*,9_be:e447hkfba9,*&........+&*-9abe477hpoqpgbac=$%@............@*=30b4h<7edc3$%&..........&**>-33->==**$*>>,-33,,=#&....+%,cafiqTTqigijUTWqolh77bbc3%.................+++++...................................................+&*,9abijUUjgb0-$%@..........&*,;ab:7kh7fee44hh4bba;=*+......+&&%#$#%*&%%%##%&%@+.........&*,cde4hhk74bd03>>>3adee477f9@.+$,0b4khhh4ebd00cadbf<kh7e:d9#..+#-c_ee4hpqqphffebbdbf477h4e0$............+&*,;ab1bba9>#%+......",
|
||||||
|
"...+*>9abeklVVh74kkVll7eba9=&.......+%*=-9cdbbgpWUWqm7ed~c93*%........@#$-0be47kkkllkk1a;3*&+.......+#*-cd:4kkllXoonhedc9=%&............&*>3_e4khk:ac,*#@.........&*,c!ad(da093,=,3cddbddac3$&...+#-cbfjUTTTjmmqUTTWZnVhk41a-#+...............@&##%&@+..................................................&>,cafiqWUWieac,*@..........@*9'be4kllIk[kklVlk4:ba9*&....+%*>,3333,=,,-3,-,,=*%@........&>9ab4lVVVlk7ed'c;0d|47kh<k49@..*9dekVVVlk74b(dd|e[kllVl7ed;#..+$ca:4klVoqWoVhkk[447k<llhkea$+...........@**9!de44eb'3$#@......",
|
||||||
|
"...&=-~{/rxtCBCBAACCCAyr/{!-%......&*-;~{F^zsstDuEEDHxssr^F{;>@......+&=-'{/zxBBBCCCAsrF~;-*@.......@$-;)/zsABCBHHvHtszF);=*+...........#>;~]^ssyz/{~;=#+........+=;{/zsxAxzr/])~)]zxAtxszr]!$+..+$!1QJwuuTEGHHvEEEEGHCAtyrF~,@.............@#>>---->$*%@..............................................+%-;{FzADEEEtKF);,*+........@$-~]rzyACCAtyxBACCByz^]~-#...&#-;){FF]]{){{]]]]{)';-=%@.....+*;)FzsCCCCAAyzz^//rzxtCCCAxz'&.+-~^zACCCCCyyzrrzstACCCCAsz/(>..@;FrsttBCHvGGHCACBAABCACBys^(=............%,;~]rzyyyrF)-=%......",
|
||||||
|
"...@$-;)]rsABCBBBBBCAAz/]);>#+....&*>-')/rzsxABvEEELHBAxyzr{);#.......#=-!]^stACCBBtxz/{~;,=%.......&$-;)/zxBACCBCBCBsr/);>*@...........&=-;{F^rr/]~;-*@.........&>'FryABBBAxr/F){/JGLHCBts/)-%..+$!]^svEEEuvBGLEEEvGCBBAxzF'>@............@#>-;;'~;;->=#+..............................................%-;)FKAvLEuAzF);,#+........@#-~]^syBBCByxtABBCBxsrF~,%...&=-!{/rrr/FFF/F//r/F{';->#&....+*;)FrxBCBCBAxszrrrsyABACAys/;@.@-]^stCCBCAAxszzstBCACAAAsrF)=+.@;/sAACBACCCCCCCACBBCBCAAxrF~$+..........+#-;)FryBBtzF);,#+.....",
|
||||||
|
"....@**,-'{/IrrQ^^rI^/1~;-=#+.....@%*=-~1/QQQIKONSNwJPIrQ[2(!>%.......&$=-!(/IrKKzr^/F(;-=*%@.......@%>-;|2[rIrKKKKI^F]);,$%+............%$=-;~)~;-,*#+..........@*-)F^IzsKK^F|)!!([PJJKKr/{!>&..+#=;_25MNNwJJJwNNwwJKzQ/F{~-#............+&*=,;!!!;;->#&+.............................................+@==;!:<Owww5}(;-*%.........@%*-!(]/QrKr^//IrKIr/](!-#+...+&=-~{]}F1{|{1]::}}|);-,=*%+...+%,;):QPJsKr^//}FFF//rKzKr/])=+.+$'{FIKzKKr^/}/2/QzKzKrKr/:~;*..+,)F/^^rIrKKKKzKzrKrrKzK^F_'-&..........+&#=-;)F/zKrF~-,*@......",
|
||||||
|
".....+#*,-!(|2}}}}22:(;-=*#+......+#$,c~[568688RNNNSYO8666<}_-%.......@*$-~|}QIIIQQQ}1(!->$&+.......@**-a:<5<Q[[QIQ[21(';=#@.............+@%==-,,>>#&+............#-9(2<8OJ8[:(_~~_1<5IKQQ[|;,%...@=-c(}56O68OYNNNSOPIQ[2|(;-%+...........+&*,;!(1:1~;=*$&..............................................@$,-a|<RSNY5f~;,*&+........@&$=;~(|[QQQ[22[QIQ[1(~;,%+....%=-_:2[[[}1::|}[<<41~!;,*#@....#>;(1[Q5IIIQ[[[}:[[[QQQQ[}(;>..+$;|}[<IPK<QQ[[[[QQIIIIQ[[:(;#..+$'(:}[QQIQQQQQQQQQQIQQQ2|~-*&..........+%$>-!(1QI<Q1~-*#@......",
|
||||||
|
"......&#>=3~a|:e2f1d_0->>#&.......+%$,0eiqqWWWWUTTTTTWqWWqjibc$.......@*=9_ek<hhh<hh7fba;,$#+.......@$=3agjjih7khhhhfbd0-*%@...............@##***#%@+............+#-cdeioqqoifbdaadb7hkhlh7ec-&...@*>9afh5lnoqWUTTUqmhk7ebb9-%...........@%#>9ad:777ea;=#%+............................................+@*,;dfiqTUqpgdc-*%+........@&$>30_b4hhh<77khhh4bdc-=&+...+%=;d7hhhhk74ff7ijji7bda9=$&....%>0bfhhllh5lkh777hh<hhhh7fb0>..+>dekhllmmlklkhlklllhlhlhk4b0$..+*cd:7khhlhlkkhkhh<hhhk74bac=@..........@%=90dfginpifa9=$@......",
|
||||||
|
"......+%*,-0ade4eeeba93=*%+.......@#,3agpZUWWUUTTTTTTUWUWWWif0*.......&*,0bklVVVlVlVVkebc3=%@.......&*>9dioonlhkllVk[edc9>%@................+@&&&@@+.............+#3ab7mZWWqmhfbdbbekhVVVll4d3#..+&*-9dehlVnZWUTTTUWnVlk441a3#+..........@#>9~beklVlkea3$%@............................................+&>3abgiqTTWp7ea9>#&........@%#=9!beklVVllllVVlkeda9=*+...&=,0|kllVVVVhkkhXqZjl741ac>#+...%-aekVVVVXlVVVVVlVVVVVlllked,+.+,bklVVXlXXXVVXVXXVVXV6Vlll7b>+..=0b4kVVXVVVVllllVVXVlllk4bc3%.........&#>-ab4kmoZZohbc>*%+.....",
|
||||||
|
"......+&$-;_{F^zzr^]{~;>=%@.......&$-~FKGLEEuEEEEEuEEEEEEvvAk(>......+*-!]rxBCACBCCCByz^{'->&+......&=-!2JDvGBBCCCCAsz/);-*%................+@@@&@+..............%,!]rsHvELvHxsz^rrsACCCCCAs^'$...%,;)/ztACHvEEEEEEEDHCBxsr]~,@..........&=-)FrsABCCtzF~->&............................................%$-~FrxGDEEEGxzF);,*@.......@#=-~]^stBCCCCCBCBBxs^{~-=@...%-!]ryCCCCCCCACHvDEGHAAsr])-%..+$;FzxBCCCCCCBCCBCBCCCCCCByzF;@.@;/xBCBCCBCCCCGHHHHBCBCCBCBy^;@.@,(^zxCBCCCCCBBCBCHHHBCCAsrF'*.......&%>-')/zACHLLEDxQ{;-#@.....",
|
||||||
|
"........@#,;;){F/F])';-$%&........@$-!{IxtBHGGLuEuEEEvGHGGGs^)=+......#-;)rsABBABBABAsrF)!-#&.......&=-!FztBABBABBAyz/{);=%......................................@$!{/stHvGGAyzrr^rsAACBCCBs/)$+..+$-!]rsytCHGDuEEELvCCAAsr]!>@..........&$-)FzyBCHHBzF~;=#+................+@&&@+....................+%>;']rsyGDGGAszF~;-*&.......+#=;~{/zyBCACACBCCByz/]~-$&...%-!)^yACBCGHCCBCHGvvvHHBs/{!*+.+>;]/syABACBCBCCCCCCBCCCGCAz/;@.@-FzxBBBCBCCCBCBHCHCCCCCCCCAz!@.+-)FrstBACBCCCvCGHBBGGHCCyrF!*.......%,;;)]/sACHLvLDy/{;,*+.....",
|
||||||
|
".........+%*=,-;---=>#&+...........%*=-~1:}}[2<ORNNRPQ2[}::_;-&.......@*=-~]F/^^r^^/F]~;->$@+.......+#*>;d:2[////FF]_!-=*&+......................................+%>;_:QKPJKI[2{(((]/QKKKKI/~-%....@#=-;){][[IJwNwNwJKK^/F|!-%...........+&*-~][PwwwK['-=%@................+@@&&&@+...................+%*>-'1}[4[[<[2]'-=$%@........+%=-;){FQrKzKzKKrQF]_;-=%+...@#=;'{F[IJwwJKKKIPPOwwwJQ:'-%...#=-;){FF/2/Q^QKKKKKKPwwwOK}(=+.+*;~]FF//QrKKKKKKKKII/QIIJOP}-...%-;')]F/2^QPJwwwJJPwwwwJQ1~-%......+&=-;!)1/IKJOSO8Q(;>$&......",
|
||||||
|
"...........&&%*****%&@+.............&*=,3c!_(12<MNS6<:1(a;c-,#+.......+%$=-!((1:1:|1(~-=$&@+.........+%*>-c_((||:((!;==$#+........................................%$-;(}QIIQ[}|(__(_:}[III[:_-&.....@%$>,;!_12<6SNYOPIQ[}|(;>#+...........&*>;_1Q6O65|;>%&................+&######&+..................+&**-;~((||||1(_'->*#+.........@*=;!_:[QQ<IIIQQ[:_~;,$&....+#>,;_(:QKOOPIQQI<I8YSS8<|_;#...@#*--;!((11}[QIPPIII<OYwY5:~>..+%,-!__|:}[QIQQQ[Q[Q[22[<885|>+..@%*--'_(|:[<OwwOPKI6SSO8[(!-%......@*>-'(::[Q<<555[1~->*%+.....",
|
||||||
|
"............+@%%&&&++...............+&$>=,90abfgpqjpgbd093-=*&........+@#$,3c_____0_cc,*#@+...........+#$>99aa_0dac3-$*&&.........................................&$,cdfhhlh7f1bdddde47hlhhed,%......@%*=-30dfgjUUUqplk4fbd0>%............&$=30dfgigfd9>&+................+&$*$*>$*&+..................@#*=9;aaaaaaaac3=$#&.........+%=,;ab7gmmmmpmmii7bac3*%+...+&=39abbginXmlhhhkimWUWqifd9#...+%*=,;0adbe47hhmlikhijWWqpf0>...&=9adb:f47hh77774477777hmigb$...@#$>,30d:f7imjnpmiljWUqjgbc,&.....@%*-cb47hhhhh7efbbc9=**+.....",
|
||||||
|
"..............+@+.+..................@%*>99adbehmnnmkfda93=*#@.........&#**>999c9cc99,$*%@.............@*==--c9c3-9,$*%@..........................................%*3c|7lVVllk742ee47hVVmXlkb0*.......@#$,90bfioWUUWnVlk7e|a9#+...........@%$,c0abbbac,*&................@*>,9c0c93>*%+................+&%$=33393!93-9>$#@@.........@*=0d:7inqZWZZWqZXi7ed03#+...@#>30d|4klmXVXVllllnWUUqp7bc$...@&#*3cad|ekhlVVVVVlVnZWUZpgb,+.+%-9_b4kklVhlk7e4f4kklVVllkgd=+..&#*>3c!b4klVmXXVllXoWUWjhea9#....+&*>cb4hVlVVVl[4eedac3>*#+....",
|
||||||
|
".....................................%>-3;!)FrstCCCAyz/]~;-,$%.........+%#=>--;;;;;;--$#&@.............+%$---;;;;-->=#&...........................................*-'{rxBCCCCCBtyyxABBHHGGGtz{-.......&==;!)/zxvEEEEDHCAysr]~>@...........@#=,c!a_a09c3=#...............@=-;)Frzr/{';>*@................@&*>--;;;;;;-->=*&+........@%-;]/zxGvEEuEEEEELHszr]'-@...%=-~]^zsyCCHBCCCCBHvEEEEGyr{-...@#=-;(FrzstBCBCBCCCHHLEEEGs^;@.+=;~FzxACCCCAxszzzsxACCBCAxz],+..&=,-!)FrxBCCCBCHCHBvEEEDAs2)*....@$-'{ryBCCBCCAysszr/{~!;-*@...",
|
||||||
|
"....................................+%=-;;!)]^sABBCBxz/]~;;,=&+.........+&&#$---->>$$%%++...............+%%#*$$=>-=*&+...........................................+*-;{^yCCCBCCABBABBCCBLLLGAzF,+......&*,-!)FIyGLEELvCCBAsrF',@............+%=,-;!;;--$#@+.............+#>;)Frytyz/)!-=#.................@%#*,>,-,->>$##&+.........+%>!(/zstvLEEuEEELLtxz/]!>&...&>;~]/zsyACBCCCBCCBGLEELtsr{=+...@$-!{FrzyBCCCCCCCCBHLLuLGyr;@.+$;)FryBACBAAszzrzzyBBCCBByz]-+.+%$-;~]^zyACCCCCCCCCvLELGts/)$+...+=-~]ryBCCCCCBtszzr//])~;-*...",
|
||||||
|
".....................................&#*>--!_(FQIKKI/}_~;->*%@............++@@&@%%&+++....................++.+++@&&@..............................................%=,;)/IJJsKzKrrrrrKJJwwwOP}~=.......&#*>-;):Q6NNwOJJKr^/1);*...............+&%**##%&@+...............@#=-;(/KKK/|';,*%...................++&&@&&&@++.............+&%=-!(2<6OwwOwOwOJ<:(~;-&+...+#=-~(F[QKKzKKKKKKKJwwwO<2(!*.....&=,;)]F/IrKKrIrIIKPwwNw6[|-+.+*,;)F[rrIrI/F|{(]:[IPPKIr}];*...@%=,;'|F^IKKrIIKrKKwwNwO<}_;%.....%=-'{/IKKKrI^/}]:F}F|)!;,#...",
|
||||||
|
"....................................+@#>-;!!(1}}Q[Q221(~!;-,*@.................+..................................................................................&*=;_}QPPKIKIQ[[[[IKJwwSO<|!*+.....@&#$,-!_|46RNNYJP<Q[}:~;*+................+@&&+++.................&*>-~14P66<:~;-=%+......................+....................+%*=-c~12<[<<<[<421~;-,*&.....&,;_:}[[QIIIQ[[<866665<}(!,%.....@*,;~1}[QQQQQQQQQIKOSNR84_,+..%-!_:[QQQ[21__~(|}[QIIQQ}:_;#...@#>-!(}}[Q[QQ[QQQ<IJSNR8<:(;#.....&$,;(2QIIIQ[21|(|:}}1(~;-*+..",
|
||||||
|
"....................................@&*-cadbbee4k774febbda09=&....................................................................................................&*=3aehkVmmmmmimiilmjZWWqifd$......+%*=3cabfgjUTTqomkhk7eb9*........................................+&=3cbfiqWqpgba9=*@............................................@%*>,93caddd0daaa;9,=*%@....+#>cb4khllhhk777iqqomh7eb03=&....+&*-0b44hkkhhhhkhhhmoWUqpgb,+.+%9abf<hh7e|da0ade4khhh77f:a9#...&*>;df7kkk4k7k7khhmjWTUjgfd9%.....@*,;dekhlhk7f:ebef7kebd03*...",
|
||||||
|
"...................................+&$,cd:44[kkhkllkkk4ee:da3#+..................................................................................................+%*,cb4lXVXoZZqZoonXXZZWWZphb,+....+%$,cabe7hmqUTUZoXXmVlhea,@.......................................&$>9dehpWUWoi4dc3*&.............................................&#%>=99990c0c399,>*$%@+....&$9d4hVlVVVVlkhhXoWomhk4ba3$&....+#=9_ekVVlklhllhlVlnZWUWol49@..*cd:kllVh4:bddbe4hlllllkkeb0*..+&*3ceklllIlhkklkhVXZWTUqm7e0*.....&*3!b[lVl6VVhk47kIllk4eda>@..",
|
||||||
|
"..................................+%>-~]rsytBACCCACBBBAyysr/)-%..................................................................................................@=-'{^sBHHGLLEELDvvHBvLEEDHtr;@...+%=-~]/zxAGvLEEEELGvGGGHs/!#......................................+#-;)/stvEEEDBsr{!-=@............................................+%#=3-cc00~0'0;;3-=*@.....+*-)FstCCCCBCBBABGvLGAysz/);>&....%>;~/sABBCABACBCBCHGEEELvAs)@.@-(^zxBCBxzr//F/zxACCCBCAtyr(-...#-']ztBCAABAAtACACHGEEEDHxz{=....+#,!]rxCCCCBCCBAAACCCBxs/];%..",
|
||||||
|
"..................................+*>;)/stCCCCBCBCCCCCCCBCxz]!$..................................................................................................@$-!)rxCBHGGGvGvGHHABBHHGHxsF;+...+%=;)/rsAHLLEEEELLLLLLLGx^~*......................................@#>!{/sBvvELGHsr]'-=&.............................................++%$,>----;->--$*%@+......*;~FzABBCBBBAtyAAHGtysr/]~-$+...+%,;~FstAAAyyAtBABBABLLLLvAz)&.+,{/zyAAAsr/]]F^zyCCBCBCCCtsF,+.+%>;]ryAAAyysssyxAABvLLLvCyr(=+...+#=;)^stCCCCCCBBBBCBCAysrF;#..",
|
||||||
|
"...................................%*,!|5JwwwwwwwwwwwwwwwOK[(-%..................................................................................................+&*-;)}rPJKP5<Q[[[[22:}}}:(_-#....+@*>;)|}QJwNNNuNwNNNNwwO<|;&.......................................%*-~1[IOwNwOK}(!-*#+.................................................&@@&#&#%&@@++.........@$-;(F^^^//FFFF2[[[2|)~;-=%@.....@#=-')FFF]]]]]]]]/2IJwNwJQ1-@..*;')]]]]{!;;;;_:QJJJKIKKJPQ($...@*=;)FFFF]]))){]FFQPwNwJI[]!*....+&#=;)F/rIKsKKIrIKKzKI/F(~,+..",
|
||||||
|
"...................................@$=9|IOOYYwYwYwSwOwYOOM84_-#...................................................................................................&$=-_:QQI<Q[2||(_~'!!0c0c9>#+.....+&*=;_|[5OwwSNNNwwwSwR84~,&.......................................&$,;(}<8RSR6[:~-=$%+......................................................+................+&=-!(::(__~___(||(~;-,=*#%+.....+&#=-!!(_';;-;;!!_145OYO52(-+.+&=-;;;!;--==,-c([6OPQQQ<865_$+..+&*-;~__!;;;;-;;~(}<6wY8<:~-&.....+&#=-_11[<PJ666668O6[:(~-*+..",
|
||||||
|
"...................................@*=9agijpppjjjppjpjpjppgfa>%...................................................................................................@#=3a:7hlh7fbd0c033->>===#%+.......&*>3cafgijjjjjjjjpjppgfc=+.......................................@$>;af7ijqjigb0-*%&+.......................................................................+&*,;00_a9,390000a0;3=>$#&&.......&%$,99cc9-,=,,-3cabgimigea$...&*>,3,-,,>**>-3afgii7f47iiga#....&#>390099>>-=,-90bgiipgfa03&.....+@%>,;adbgjqZqqWqZqjgba9,%...",
|
||||||
|
"...................................+%$,3dbffg777g7gg7g7gfgba3=&...................................................................................................@*>-aehlVh4eb09,>*%&%&&&&&.........@#$,-0affg7g7g7g7ggffb09*........................................@%>3db4hmpihedc->#&.........................................................................&#>>999999,9,3,;99,>>*&@+.........&*=--9,->>>*$>-90cdfffba3*+..+**=>>$=**$$=*33abfbebbfbbd3#....+%*,93>-=>**>=,330abffba03=@......@#$=30aehoZWWZWWWZoibc9>#+..",
|
||||||
|
"...................................&*=39ad12F4///F///[F::1dac>%..................................................................................................+%=-!]rytBxr/]_9,#%+................@#=-9'_1]}/[//F2FF1:(d!9$+.......................................%=-!]/zsxtys^]~;=*&........................................................................+&#=>-;;;;------;--,==*&++.........@#$--->===>===--;~a(b{(!3%....%*==-=,==**=,9ca_|{]]{|1da,%....+%*=>--==>=*=,-;;'ad(1{_';-&......@#=-;_(FIyGHHHHHGCxKF~;,#...",
|
||||||
|
"...................................+&#=-;!~){())))))({))~~;--#+...................................................................................................&*,;)FrszzF{~;-*%...................+&$-;;!~~'~)))))~)~~;;-#+......................................+&#>;)F/zsysr/);-$&+..........................................................................+%$>,>->,=,=>$$$*%%%+.............+%*#*#$**=$**=,--;;';;;>&....+&%*%$##%&%#*=,-;;''''!!!->@.....+&%#**%%@&&#%$->-;;!;;;-,#+.......+%>,;')F/rrrzzrrr^])'-*+...",
|
||||||
|
".....................................+@%*>==-->===,-->>,===*&+....................................................................................................@%#=-'){{)'->=*++.....................+@%#==,>=>>=,,>,>=#%&+........................................+@#=-;'({]1)'-=*&+.............................................................................+@@@&&&@&@&&+.++.+...................+@@@@&&@@#*&%*$*%%@........+.++.+....@%#*$*#***#$#@...........+++...+.+&%&%*$*%%&&+.........+&%#$>3;;!;!!c!;;-==#@....",
|
||||||
|
".......................................+@@&&#%**#*%%%##%#%&@@.....................................................................................................+@&#=-';!!;=$%@+........................++@%##$*%$##%%%%@.............................................+%*$--;;;-==%@......................................................................................+.....................................+++++...+......................+&@+@++.+++......................+.++..+................+@%#*=>=======**&@.....",
|
||||||
|
".........................................+++@@@@@&@@@@@@++...........................................................................................................@%*,,,=*%&++............................+@@@@+@@+...+...............................................+&&%%#%*%&%@..............................................................................................................................................................+.......................................................+@&&%%##%%%%@@+......",
|
||||||
|
"...............................................+..++...................................................................................................................++@@@++.+...........................................................................................+++++.++..........................................................................................................................................................................................................................+.+.......+........",
|
||||||
|
"..........+++@++++.............................@@@+@@@+@+....................++++@@++.........................+++++++..................................................++@@&&&@@&@@++...........................+.......................................................+@+@@@@@@++............................+++@@@++....................+++&&&@++.....................................................+++++++................................+++++++++..................++&#$$$#&++..........................................",
|
||||||
|
".......+&*>=-,-->$*&+........................@#*$=>----=*#+...............+%*$------>*%+................@&%%#*$$>>>>$*#%@..............................................+@#=,-;!;;-,>$#%+.....................@+@@&@@@@@@&&@...........................................+##>>,--,==$*&.........................+%*>>,-,>>$#@................&*>--!;--=*#@................@&&&%%%##%%%%%@+...............+%*==----=*#%@.........................+&#*$---->>*#&@.............+%$>-)~))~;>$*#&+.............................+........",
|
||||||
|
".......+#*-;!~';-=$%@+......................+@%=,-;;~'~;**@...............+*=-;!)));-=*@...............+&%#*$=,>>>>>,=$##@..............+++++++++@@++++...............+&%=-;'))({)!->$&@...................+@%%&&%%%%&%&&&&++..............++@@@@&&@@+@&@+............+%*,;'~!;-,=*#+........................&#*--!~;--=$#+..............+%=-;')~!--=*%+...............@&%&#$%%#*#$##*&+..............+#*,-!~';-***&+........................+%*=>;!';;-=$%@.............@#,-!)]1|)';=*#%+................++++@++.++@@@+........",
|
||||||
|
".......&*=-;~(1_;-=$#@......................@%$>-;;((1~;=#@..............@#*>;!((||_;-*#&..............+&$$=-;;;;;;;-,=*%&..............+@&&%%%%%&&%&&&@..............+&#>-!(|221|';>*#+..................+&##*#*#**##$####%@.............+@%##**##*##%%%&+...........@#*-!(1(~;-->*&......................+&%$=-;((_!-,*%&.............@%*>;_(||(!-,>*&+.............&&%#$$*>>$*$*>$*#%@+............&*>-;~|(~-=*$#%+.....................@&%#*=-;(1(;-,=#@............@#>-;~|}[[:_!-=*%@..............+@&%%&&&&&&%&&&&&.......",
|
||||||
|
"......@%$=90deeba;,*#%+...................+@#*=3ca_bbedc,*%+............+&$=30abeeebc9=*%+............@%#*>3;aaaaaaaa;3>*#@............+&&##***######%%&+.............@%*,;abe474edc3*#@.................@%*=>>>=>>,,=>>==>>#+..........+@%#**>>==>=>==*$$&+..........@#*-abeb_a0;,>*@+...................+%#*>,;abeba;3>#&+...........@&*>3abeeebda3>$%+............+%#$=3-3-3>3-33,,=>#&+..........@%*=3ade:dc9=$*#@+...................+&%#$>3cdbeb_c3=#@...........+%*,;ade77kfbd03=*@.............@%%%#$*#%%#%####&%@+.....",
|
||||||
|
"......@$=,;de4k4bdcc,*%+.................+&*=,ca1ee444:a3>%+...........+&$=9~b}7khk[b~c,$#@..........+%=,99dbe44eeee:bac,=#&..........+#*=>,-3-,,==,,-=$*@...........+&*>3_b2khlhk4(c3*#@..............+%*,30caaaaaaadaaaacc>#........++&#=>3ccaaaaaaac93,,=#+.......@%$,c(4444e|dc3=*&+................+&**,9ca(ekk4|a9=>#@..........&#>-9a{4khkke|d93=*&..........@%*>-ca1bd~aa_dbdaa93=#+........+&#>3;de[7eb~ac,>*&+..................&%$>3;a(e4k4ea;3=&..........+&*,9a14khllk41d03=#+...........&*=>,,,,=*>>,,3-==>*#@....",
|
||||||
|
".....+&>;;)FsxBAxsr/{;-*@...............+#=-')FrsAAtysr]!->&..........@$>;~]rsABBCCAsr]~-=*+........+%>;)]/zxACBHHtAAyr/);,*+........@#-;~){]FF{~~){]F{;-=&.........+&=-;{^sxCACBtyrF);=#+...........+&*>;){/^rrrrzrrrzrr^/F)-@....+&%$$--!~{F^^rrrr^/F]]{)!,%.......%=-'{/syAtAxz/{);-$%+.............@#=-;~]rzxyBByr]);-=*+.......+%=-;)]rsyCACAAyrF);-*@........@#=-!)/zyyzzrrzsxsr^F{!,#@.......&$,-~)/stBAssrF);->#&+..............+%=,;!{/zsxAAyz/{'-#+.......+@#=;~FrsACCCCCBxzF)!-#@........@#,;~){{]])!!~)]]]{)~;-=&...",
|
||||||
|
"......#--!)/zAABBAsrF)-=&...............%=-;)F^stBAByz/{'-=%+........&*>-!{/sBACCCBBAz/);-*&.......@%*-)]rzyHvLLLLLHCAsr]~-=%........&=-'{F^rzr/]{]/zz/);,*&........@*=-~]rxBABBBBys/{;-#&...........@%=-!]/rzzzzssssszszzz/];#....@#=,-;~)]/rzzzzzzzzr/FFF)!>+.....@#-;'{/zyABCByz/]~;-=#@.........@&##$-;!]^stBBABxrF);-,*&......@#=,;'{rstBACCCAByr]~;>*&@.....+&=-!)FryttyszsxyAxsr/F)-=%......+&*=;'{/zACBBAxzF);-,#&@...........+@#*--!)/sytBBByrF);-=&.......@*=-')^sBAACACBCByr]~;-#@......+&>;']F/rr/F{)]//r//F]~;>#...",
|
||||||
|
"......&*,-;)]^rrIr/F_;=*&..............@%*,-!)]/rKzr/]~;-*&+........+&#=,-~{/rKzKzKr/}{!-*%+.......@#*=;~]}QPwwwNwwOJI/|!-=&@.......+&*,;!)]}/}])')]}F(;-*%+.......+&$=-;)]^rrr/^^FF(;,$%@...........@%$>-']}/[Q[/^Q/[[^[/}:_;&....@#*,--'~(]}/[/[/[/22F:|();*......@#>,;'(]F^KzK/F|~;-==*%+.......+&#*$>--;)]/rrrI^/|);->$%@......@&*=-;~]/rIzKzKKr/]_;-=$&@.....@#>,;~(]^r^^/}//rr^/F|)',*&.......@#$=-')F/rrIr/})!-=>$#&+..........@%**,-;)]/rrrr//(~;=*%+.......@#*=-~{/IzKrKzIzI/F~;>=*@......@&*,;'_{]2]|)~){F2F{_~;>*&...",
|
||||||
|
".....+%>>;!_|2}[[[[1_-,*&+............+&$>-;~(|}[[Q}|_;-$#&+........+@#>-!~|}QQQQQ[[2:~;=$&+.......+&$,;_(:[<P6JOOOPQ[|~-=$%+........&*>;!(|22}|((((||);=$%+.......@&*>-;_12[Q[Q[21(~;$%@+...........@%*>c(}<<55555<555<555<bc*...@%*,-;~~14<<<<<5<<<<<<4}:_!>@....+%$>;;__:}}QQQQ}|(!;-->*&.......@#*$-;;!~(1}[Q[[21(~!;,*%@.....+&$>-;'(1}[Q[QQQQQ2|(~;-*#@.....&*=-'(|1[[[[}2}[[[[}1|_;,$%+......+#*,;;_|}}QQQ[21~;;,=*#@.........+&#$>-;!(1[[QQ[2:(!-->#@.......&*>-;~(}[QQ[[[QQQ[|~;->*@......@#$>;_(|:}}1(((|:}::(_;-=&...",
|
||||||
|
"....+&#>3cddb:f7k77fb0-$*+............@%>9cabbe4777fda-=$%@.........@%*3;dbef4k47444f1dc,$%+.......@&$,;dee47hhihihh4ed0-*#%+.......@*=3cadee77fbbbbbba;=*%+.......&#=3cad1f4<7<47bdc9=%&+...........@#*9agiqqqUqUqWqqqqqqUqgb*..+&#>9adbfijjqqqqqqqqqqqjpgfd,&...@&*-;aab:f477hk774ebdac9=#+.....@&$,3;adbbe74h<474fbbda9>*&.....@#,9!db:7477447k7h7febac,*&....+%=3;0bee4h4h44e7777eeedc-=%+.....+@$$-cdbbe44k774fbda;3=*#+.......+&#=-30abb74<k77ebbdc->*@.....+@#=-0_b:477[7444h77ebba3=&.....+&$>-0dbef77feeee474ebba;=#...",
|
||||||
|
"....@%=3adee44k<lVlkedc,*%+..........%*=-0db2kkkIlk4eac3*#&@........&*>cd1e7Illlhk4k7eb03=#@......+@$=3ae4khhklVVVVh7edc3>#&+......+%*,cd:e4klkk[444e1dc,$%@......@%=30d144khlVVVh71a;>*%@...........@*,3agoWUTTTTTTUUWWUTTTjb>..@#>3~b47hpZWWWWUUUUUUWWZnXhea*..+#>3abe47kkhhhllVlhh774eda,#+...@*>-adee47kklllllhhkk74edc3$@...+#3cde47khlllhhkllllkk74ba3$+...&#,cde4khllllllh5lllhh471a9=%....+&*=30d|e44k<lVVkk4ebdac3*&......+&%=3cdbe2kkllVlk44e|dc3=#+....+%=30d:47kklkkkhklllk4eda3#+.....&*3a(e4[hkkk7[4kklkk4eba3#+..",
|
||||||
|
"...+#,;)FrzsxAABCCCts/]~-$&........+%=-'{FrzyBBCBBBxs/]~-,*@.......+#-']rsxtBCABCCABxsr]'-=&......+%,;)FsxACCCBCCCBBxs^{!-=#+......&=-!{/zstBCCBBtyyyz/{;-=@.....+#,;)FrzyABBCBBBBxz/);-*&..........+#-;)[sGvEDEEEEEEvLvDDuuw7;+.#-!{ryAHHGGvvvvvDDDDLLLvGBBsF-+.&,!{rxBHHGGHGvGHGGGGGGAGs^];$+..%-!{rxBHHHHGHHGHHHHGGHttK/'-#...#-)/ztHHHGGGGHHGGGGvvGHAs^];#...$;~FzyHtvvGGHHGHHHGGGGHts/);#....&*,;)/rssxABCCBCBBxysr/]);$+....+#=-'{FrzsytBCCCCCtysz^F);,&...+&=-~]rsxAACCCACCCCBBByszF),&....@$-~FrxxACCCCABACACABysrF'-&..",
|
||||||
|
"...+%-;)FrsyBCCCCCCCsrF);-#+.......+%>;)]rzxACCCCCBByrF);-$&.......&=-!]rsyBCCCCCCCCBsr]~-=&.......#,-)/sABCCBCCCCCCAzr]~->%@......%=-~]rsxBCBCBCCCByz/{!-*&......%-;)FzsABCBCCGCByz^{',$%+..........&-;(/stGLEEEEvHBCCBAHBAx/-@+#-~FPtvLGGCHBAyyxAtCCCCCCCAs/,++*-'FsGGLLLLELLLLLLLLEELutzF),&.+*;'/sGGLLuLLLLLLLLLEuEEExr]!=+.+*;)/JGGLLLLELLLLLLLLEEEvwzF)=+.+$;{/JGLLLDELLLGLLLLEEuEDwr{;*+...&=-']/zsABBCCCHCCBBAxsz^]!,%....@#,;)FrzyxBCCCCCCCCBysz/{!-#....#=;~FzsABCCCCCBCCCCCAAxzF)-%...+#>;)FzyBBCCCCCCCCCCCBtyzF),&..",
|
||||||
|
"....@*-!{}/IKJJwwwwOI}_'-=&.........&$=;(F[IKJwwwwOPQ}(',=#+.......@%=-'][rKJJwwwwOPI[{;->*@.......@*=-)/QrKJwwwwwOPI2{~;=$&.......@*>-)]/QKJwwwwOJKIF{~->#@......@*-!(}/IKJwwwwwJI}{!-*&@...........@*,;~2QPONNNwJKI/[[[rIK/(=++&=-)[8wwwJKI/}]1|1:[QrKKIIr})*.+&>;_[6wwNwNNNwwwNwwNNNNS6}(;=@..&,;_[8wwwwNNNwwwwwNNNNNS52~-%...&=;(QOwNwNNNNwwwwwwNNNNw5}_;%...%-':QJwwNNwNNwwwwwwNNNNw5{~-%....+%*,'{/[IKJJwwwwwwJKK^[]~-$@....+%*,!{F[QKJwwOwwwwJJI/[]~-$@....@#=-']/IKJJwwwwwwwJJKr/F_-$+....&#=-)]^rKJJwwOwwwwJJzI/F(;$+..",
|
||||||
|
"...+@$>;(}QI6YMNRNRY52(;,*&+........@%-;(2[<6YMNNMN65:(;,$%@.......+%$,'|}[I6OSSNNS8<1('-*#@.......@*=-!:[QKJMMNRNN6<1(~->&@.......@%*-'1}QIPOSYMNM8<:(!-=#@......@$>;(2[IPOMNNNMY5}(;,$#@...........+$>-a1[<8SNNS8<Q[::}4Q[2;*..&=9_f8RwR8[}|_~';'~(}[Q[QQ[|;%..&*-0|<688OOYO8886888NNNY5:~;*@..&*-a2<68OOOOO866886YNNNY5|~,*...&=-~1566OOOYO868688OSNSY51!-%...%=;_2588OOOOO88866OMSNNO<1!-#.....@*=;(}[<6YSRNNNNSYO5Q}1~-#+.....&$,;(}[<POYRNNNNYOJ5Q[|'-#+....@%$-'|2[IKOYSSYYNSOOPQ[:~-#.....+%$-!1[QIPwYNYNYSSYJIQ[:_-#+..",
|
||||||
|
"....+*=;d:7ipqWUTTTqifbc9>&+........@#=;de4hjqWTTTTqjeba-=#&.......+&*,0b47hpoWUTTTqieba;>$@.......+%*3a|44ipqUTTTTjifba3>&@.......@%*3a:fhhjqWTTTTjifba9=#@......@*>cde4hmoWUTTTqigbc3$%@...........@*=9afgmjWUWqpi77fe47k7bc%..&>cdgpqWqmgeba99-90def7774fb3#..@*,cdfgg5i5mgggffggijUWqieac*@..&*-cdf7hhi5mi77fgggiqWWjiea9#...&$-9dfg5ilmmi77777giqWWqgfc9#...&=3abekhi5mmh77777gjqUWjiba-&....+&*>cdeehpjqUTTTTTqjikfb_3#......@*,;de4hmoqWUTTTqqji4fba,#.....@%*,0be7hpoqUTTTUWjmi7fba,#.....@%*3a|f7lpoqTTTTTqqph74b0,#...",
|
||||||
|
"....+&>3cbe7mooWUTTWjl71c3>#+......+@#>3!be7mjqWUTTUoi71c3=&+.......@*=;db4hmnoUTTTWmh71a3*#+......+@*,9db4kmoqUTTUqmk4103>&+......+%$,cde4hXnqTTTTqmk4(c3*&+.....@#*30df7lpoTTTTUjh4(03>%+.........@&$-0b4mooqZoonVVllkkkk4b;#..#3aehoWWZmhedc93339cbe4444ed9&..@%-;ab4khVVVI74ef}4ioWWqifd9=@..&*,cae7khlVlhkf44k<moWWqiba,*+..@*,cae7khPmml74fe7hmoWWqib0-%...@*-cbf4kllmmh44e47hnZWWoifc3#.....@#=3cbffipjqTTTUqjlg4edc=&......&*=90befkipqUTTUopk74:d;,&.....+&#=cabe7hmjqUTTWoph74bdc,#+....@%$,cabe7kmjqTTUWomh7fbac,%+..",
|
||||||
|
"....+&-;~{^zxHGLEEuEGBAz/);>#+.....+&*,;~]rztAvDEEuuGHxzF~;>%.......+$-;)FrstCvvEEuEGBtzF);>%+......&=-;(F^stHvLEEELHBxz]';$@......@*>-!{FrsAHvEEuuEGAyr]~->%+....@*>-~]rstHvDEuEuvHyzF);=%+.......+#=-~]rxDDDvGGHCCCCCCCtsz/'$+.*~FKADEEEtxrF)';;;'~]/rrrr/]!%..&$3_FrsBACCBAysssxBAGvLGxKF_-&..&=;_FzsACBCCAyssytAHvLLGyI{;$...&=9_FzyACBHHAxssxxBGvvvGyQ{;$...%-;)/zxtCCHGAxssxtBGvLvGsQ{;*.....&=-;~{/rzswvEEEEAxsK^F{!3*......+*,;~{F^zstGEEEvGysr^])!-*.....@%$-;){F^zstDEuEvAysI/])'-=@....@&$,;~)F^KxtuEEEEHyKr^]);-*+..",
|
||||||
|
".....@$-')]zyCCvLEELGHAs/)'-=&......%=>;'{/zyCGvLEDvvCBs/);-*&.......#=;~]/sACHDvELLvHAzF);-$&......@*-;!{/zABGvuELGGCAzF);,#......@#=-!)/zsBCvLEEEvGCtzF);,*@....&$*-;{/zyBGLEuEvvHAs/)!-=%+......@*-;)/KAvLvCCBCCBCCCCCBsrF'*.+>'/ztvLEuHsr]);;--;;)]F/^^F)-%..+$-!FrxABCCCAyssxACCCBCts^{!,@..@$-'FryAACCCAxssyBCCBCCAs/);*+..&=-)FryAACCBByssyBCCCBBszF);*+.+#>;)FzyABBCCAyssyBABCCtxzF);*+....+%=-;'{F^zstEEEuAsr/F)!;,%+......@#-;!){/zsHLEuDAsz^])!-,%+....+%#=-;')F/KyHLEuDAzr^])';,%+.....@#>-;;)]^zyGEEuHAsz/]);;,%...",
|
||||||
|
".....+#>-;_1QJJJP6P6JOPQ|~-=*&......+%*>-!_2<JOOP6PJOJPQ{~-,*@.......&*=-'(2IJJJ6P8OOJP[|'->*@......@#*,-!)2KJJJP68JJJI[('-=%+.....+%$=-!):[KJJJ866JOJK}('-=$@....@%#=-;(2QJJJJ888JOKQ1';=*%@......&*>-;(:5JwwJsKsKKKKsKKr2{~-%..%-_:<ONww52('->$*$$=-;;!!'!-$+...&=-'1F/QIKK^/2F[rKKIQ^[{~-=%...+#=-'{F^rIKrQF2F[IKrIQ^}{!-=%...@$=;~{F^IKKKI/}/^QKIQ^[1(;-$&...@*>;_1/[rIKKQ/}2^IKIQ^2:);-#@......+&#==-;_(45wwNO<}(!;->$#+.........%$=-;;1[5MNNO<}(';-=*%+......+@%*>,-;~1[8wNw6<:_';-*#&........+&*>=-;_|[6wNw6[1)!;-=*&+...",
|
||||||
|
".....+&=;!_:<6O5<[4<8Y6<1~!3=#+.....@&$=;'_:58Y5<Q[<6Y6[|_;-=%......+&$>-'(}<6O5<[Q56Y6[1~;-*&.....+&%$,;~(156O5<[Q<6O841~;-=@.....+&#>;!(1[6OO5<[[56Y5[(!;-*&....+&*>-!(1<8O6<[Q<6Y8<:('->#@......@#>3!_:Q6JPPIII6666665<:_;=@..#,!b[6MSO<:~;=*##%#$*=,>,=>>&+...%*,;__}[QQQ[}::}[QQQ221~-=&+....&*,;_:22QIQ[}11}[<Q[}}1~;=#+...@%*-;(|}}QQQ[}1:}[QQ2}|(!-**&...+&=,!(:2[QQQ}21}2QQQ}}1(9-*#+........+&*=-9~1<YSS67(!;,$#&@...........&**,c_15YNM64(!;,*$%@........++%#*=,c_15MNR8}('->*#+...........@%$=-9_e5YRY5}_;-=*%+.....",
|
||||||
|
"....+%=-cdbfiqqmgffgpqjifbd03*@....+&#>3cdbgiqqpgffgjqjieba0,#+.....@%=-adbgpjqigffijqjifba0,#.....+&*=3adbgmqoige7ijqpiebd;,%......@*,;abegpqoig7fijqjgfba;,#+...@#=30dbfiqqpgffgpqoiebbc3=#+.....@*,;abb7imlliVmoqUWWqqifd9>@..%3cbgjWWqifa;,=$###*$>=>>=**@....%*-cdbe4hmhh4}f7hhh7feda3>&.....%*-cde44hmi74e44hlhhfed03$&....+%*-9db44lih4ff475ihfedac3*&+....&=,cde4hhli7fee4hlhfeda9-*&..........@#$>90biqUUjgb03=*#@............@**>30biqWqpfbc3>*%@...........@%#$>-0fiqUqjfa0-*%&............+&#=9;0fiqUqifdc,*%@......",
|
||||||
|
"...+&#>0de7hnoZph[7koZZnh7edc,&....+%*30be7hpZophkkinWZph4ed9>&....+#>3a(e7hnZZnh4hloWomh4edc$@....@#>9abekkpZqXhhhloZomk7ed9$+....+#=3_b47koWqmh7hmqZom74bd9$@...&*9c(e7hnoqnhkkhoZqnl72dc,*&....@*>9d:44lVlXVXXoZUUUUUqjgb0,&..#3aeioWWqp7bd03-,>,,3-3-3-,*%....&*,~b4klmonmlllhnnXh7:dc3=#+....&=-a|ehlmoomllhVnnmh4eda3=#+...@#>3_b4klXoomllhmonmkebac,>&....+%=9a1ekhnonmlllmnpl71bac-$%+.........@%*,cafiqUUjiba;,$%+............@%$,9dfiqWWjgba9=#%+............@#*390fpqUUjgb9,>#+.............@%$>0bfjWUWjgd;,>#.......",
|
||||||
|
"..+#,;~FzxAHGELvHABHDEDGCtxz]~=...+#=;~FzxCCGELvGBAHDEvGCtyr];$...+#,;)/zAAHGEvvCAAGvLvGAAsr];#...+#,;)/syCHvELvHAHHDLDHCtsr{;%...+#-;{^stBGvEEvHtAvLLvHAAsr{;%..&=-)FzyBHGDEDHBBHvEvGBAyzF)3$+..+*-']rstBBHGGGGHGDEEEvDvts/{;%..*_FztGELDHssr/{)~~){{{]]{{);>+...*-!{^stHvLLvGCCGvvvtszF{~;>&...@$-~FzstGvuEvHCGHvDvtsr/]~;=&...&=-~FrstHvLLvHBHvvvGxz^]);-=@...@=-~FzsAHGLLGACCGDDGyz^]);,=@.........@*,;(/KtEEEDyI]~-=*@...........+&=,;)}ztEEEGJr{~-=*@............&>,;(FKtuEEvJ/(;-*+.............&$3;(}JtuEvvs});-$+......",
|
||||||
|
"..@#-;)^sBCBGLLLHCCHLLLHCCAs/)>+..&$-;]^yBCCGLEvHCCHLLLHCBts/)>+..+*-~]rxBCHvLLvCCHGLELHCCtsF!*...&$-!]rxBCCLLLvHHGGLLGCCBtzF'=...&=-~]zyBCHLLEvBCHGLEGCCBtzF'$++%>!)/sACBvLLLHCBCLLLGCBAs^)!>&..&$;)FztBCHLLLLLLvGHCHHHAyr]),%..*;FIyGLLLHAszrF]]]FF/rrrr/F),&..+*-!]^syAGLLvBCCGvLvAsr/]~;-*+..+*;~FrxAAGLLvCCBGvLGysr/]);>%...&=-~]zsAAGLLGCCBGLDGyzrF)~;,%...%=;~FryxHvvLvCCBGLLtxz/F)~;-#.........@$-;)/KAuEEDxr]!;=#+............&*-;)FPALEEvy^{'->$@............&*,!)/JALEvGs^);-$+.............@$-;)/VALuuGs/);-$&......",
|
||||||
|
"..+&=-!{/IKPwwNwwJKJwNwJJKr/|;*...@#=-!]/IKJwwNwJJKJwNwJJzQF(;*...+%=-!]/IKJwwNwJJJJwwwJJKr});%...&*>-~FQrPJwwNwJJJJwNwJKKrF_;#...&*,;'FQKKJwwNwJJJwwNwJsK/F)-%..@*-'{/IzJwwwwwJJJwwwJJzr}{!-*@..&*=;(/rIKwwNwNuNwJPKQIQ[2(~;$+..@$;([6wwwJIQ}]|)~)1]}}}/2F_'>+...&=-!)F[IJwwJKKKJwwO<}]_~;->&...+&=-'1/[KJwwJPKPJwwOQ}:_~;-=&...@*>-~12QIJwwJPKKJwO8Q}|)~;-=&...@#>-~]2QIOwwJKKPJwwPQ:{(!;,*&..........@*-;_e5wNwOQ|'->#@.............@&*,;~}5wNwJ<|!-=*%@............@%*,;~26wwwJ[|;-=%@..............&=--)26wNw6[(;,>#@......",
|
||||||
|
"...&$,;(}QI5OSSOJPIPYSSOK<Q2~;*+..@#$,;(}QIIJRSO6PK8YMw6KIQ}_;*+...&*-'1}QI5OYSwJIP8RSSPII[}~-#...@#*-!|2QIPOSYOPPPOYSOPK<[1_-%...@*=-~|[QIPOwSYJPPORSOPIQ[:'-%..&$-;(}QQPJSwYJPP8OSROI<Q2(;,*@..@*-;(:QQPJSNNNNNS6QQ[[2:1(!-*+..+#,_:<88O6P<Q}1::::}[<<<}:(!*+...%$,;_:2QPOY85QI5OY6<}((_';>#+...&*-;(:2<8OO6III6YY6[1(__;3=%...+%=-~_:[<8YO6I<<8OY6}1((~;-=#...@%>-!(:}<8YO8III6OY54:(_~;-=%..........&*=-c|5YSR84(;-=#&.............@%$=9_|<YSR82('->#&+...........+@#$=-a:5YSY84(;-$$@+............+&*>-a15YSR5e_;,*%&......",
|
||||||
|
"..+&=3cb7hmmjZqommlmjqqoplh7d9*...@*=9ab4hmmoqqqpmmpoqoXmlhfbc*....#=-cbkhmmoWqomlmmqWqommhfd3%...@$=9af7immoqoopnmjqqZXmlhfdc$...@*=9aekimmoqWjmmpoqWopmlgfd9#..@$3cdfilpoqWopmmnqWWomlh7bc3*@..@*3cb7himjqWWUUqqjih77febba0$+...%>0d7hilpopmhk77khimjjjifbc$+...@*-cdefgpoomlkhmpqjgfbbdaa9*+..+&*3cdffhpoomihhmjqpgfbbdda3*...+%*-0de4hpoomihhmjqpgbbbbac3#...@%=3cde4ipoomhhimjqigfbbbaa-&........+@%*,9abiqWWjgb;3=$#+...........+&%>-cafiqUqjgd0->*%@...........+&#>-cafpqUqjg_c9=$&+...........@&*$3;dfiqTqjeb03=#%+.....",
|
||||||
|
"..@=-'b7inXoYZoXXVVVnZZoZomifd=+..@*-!b7mXoonZZnnXXXnoZooonlfd,+..@$3ab7mnnooZnnXVVXnoZoooXie0$...%=9~b4mXonZZoXXXXnoZoooonhfa=+..#>c_bhmnXoZZonXXXnnZXZnomkea*+.%-0d4iXooZZoXXVXnooqZooXi4dc,&..%30d7inXoooqoqqZoXVlk7k444e_9%..+%>9de4lmnZZoXVVVVVXZZWZph:a,@..+#,cdb4klXnXmlhklnopmhkk44ed,&..+*=9~b4klXnXVlhhmmnmVkk444e_=+..&*>9ae4hlXonVllhmnjmik7444e0$+..&$,0de4klXXXmhklmnomlk4444:a$........@*=33adgiWUUoiea03,=*@.........+@*>,30bfpqUUogedc3>=&+.........@#*>,0abgjUUWjged;3,$#@.........@&$=39abgjWUWjhbdc93*#@....",
|
||||||
|
".+*;)FzxHEEDDCCBCBCCHHGDLEDHs/'@.+$;)FzyvLLLLvHGCBCCBHvLvLDGs/;@..*-)/zyDEELvvvCBCCCCGvvLDDts/;@.+=!{/sADvEEvGCCBHCBCGGLvLDAsF;+.+=!{/stvEEvGGHHCBCHBvvLLLDtKF-@+$'FzxGvDEDvHCBCCCBGGDLEDGyrF!$++$'FzxGDDDvGHHGGGHBCCAxyyAAAz{=..+#-!]rstAGDLDHHCHHHHLEEvGyzF;%..%,'{^zxABHvBHtAttBHCCBBBABxr{*.+*-;(/zytBHGHBABtCCCCCBCCABxr;@.+*-!)/zxABCHHBttAtCHBCCBCBBy^;+.+*-~FrsyBCHGCCAxtACHHACCBAty/;+....+&#=;'){FrsHuEELtsrF{)'-$@.......&#>;!)]/rxGuEEvtK^]{~'-#+......+&$,;'{F/zsvuEEDAz^]{'!-=@......+%=-;~)]/zyGEEEvxzr/]);-$&...",
|
||||||
|
".+#;)/zyvLELLGCCCCCCCBGGLEuGxr;&.+$!(/KtLEEEGCCBCCCCCCBLEEDHxr~&.@$!{^KtLLELLCCCCCCCCBvLLuLGyr;@.+>;{/stLLLLLCCCCBCCCBCLEEuGs^;@.+>;]/KGLEELLCCBCCCCCCGLEELHs/;@+*)^zyvLELLCCCCCCCCCCGELuvxzF)$++=)/zAGLELGBBCBCBGCCABAtABCCsF-+.+%-!{rzyAHGGGGCGvBBCGGvvtsr]-&..#-']rsACCBGGCAtyABCCBCCCCCAs{>++%;~]rsACCBCCCBtytBBCCCBCCAAr~&..*;)]rsACCBHHCBAxBCCCCCCCCBAr;&.+#;)FzxCCCBHCAtyABCBCCCCCCCxr;@....&*=;!{F/rzxHLEuEBxzr/])!-#......&#>-~{F/rKyGEEuLByz^/]);,#......+*>;!)]^KsxGLEEGtsr/F]);>#......@=>;~]F/zzxvLELuAszr/]);=#...",
|
||||||
|
".+%>;(2<ONNNwJKKrIrIKKJwwNNOI}-@.+%-!(25ONNNwJKKIrIrKKJwNNw8I1-+..#-!1[6YwNNwJKI/QrIKKJwNNw8I1-@.+#-'1[8wNNNwJKIrIrIKJJwNwwJQ(-+.+$-~:Q6wNNNJJKIrIrKKJJNwNw8Q(,@+%;|[5ONNNwJKIrIrIzKJwwNNOQ})-%..%;_[5ONwNOKKKJwwwwwJzKrKKJJ<_>....%$-')]}QIPJwwwwJJKPI5<21_-$+..&>;)}IPJwwwwJIrIrIKKJJJJKzQF'*.+&,-~}<PJwwwJJKKIIrKKJJJJsKQF-@..&=;~}IPJwwwwPKrrIKKKJJJJsI/],+.+&=;([IJJwwwJJIrIrKKKJJJJKz^{=+...+&#*-;)1F[Q<JNNNw8I[}F|~;=#......@*=-!)12[[IONNNMPI/:](~;=#.....+@*=-!)(F}[KOSNNwPI^}](~;=#.....+&$=;!(]}[Q5ONNNOPQ}}]_~;=%...",
|
||||||
|
"..%=;(}5YNNNOPI[2}}2QIPMNNMO<1-@..%=;([5YNNSOII[22}[QK8YSNN8<:-@.+%-'125MNNS6PQ[2}}[QK8RNNS6<:-+..#>'1[5MNNYOPQQ2}2[QIPRNNR6<|,+..%-~|[5MNNSOKQQ2}}[QIORNNR8[|-+.%-(}<ONNNOPIQ}}}2QI6ONNS8<}_;#..#9(2<ONNRO5IPOSYSSYYP5IP8R85($+....&#>-9~|:[QPJJJPQ[}:(_0,$#+...%,9_25OYwSYw8PKIIIIPOwwO6<[|!*..%=;_26OYYSSY8PPPIKPKOwYOPI[(-@..&=3_48OSYYwYJ5KIIIPKOYwO6<[)>+..#=9(48OSMSNY8PKIIIPJOwwOP<[(=....+%$>-_(}}[Q58SNNR8IQ[}1(;-#+.....&#>;_|2}[<58SNNR6<QQ}](;,&.....+%*>;_|:[Q<5MNNNM6<Q[21(;,&......@*>;_|}[[Q6MSNNY6QQ}}1(;=&...",
|
||||||
|
"..%>cbfiqUTUqmlkfee4kimqUTUqif9@..%,cb7iqUTUjmkkfee4hhmqTTUjie3+.+%3ae7mqUTUomh74ef7hlpqTTUjhf-+..#-0bgjUTUUjpk7eee4hloqTTUjgb3+..*9afhpWTTqomh4eee4hloqTTUjgb,@+%cd7iqUUUqmkkfef4hhpqUTUqigd3%+.#;bgiqTTWjmmjWUUUUWWopnpjWqid>.....+&#$,cabfhmmVmikfbac3>*&.....@>;dgjWWUUUWopmmmpmnqWWZni71c*..%,0bgjWWUUUWqmmmmmppqWWZjl7b3+..&=cbgqWWUUUWqnlmmmnoZWWZni4b>+..#,0bgqWWUUUqopnpmppoqWWZph4d>....+&*,;defkh5mqTTTTjmkh74ba-*@.....@*=9de4khlpqTTTqjlhh4fba-#.....+%*,;de47klpqTTTqjlhk74ba-#......&*,cde47klpqTTTqplh77eba3#...",
|
||||||
|
"..%,abhmqUUUqXll7444lVXZUTUqm7c@.+#,a:hXqUTUZnVh444kllnWTTUoVec@..#3_ehpZTTUnXVk74kklVnWUTWoie9+.+%3d4ipWUTUZXVk447klXnWTUUom49@.+*;b4ljWTTWoXVk447hVXoUUUWome9+.*;e4moUUUZnVl7447lVXqUTUqmkbc#..*cehjqUUWZmmoWTUUUUWZnnXoUqjb,......@#$,cdeklVXXXlhed03=*&+.....%=9bgoWWUUUWZnnnXnnoZUWWoVhec#..%3abiZWUWUUWoXVXXnnZZUWWnmke9@.+&,;bioWWUUUWZnXXXnnoZWWZnVkb,+..%9cbioWUUUUZonnXnnnZWUUZoVkb,+...+#*3ab4khVlnqTTTUoXVlhk4dc=&....+%*3a:7kllVnqTTTWoXVlkke(9$+....@#>3ae7klVVXqTTTUoXVVkked3$+....+#=9_e7hlVmnqTTTZXVVVkkea,*+..",
|
||||||
|
".+*!]rstvEELDHCtysyxACHLEEEDHs)%.+=']zyHvEELDHBBsssxCHGDEEEGAs)&.+=!FzyHvEEEDHCAxsxtCCGDEELGAs~&.@=~FzAHDDEEvGCAssxtACGDEEEGtz!@.+='/ztvLEEEGBCtssxAAHvEEELvtz'%+=_rxAvvEEvGCtysxxBCGDEEEGHxr{=++>(rxGDEEEDGHvDEEDLEDGGGCGDDwe,+.....@#,c)/sxBHGvGHxzF~;,=@......%-_/xHvLEEEvGHCGCHCvvLLvGByr)*.+*;]IsGDLLLLLGCBCBCHvLELLGCxz'&.+*;_/xGvLDLvvvBCCCCCGvLLvvAy/-@.+*!1IyDLLLEELHBCCCCHvLELGGAs/-+..+&=-!{rxtACCHvEEEEvGBCBxs/)3%....&=-'{rstCCBGDEEEEGBCCBxs/)-%....&$-~FzxAACCGvEEELvCCCAyzF~-&....@$-~FztACCBGDEEEEvBCCAyzF~,@..",
|
||||||
|
"..$;)/zyAGHHBBAyszssABAAHBHtxz)&.+*;{/sxBACHACBxsssytAAAHHHtyr~&.+=;{/stAHGGCCtyszsttABBGHHBs^~@.+$!]rsxAHHHBBtxsssyAACAHAHts^'@.@>;]rstHHHHCBAysssyBACAGGAty^;@+$)^zyAHAHBCAysszyAABCAHHAxs^)$++>)^sxtHHBCBACCBCCHBCCBCBCHtsF-......@$-;)/sBHGLvvtsr{'->%+......&>!1ztCCCHGCCBCCCBCCCHHCAyz/'*+.#;)/sABCCCCHCCCCCCCCCCCCBxsF;@.+%;']zACCCHHCCCBCBCCCCBHCByzF-+.+*;)/stCBHCHBCCCCBCCCBHCBAyz]-+...@*-;)rzyABBACAHHHCABtyyzF),%....@%>;]/zyABCCBGGGHBCABxsrF)-&....+*-;]/syBAACHHGGHACAAxsrF',&....+*-~]rsttBBCAGGGACBBtysr]~>&..",
|
||||||
|
"..@=-_(:}[[[Q^/F]{]]F2[[[Q2}:_,+..&>;~(}2[[Q[^/F]|{]F/[[2[[2{_-...%>;~1:[[[[[^F]{(]{F[/[[[}2]~=+.+%>;_1:}[2[^^/F{{{]/[^[[[[2{~>..+#,;_11}[2[[^FF{{]]2[[[[[[}{~=+.%-~(:}[[Q[//F{){]F2[^[[[2]{',&..%-~1:}[[[[//[^QQQQIIrIrQ^[}_-%.......@*,;(2IJwwwJQ:_;-=%+.......+%-;(:}[Q[III^rrQ^Q/QQ[[/:(~>@..+*,;(2[/QIQQrQQ^Q/QQQQ[/2](!$...@=,;_:[[QQIIQ^Q^I/Q^QQ^[2F(;$...&*,!(2[/IIIIQrQrQ^QQQQQ[F:)!*.....@*,;~]]F/^[Q[[[[Q^/FF]_!-$+.....@#=;))]F/[^QQ[Q[Q^//F{(!-*+.....+#,;){]F/[^2Q[[Q^[/F]])!-#+.....@*-;)]]F/[Q[Q2QQQ//FF])!,&...",
|
||||||
|
"..+#,-!_(_(||(__!!!!~(((|((_!,*+..@%=3'~((((|(__!!!'__(|1((_!-%+..&*-;!___|||((';;!__((((|(~';*...@*-;!_((1(((_'!!!'_((((((_';*+..#*-;'_((1(((_'!!!__(|_||(_!-%.+@=-!~_(|(1__!;;!!~(_((((_';;$+..&>3;~_(||(__((({|||:::::|(_;=@.......@%*-'(}<668<:~;,$%@.........@*>;~)(|::::1111:|:||((_~;-#+..+%*-;~_(1|1:|:1]|1{|||__~';-%+...&#-;~(((::1::1:|1|1(|(__!;-#+..+#*-;~((11::11|1:||||||(_~;>%.....+&#=;;__(((||1|||1((~~'-=@.......@*>;''_((_||1||(((_~';-$&.......&#,;;__((|1|1|||(((_!;-#&......+&*--!__((|||1(|((((~~;-*&...",
|
||||||
|
"...&*>33cc0;0cc9-9939c90cccc9=&...+%$>,9900c0c99-333c9c909cc3=&...+&*,39cc;c0;9-3--9cc009ccc9,#....&*,33c90090c933333000c9c9-=&...@%=,39;9c09cc93339ccc0c0;c-#+..+*>339c090099--3999cc09093,=#+...#,-39cc0cccca00a0c~a_aac0c3%........+@#*9;abbffba3,>#&+..........%$,39c!a_aaaa0c'0a0!0cc93=&....@%$>;c9_aaaa~aa~c00000cc9-=&....@&=3-c0cc'a'a~a~0cc000c99,*@....&#>>;cc0aaaa~cc0'0000c099,=&......+%$=,330900~a0;0cccc-3=*&.......&*$=333c0c0~a000;9c;3,=#+.......@%$,339cc0c000aa0cc33,>&+.......&%>,3939c0a0000!;c993,>%@...",
|
||||||
|
"...+&#=,,3,3,3>->,=,3,9,3-3,,=&....@%*$>-,>-3,-,>,,,,3,-39,,>=&....@#$=,-,33>3-,>>==>>-3-3-,=*@....@#*=,,9>>-,,,,>,=,>>>--,3>*&...+&#*=,,9-,-3-=,==>,,-,3,3==%+...%*=,-,,-,>-,$>>,,9,,3-,,>**@....@#>>-,-,99399999999933-9,>=#+.......+%%*=3-00a003,**%+...........+%*>-933339;939333;93-,=**&....+%#$,>3-33;993999-3-3-,=>*#@....+&%*>--939-39c9-3--3>-,-=*#+....+&#>,,-3-3;999993--3,9>-=$%+.......+%*=>,,-33399939-,=>$*&........+&#$$=,-,-33993339,=>*#@.........&***,>-333-3333-9,,>$*&.........&#*=>-9--939,-33,-,>$%&....",
|
||||||
|
"...+@%$->---------,-------->-$&....@%=>=---,-----,>>-------->*@....+&**-,----,-,>,=>->-----,>#@....+&%$>----,---,----3----->>#+....+&#$>--------,-->------->=%....&**>------>,==>----------#%+....@#$>--->----;;;;;;;;;;;--,#@.........@&#=-;;!cc;;-*%&............+%$>--;;;;-;;;-;;,----,$#&@.....@#$,--;-;;;;;;;;-;-----==#@.....+%*>---;;;;;;;;-;-;---->#&......@#$>---;;;;;;;>-;-;>--->*#+.......+#$>-----;-;;-;----=#&+.........@#*=,------;;;---->=*%@.........+%#$>---;,;;;;--,-->##@.........+#*>-,--;;-;-;---->=*%@....",
|
||||||
|
".....+&%**%*%*%#%**#%#***#*#&@.....+&&%***$**#%#%%##%*$###%*%&+.....++&%##*#**%%#%##%****%**%@.......++&**$**%*%**%**$$**%%*#@......+.@&##$*%*%%%&%#**#**#**#&.....+%##$$***%%%%##%*#$*##%%%+.......@%%%*=*$*$#$*=$$>>====*%@...........+@#$==>>>>##&+..............+&%**$$===$=$*#$>*#*%%@++.......+&*%#$$***$==*#=$=$**%%@+........@%#*=====$*$$>$=#**%%&+........+&#**$*$=$##$=*#=$$*%%##@..........+@%%*#*$=***$$**%%@+...........@%#**$==$**$*#**%#@+++.........+.++%%##*$$$$$=$*%%%&+............&%%*$==$=$===$#%#%&+.....",
|
||||||
|
"...........+..++..+.+.+++.++............+.+.+.+++....++++...............+.+.++........+.+..................++.+..+.......++.............+....+..+....++++.+.............+..+.++.+..+.++++..................+.+.++.+..++++..................+++++++........................+++...++..++.++..............+...++.+.++.......+..............+++++......++..+++.................+.++...+...++.................+.++.++.+....++....................+..+.++..+....................++........++...................+..+++++.+.++.+........",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"..........................................+@&%%%**%%&++++..................@&%&@+...............................+@%%%@+.....................+@#****&+.......................+@&%%%%%%&++................................................................................................................+@%%#*%%@+.............................+@%%%%@+....................@%%****%@+............................................................+@%%&++........................................................................",
|
||||||
|
"...................++...................+&=-;!))~{)'!--,-=$&+..........+%*=-~);;--=*&+.......................%*=>;''!-,$%&+.............+%**=-~({~);->*&+..............+%*>>-;!))))'~!-->>*&+..................................................................................+++.+@&&@+.............+&*-;!')!;-,$%@+......................@%$,;;;~!-,%&+...............@#,!))())'-,*%@+...................+++..............................+%*>>;;';-=*%@................................................+%*****%&+...........",
|
||||||
|
"......@&%%&%##%%&%#%%%&@+.............+%#>-;))F/^//F])))'!--#@.........%>-;)]]]~)';--%+....................+%=>;!)]]])~-,*&+............&$-;!]/^//])~;-*%+............+%*-;!))(F/FFF]]))';-=%+...........+&%&#%%%#%&%%@+....................................................+@%#*###**==###@..........@$-;~]]]{)~'-,*@.....................+#>-;!)]]]~;-*%.............+#$-!)F/r/F])!-,*%@..............+&%##*%%%##%%%@.....................+&$-;!))))';-=*&...........@&%&&@+...........................+@#$>--;--*##&@........",
|
||||||
|
"......@&%$#%**#$*#*$#%%&@.............+#*=-;)_]}/}F]_()))!-=*@.........&*-;~{{1{)~;-=#+....................@%>=;;'{]]~'->$&............+@*=-;)F//}]{';-*&+............@%*=;!)(]1F}]({_()~;>*%+..........+@%#%###%*$#%%@+..................................................+@&&#%#*#*$$=>**%%+........+&*=-!){({()!-=*@+..................+&&*,-;!){{)!->*%+...........+@%*,;)]}/}F();->*@+.............+@%##%#%%%%*%&&@+....................@*=-;!)({{';,*%@..........+&###$%%&@@........................&%*>,--;-,$##%@+.......",
|
||||||
|
".....&%#$*>$**>**=$*$*##%&+..........+&%$>;~(:}[2[}}:1}1(~;>*@........+&$=;(1}}1}('->#@...................+%#=-;~(1}}1!-=*&............+#$,-~|}Q[Q}|(!->*&+..........+&#$-;(|}[[[[}21::1(!->#@..........@#$$$*#*$**$$$#%@................................................@%&#$*$=>,>---->**%@.........@#>;_|}2}21~;>$#@..................@&#*-;~(|}[1_;,$#@...........+%$,-;_}[QQ[:(~;=$#@............+&%#**$*$$$$$$$#%&+..................&#$>;'_(}}1(;-$#&.......+&&%*$$$*$*#%%&......................+&*>,--!;;-,=$#%@.......",
|
||||||
|
"...+&*$*>=333333,-3,,>=*$$#&+........&%*=-0de44hhh74f44fedc-*&........+&$,cbe7774e~9-*#+..................@*$-;adbe74ea9=*%...........+&%>-0df75kh7eba;,$%@..........+%*>9abe4hhhk7eeeeeba-=#@........+@%*=,,,>=>,-=,>**%+.............................................+@%$*=>,,-3cc90c0c>=*&........+@#=;de4774e_c,*#%@................+&#$=;0dbe47edc3**@+..........@#*-cab4khkkeedc3$$%@..........+&#*$,-,==*=,-==>**%@+...............@%*>3a~be47eb0-=#&+.....+&$$>,,3>,>=**##@....................+%*=,;0ad_dc93=$#&+......",
|
||||||
|
"...&=,3cc_a_d~dd_dddaa0c3,==*&......&%>,30_e7klVVlllhhhk4|a3=%........@#=9'e[lllhkea93*&+................+%$30d|e4klhedc3*#+..........+&>3ad:klVVVlk4:dc,$%+........+%*,3a14kkllVVlhkkk4edc>*@........+*$,;!aac;cc0aa993>*%..........................................@%#=>39ccadd(bbbee1da9=#+.......&$=99b4klllk7d09=*#&+.............+&**3c_be[kll4e_;3=#+.........+%$-0d:4klVVVk4ed03=>#&........+&*>>;0~aac;c!aa0933==#+...........++&#$>ca(e4kkVked03=*@.....%*,3ca0_daac9-,=*%+.................+&#-0dd1ef4ee(a03=*#+.....",
|
||||||
|
"..+*!{F^zssssssxsssssz/F]{)!-$+....+$-')]/zxBCBCCCBHCCBysrF~-=+......+%>-']rxBACCAyr]);>#&+.............@%,;)/zyyBACts/{'-=@.........+#$;)/zyACCBCCCxs^F';>#+......@#,;~]/sACCCCCCCHHCAyz^);,%.......+#>-~Frzr^/F/rzz/F{)!-#+.........@@@&&@+.........+@@@@+........@*-;!){F^rssssyyAABBxrF!-&.....+%$-;)]rstBCCAyz/{~;-=#%@+.......@%#=-;;)FrsxAACBxr/{';,*@......+&*,;)FzyACCCCCBAyz/])!-=@......+%*-;)]rzzrFFF^zzrF]{);-#+........+&$=,;;~]rsytBCBts/]);-#....&>-)]rzssssz^FF{~;,$%+..............@#,;)/zstBBHAAxsrF);-*&+...",
|
||||||
|
"..%-~FrsxBACCBBBBAABAAyz//]{;-%...+#=;)]/rsBCCCCCCGvGHBxs^{~;>%......@#=-!{/zxBCBAyz/]~->*&+............#>-~FryABCBtyz/);-=#+........@#,;]ryABBACCCABxz/]~-$#+.....+*-!{/ztACCCBCBHGGBtsrF)-,#.......%*-;)/ytyzzzzxAysr/F);>%........&%$>==*%%@+..+@%%#*$***&......@$>;!)]/zsABBBBACCGLDGy/{;$+....@*>;~)FrzyAACCBxr/)!--=**&......&*=--;;){/yBCCBBxsrF)!--=%......%>-;~{rsABBAAAACBAsr/]);>#+....@&*,;']rsyysr/zsyyyzr/]);=%......@%#*=-;;~{/stCBBBAsr/{~;-*+..+%-!]ryBABAAAxzr/]~->*%+............@#=-!]rxBCGGLLHCAs/{';,*@...",
|
||||||
|
"..@$;)F^IzKsKsKzKzKzzKr^F1(~;>&...+&*,;)1F[rKKJJJJwwwJQ2F)~-=*@......@&$>-;){/rzKzQF|';>>#&@..........+@#>,-)FrKzzr^F|);-*#@.........@#=-~F^rKrrrrKzr[]_~;,$%@.....+#,;!)]/IKzPJJJwwwI[]_!-=%@......+&#=-']^r//1FF/rQ/]()!-*#+.....+@&#*$$>$*#&@@@@&%#*****#%+....+&*=-;~{F/QrzKzKsJJwwwO<|!>%....+@%$=-!~{]F^KzrI/F{~;-,>*%&......@%$==--!)]/Izzrr/F|)!;-=*&.....+%*>-;~]/rKrrrIrKzr[F]);->#+....@&$=-;)]/Ir/F|F/rr//F|);-=&.....+&#*$=>-;;']/rzKzr/F])!;-$*+...&=-)F^zKzKzKr/F|);-=*#&@...........@#=,;']^IJwwwwwKK^]~;-*#@...",
|
||||||
|
"..&$-!(2<PPPPIIIIIIQQQ<<[7}1c-*...@%$-;~(1}QIKIPKPOOO6[:(('-,$&......+&#*=-'(1[QIQ[}|~;-**#&@.........@&$*,;~|[II<[}1)~;,>%&+.......+&#$,!|}Q[[[}[QQQ}:(~;>*%+......&=;'(|}[IKIPPPOOO<}(_;-$%@......@%$$-;|[Q[}:|2[QQ}:(~;,$%@......+%#>----=*#%%&%##*>--->>*@....+%*-;((:}<<IIIIKPPOYNSO<1;,#....+%$=-;'~((12QQQ[}|(~!;-,>$&+....@%$=>--;'_|[QIQQ22|1~_;->*%+....@%*,-!_|2QQ[[22QQQ[}:(('-=$&...+&#*,;!_:[Q[:|1|}[[[}1|(!-=#+....&#*>=---;!_|}QIQQ[[1|(_;-=*&..+%*-!1[QIPPP5Q[}1(~-,$$#%@.........+&*>-;(1<P666O86J5<}(!->*@...",
|
||||||
|
"..&=9abgmqoqnmlhkhh<khlpjqjgbc=+..@*=9abb47kklliVmoqopgfebd0-=&......&%$>-;abe4h<k7eedcc,>*%@........+#*>,90be45h<h4fbdc9,*%@.......+&*>-0:4hk7747hkh7ebdc-*#@.....+#=;adb44hllmVmoojifbac-$%+.....+&#=>;ab7h744f77<77ebdc3$#@......&*=9caa09=$*$#**$39aaac,=@...+&=,cbefgmjjphkhmoqWWWWqifa3#....@#>9!adb:ee44kk44eebdda;33*@....&*>-caadbbe7kk<774ebbbdcc,$@...+%$=90dbe7<h74444h<7ffebd0-=@...@#>,;adbe7hkf:bb44h774eed0-*@...@%$,9;aa_dbb:77<hk47febbd09,%...#*3c17hhnnoph77ebda;>=**&+........+%=3cdbgioopigimjoigbda3$&...",
|
||||||
|
"..#=;_ehnZWZoXVVllllVlXoWUWpgb,+.+%=-a:4kklVVVlllmXnXVVkk74|dc#.....&%=,39d:4klVVVlhk4eda93$#+......@*=,-c_e4kVVVVllk4e(d03>%+.....@#*>3abekllVlllVVVk4:ba93*&....+&*,c~b}7lVVXXXXXXXl7:ba9,*&.....+*=,ca14<llhlllVllk4eba;,*@.....&%=9'bb1ba09,=>>33;abebd0,#...%*30b4klVoZZnmllXZZUUTUqp7b0$+..+#>9de4k7kkkkk7k7kkkkk74e(a9*...@#>9a|44kkkk<kkhhkkhkk742ba9%...+*-c~e[khlVVk744klllQlkk7:d9#...&*30de4k<Vlh74e4kllVllhk7:a9%...&>9ad|e47k7kkkllllIVlkkk4410>+.+&=3aeklmnZWoXVkk44bd0c3=$%+.......&*,0de4hmZomlhlmoZni4ed0>%...",
|
||||||
|
"..*;{^stDEELDCCCCBCCCCHLEEEGs^!@+&=;{/sBCCCCCBAtxABCHBHCCAAsr{=+..+%=-;~]FzsABBCCBCCAysz^F);-%.....&=-!){/ryABCCCCCCCxsz/F)!,&....+#-;~{/zxtCCCCBCCBCBysr^{~-*+...%>;!{/rsxBCCCGBGCGHAxsrF{!-$+...@*-;~]/zxACBCBBCCCCtysz^]~;#.....#-;)^zsszrF{)~~))]FrzssrF'>+..*-)FzACCHGLEGHCHHDEEEEEDGsrF-#..%-!]rxBCBCCAAysyyBBBACAAAsr],+.+$-!]zyBABCCAAyxxABBCCBCBAyr],+.+%-~FzxBBCCCCAyssxCCCCBCAtsr];+++$;'FztBCBCCAxsssxACCACCAtsr{=+.+$;{/zxBBBBBCCABABCCCCCCBAAs^;@.+*;']ztCHGLEvHCCBtysr/F{)!;=&......*-']^zxBvLDHBACHDLDBxzr]!>+..",
|
||||||
|
".+$-)/zAGGLGGCCABBABBABGGLDGA^'%+%,')^yBCBCCBCByttBCCCCCCCBxr{-+..@*,-~]/rsACCCCCCCCCCAysr]);$+...@*-!)F/rsACCBHHCCCBCyysrF~;=+...%,-!)FrzyCBCCHHBCCCCAysz/{!>%..@#-;)]rzsACCBCCCCCCBBAysr]~;>&..+#=;~{FrsABACCCCCCBCCAyszF);$+...+$-~]ryBBxzr/F]{]//zsABAs/)=+..*;)FstBGCvGvHCCBCGLLELELtxrF~#..#;~FsBCCBCCCAsssytCCCCCCByz{-@.&$;)FsACCCCCBAyssyACCCCCBBxz{-+.+*;)/sCCCCCBBysssyABBCHCCBxr{;%.+>;{/sCCCCCCByszsyBCCCBCCByr{-..+=']rsBCBCCCCBBAAtBCCBCCCCByz~@.+*-~]ztBCvLLLGCBCCAxszr/F)!-$@.....%-!]rstAGGvCBBBCLLGAysrF'=+..",
|
||||||
|
"..#,;~:[IJJJJIrI^^^^[QQPJJ6KQF-@.@*-'(QJwwwwJJrQ//QrPJwwwJK[{;*...+&=-!(F[IKJJKKKzKKzKJKIQ|~-=+...@#>;~]}[QKJJJKJKKKKKPPK[:!-*@...&=,;~|F^QrKKKKPKKKKJJPKQ|~;=@..@#*-!(F[/rKKKKKKKKKKJJKI[|!-=@..@**,;)]}^rKzKKKKKKKKJJPI[('-#.....%=-~2IJPKQ2F|))(]}QIJPJQ1;*...&=;)[PJwwJPPIIIIKPJwJOOJPQ})-%+.&,-)[KwwwJKr[FFFF[IKJwwJK^]~=+.@%,;([JwwJJKr/FFFF^IKJwwJK/1!=...%,;(QKwwJJKr^F]F2^IJOwwJK[]!=@..%-;1QJwwJKKr[F1F2/IJwwwJI[{;*..+#-']/IJwwwJJzQ//F^IKJwwwJKQ(-+..&=-;{/QKJwNNwwwJJJJIQ/}]);-*+....+&=-!)}[QPJPIQQQPwwOK/}{~-#...",
|
||||||
|
".+%*-'_:QKPPQQ[}:1||11}Q5PIQ[1;@+@#=-(<6OwSSY8<[}}[[<6OSYO<}(c#...&$>;_1}Q5JOPPQQQQ<I6OOY54~;=&...@$,;(:[Q5OO8IQQQQIIPOYO5}~3=&..+%*-'|}Q[QIQQQQQQQQIPOR85}_;=&..@%>-'|[QQIIIIIQQQIIK8MMO<:'-*@..@#>-~|}QQIIQQQ[Q[QQP8OYO<1!-$+...+&=3(78OOOI<}:_((2[QKOOO5:c*+..&=c([6wSOP<[[[}[[IIIPPP<Q[2_-%..&=3_[8OJOP<Q}(_(|}[5JYSO5}(!*+.+%>3_46OwOP5[:(_(11[KOYYO52(;*+.+%>,d[OYwOP<[1(((|}[8JSYO<}(;=@..%=;(<6OwOP<2|(_(|2Q5YYYO<}(;*+..&>;_1<8YNYO<Q[:1|}[IPOYSY5}(,+..@*=-~(}<5RNNSwSwSYO8Q<[}|~-=&.....&*=;(11[QIIQ[[[5YR8<2:(;>%+..",
|
||||||
|
"..&=90bfimpXik77eb:bbbfgillhhfc@++#>cbgqWWUUUji7ff44hpWUUqieb;%...&=-cbf4hmoqomk7khhljqWWjgbc3&..+&*-ab4khmoZomh4khhmpZWWjgbc>%..+*>3ae4<hllhhhk7khhmoWUqjgdc3&..@*>;ae7hlhllkhk7khhmjWWqpfdc>@..@*,;df7<hllkhkkkkkhpqWUqifa9=@....#=9dgpqjommh7bee4hipoqjib3%...%>0bgjWUqpg477774hhlmmlik74b9%+.&=3dgqWWZp57ebadd1fiqWWqm7bc*+.+&>9dgjWWqnk7ebad1b7iqUUqi7bc*...%>cbgqWZqmh7ed0ddbgmqWWqieb;=@.+%>cbiqWWomk4bd_abegpqWUqiedc%...&=9abgjqUqqik4:bb47hpqqWqiea>...&*>-abfgiqqUWqqqqqqmllh7fbc3&.....@*,;def4hihhghijqUjifed0-#...",
|
||||||
|
"..#,cdehmoZoopnlk7444e4hmVVVhk0%.@*,ceiZWUUTUZmhkkkhlnWUUqpkba*+..#,0(4hVVnZZomlhkllXoWWUoifd9*..@*3cb4hlXXZZnmhkklVVoWUWoiedc#..&*3017lVlVVVlhkhhlVVoWUWjhea3#..@=3a:7VVVVVVVhkhklVmqWWWjhba3#++&=3a:klXVVVVVlhkhlVXoUUWjgba3%...+&*9cegmnmnnmlhhhmXonmmigbc#+..%9afioWUWpikkllVlllVmmVVVVkea*..&,cbioWWZnVke1bdbf7pqUUZj4ea>+.@$>cbiZZWZnVk4|bdbfkmZWUqmhba$+..%3cbioWWZnV<eb(beekpZUUZpkba=@..#,0eioWZZnVkeddbbehmZUUWpgbc*...%=9abhmqqqnVlk7447hVmooZjif0$+.+&$3cde4hmoqqjjpmjjmXXVVVk41c*....+&$3!b4kllXnnpojqWWolk4e_3*+..",
|
||||||
|
"..*!]rxADEEEELLGHAAysssyBCBCCx]*@%-c]KtDvLEELvGCABBtBvEEEDHsr]=+.+=']zxHHGGGvGAtyxAACCLELGAsr{=+.#-~]rxHHvvDDGAAyxyACGvEvvAs/(>+.%;)FzAHGGCCCCtyttBBCGvLvvAs^)=++#;)/ztHHGBCCAAxxxtACGDLvGts/)*..#;)/stHHHCCCAAAxytBHvDEDGAz/'*...+#>;_2rsyGDEvGBAHvDLGAys[{'=+.+=)/stLLELGAtACCCCBCBCCBCBCBs/,++*!{rtvLLDGCts^/^^zsHEEEEvxz]-@.@>'{zyvLLvvCtz^//rzxHvEEDGyr{-+..*!{KtGvLGHCtzr/FrsyGDEEEGyz];%.+=!{rtvDvGHBxs^/^rsyHvEEDHxr]-...%>;(^sACHGCHCAysstACCHHHHxr(>...%,;)/zytCBHHAyyyyAAACBCCCBsF-....+*-~]rytBBGvvDLEEEELHtxz/);&..",
|
||||||
|
".+$;]ryHLLEEEELGCBtxszsxABCCBy]#+&>']ryCCCCHGCBCCCABAHLLELAsr{=+.+>)/zAHLvvHCtszzzssAABHGHCAz{-+.%;)/sAGLvGHCxyzzzssxACHHHBxz]>++%;{/sAGDLGCBtsszssxxCCHHCAyr{=+.&;{/sHvLLGCAAszzzsyABBHHCAyr(>++*;]rsHGLLCCAAsszzsxAAHHHCtyr)=...+#=;~]^zsAGLLGHCHDLLvAsr/{;$..+>_/KAvLLvHyABACACBABCCCCCCAs]-@+=!FryCCCCCAyz/]F^rstGELLHyr]-@.@=;{rxCBCCCAsz/{{FrstGLLLtsr],+.+$;]ryCCCCBAyzF]]FrstLLEGHyr];%+@$!]zACHCCCByr/FF/KsALLLLtsr{=+..&=;)FzyCBCBCCBtyxyCCBCCCAs^)=+.+#,')/zsABCBAyssszsyBACCCCAy^-@...+#-)]zsACCCHLLLEuEEGHByz/{;*..",
|
||||||
|
"..%,!1[IONNNNNwJKQ/FF{]/^QrIr[~%+@*-!]QKKJsPKKKKKKr[QPwNwOP}(;*...*-(}PwNwwI[/:()(]{2QKKKKIr}_=+.@,;(}PwwwJI[F]()({]2QKKKKKQF_=..@>'1[6wNwJK^F]{){)F}QKKKKIQF~*++&-!|Q6wwwJI^F]()({]2QKKKKI^]'*..%-!:QJwNwJI^F])))(][IKKKKI/1'*....@%=,;~1}<OwwwJJJwSYP[}(';=#...#;_2<OwwwPQ/rKzKzrr/rrIrKIIF~#++#-!|[KKJKI^2]);;~(:<OwwO52|!>+++*=;([KKJKI^}|~;;'(2<wwNw5}(;#...%>;1^IKJrI/:{';;'(25wNwOP}|!>@..%-;|[KKKKQ/}('!!~{25wwwOK2(;*....&$-;(F/^IPJJKI/^IJJJKI^2]~-#...@*,;)F2^IKKr[2]:F:/QrIKKzI^{=+...+%*-!]F/rKKJwwwwNwNOPI/2{~-&..",
|
||||||
|
".+%=;(1<6SSNNYJ5[221__(|}[[[Q[!&+@#=c_}QQIIIIKIPP5Q[[5OSS8<|_-%..+%-0:5YSS6[:('!';;_(2[QIIQ[2(>+.@=9_15OwY6[1(!;;;'~(}[QIQQ[}~>+.&=;_ePRNS6[1(_!;;;~(}[QIIQ[1~=+.&=;(}6RNR8[:__'';!_12QQIIQ[1~$+.&,c(46SNY5[1(~;;;;_(}QQIQQ[:;*.....@#=,3!125OwYOO6OY8<1(~;-*&...%-01<YwSO5[:[QI<Q[2[[QQQQQ[:;*..@=;_}[IQQQ2__;--;;1[6SSO<:_;%..+&=9_2[IIQ[21_;--;c1<8SwO<:~3*+..%>c_}QIIQ[}(~---;_1QOSSO<1_3*@..&,9(}QIQQ[1(~---;~{<OSS8<|~-%....@&*-;_(:}<OOP<[[<PO8<}1('-=@...@#=-'(}[[QQ[}||(_||2[QQQQ[}~=.....&*,;_|}}QIIK66O8OO65<<[:'-%..",
|
||||||
|
"..&=;aegjWWWqX5hfebbdadbe47khec&+@#=;afkhlhhhmppopi47iqWWjiba3#..+*9afiqWWjgba;---3;ae77hhhkfd>+.@$cdfiqWqpgba9-9-90ae7hkhh7fd=+.&=cdfpqWqpfb_c-3-30de7khkhkfa=..&,cbfjqWqifba;3-33cde7khhhkf0$+.@,cbgpqWqifd0;9--3cde47hkk7ea*.....@#*,9cbfhioqWUqjpigba0->*&..+%3abgjWWqi7f7hlh74ff74hkhh4e0*.+&=3afkhlk7edac,--9dgjWWqieac#...%=9afkhhh7eda3-,9;bgjWWqgea3%...%=cdfhhhh4:b03,>9abgqqWjgbac*@.+&,0d4hhhh4edc3,,-0bijWWjiba3#....@%#=3aab7ioqmi4hioqpgeda9,#+...@#*9abe4hhhkfbbbdbb47khhhkfd>.....%*3cdb47hhlhhg7gimpjjjpgd3%..",
|
||||||
|
"..#,cbflnWWWoXlh4ee1bbb4kklllka&.@*30|7lXVVVVVnZonmhhXZUWZifdc%...$0d4pZWWjhbac33,39deklllllkb,+.&,cbgpWWWphba99>,-c(ekkllllkb,+.&,ab7pWWZj7ba99>-99beklllVl7b>+.%30egnWWWp7b~93-,3cb4kkllVh7d>+.#9aegoWUZpfdc9,3,9adekklVll4d>+....&*>30d14hmnWTUUoXVk4bac3*&...$9demoUUZphkklVll[4kklllllh40*+.&=cd4lVVVh4e0;339abhoZWqm7dc*+.+%,;b4lVVVk41ac39cabioWWqmfdc*...%3cb4VVllk71ac3-caeiZUWZm7d9=+..#3cb7VVllh4|dc-39abiZWWoifd3%....+@*>-0db4poZnVllmoZohedc9=#....@*=;a14klVVlk42ee44klllVll7b,+...+&=-ab4kkVVVl744<hVnZWWqif0*..",
|
||||||
|
"..*;)/stGLLvvHCtxzrr^rrxtBCCBy]*+%,!]rtBBCCCCHGHHHBHHvLEELts/)>..@-{rsHLELvyr]);;;~)/ztAABBCtr'@.%;]/yHDEEGyKF)!;;'{^stCCCBBx^;&+*!FIxvEEEGyrF_';;~{^stCCCCBy/;@+*_FKxDEEvtJ^]_!;;~]^sACBBCAy/;@+*~FzAvELLHK^(~;;;~]rstCCCCAs/-@...+*-;)FrsxBHGEEEEGGHAsr/{~-*...>)/zAEEEEGCCBCCCAyxxACCCCCts]-++*;{FsBBCCAyz/(~)(/rxDEEvtJ^(-+.@$;{^sBCBCCyzF{'){/zyvEEvHs^{=+..*;{rxBCCCAtz/(~~)FzADEEDts^)-&.+$!]rxBCCBByz/(~~)2zAEEEvtK^)=....+@#=-']^ztDvGGGGGDDHxIF);>#....#-;)/zxACHHHBtyyyxAAHHBCCAsF-+...+*3~FrytACCCAxssxAHHLELvtKF-+.",
|
||||||
|
".+%-~{rsACCCCBtyzrr^^^zsBCACBx]#@&>!]ryCCCCCBCBCBHCBCHLLLLAs^(=+.+-F^JtLLLvxz/)~;'~]^sACCCBBA^;&+*!]rsGLELvxz/)~;'~{/sAACBBCyr;@.*;FrsGLLuGyrF)!;')]rsBACCABx/;@.*;FryvLELHsrF)!;'){rsBBBCBBx/-+.='FKxGLLLAsrF)!;!)]ryBBACCBx/;&..+%=-~]/zxBGvvGvHvGvvCxsr/);*+.+=)}stLuELGCACCBABxyABBBCCCBsF,++*;)^sBCCCBxz^])){/KAGLLLBs/{=+.@=;{/xBCCCByz/])){/KtvLLLts/(>+.+$!{ryBCCCBxz/])){/KtLLLuAs^{-&++>!]ryCCCCtxrF{)){/KAvLLLAzF)>+.....@*-')]KyBGGLELLGHts/{'->%+..+&,;)/zyBHGLGCBCBBCCGGLvGCyzF-+...+*;~]zsBBBCCAysssxxCGLEDHsF-@.",
|
||||||
|
"..@=-;(2IKJKKr^FF()))(]}rIrKr['%+@*-!]/KKJKKIrIKKPKPJwwNww52(;#..+=;([8SNwO<11~;--;!)/rzzKzI^],++&,'([6wNw8Q})';-;;'{/rKzzKr/(>+.&>!1[6wNw6Q1(';--;']/rKzKzr/)=+.&,!1<6wNY8Q|);;--;~]/IzKzKr/(>++%-_:<JwwwP[|)';--;']/QzKzI^/_$....&*,-~{2[IOwwJPKJwwwJQ/1)'-%...%9_:<ONwwwKKKrr^^/F^rKzKKrQ}'*+.%=;)/IKKKr/F|)';!):<ONNw52);*+.+%=;)/IKKKr[F_~;;~(:KOwwO5}(;#...%>;)/IKzK^/](~;;!(2<wwwOK}(;#+..%>!{/KKKK^/|)';;!(}PONwOI2_,%......+@*=-'(}IPOwNNSJ<[]_;=*%@...+@*,;):/QJwwwJJzzKsJwwwwJI[{-*.....&>-~]FQrIKr^F:F:F[KOwww<2_=..",
|
||||||
|
"..@*=-~|[IIIQ[2:__~;!_1}[QQ[Q};@.@#=c(2QIP5Q[[[[[QIIJOwNS6<:_-%...*;_:5RSR8[:(~;;-;~(}[QIIQ[2~>+.@=c_15YSM821~!;;;;~(}QQIQQ[1'$+.&>cd}8RSY6[1(!;-;;_(}QQIQQ[:!*+.&=c_28YSR6[|(';-;;_1}QIIQQ[:'$+.&-;(48RRY5}1~!;-;!_|}QIIIQ[|!*+...@#>-'(|[<ORO6QIP6RY6[}1(;>#...#-~1<OSNSJPIQ[[[}::}[IIQQQ}1;#..&=3':[IIQ[}|(~!'c_|[PSSO5:_-#..+#>-~:[IQQ[}(('!;'_:[OSSO<{~-%+..&>;_}QI<Q[}1~';!~~1<OSSY<|!-#..+%=;_}[IIQ[11~~!;'(b<OwSO71!-%.......+%$=-'(}<6SNSY5[:_;,$#&+....@*=-!(|[5OSYPPKIIQPOSNS8Q:_;#....+%*-;(:}[QQQ}1|(1|:<OSSO5:'$+.",
|
||||||
|
"..@*,;dbglmih44ebd0_adb7hh5k7b9&+@*=cb4hmmlh7f4777hiXoWWWqgea3#..+%9aeijWqjgfbda~aadb7h5llk7ec*..@*9afiqWqjgfba~aaadb7hlm5k7e0*+.@=cafiqqqmgeb_a0aabb7hlli<fec*..&=3afiqqqpgebaa!aade4hll574bc#.+&>0bgpqWqigbbaaa0ad:7hilk77d9%...+&*,;ab7gijqoihhimqjpi7fba>#...%-cbgjqWqomlh774eee4hillkhfd3&..&=3abkhhh74bbdaaabbijWUqiba3%...&>9a:7hhh7ebbaaaadfgjWWqiba3%...@=3abkhhk7eeddaaabfgoWWjiba-%...%=3aekhhk7f:daaaabeiqWWjgba-&........@*=-caegpUUUjieba9,$%&+....@#=;abfgpqWWomllhlmpqqopfba,%....@*=3cdee7hh<7ebbbefgjZWqgfc$..",
|
||||||
|
".+%>30d4mnonmlk74ee:e47hmnXmhe9@.+$3abhnnnplhk774klVXoUTUqifdc*...$9abinoZnVk74e:1e47lpXoml7ea*+.@=9afioZonlk44e1e24khnnnmh7ba$..&=3dfioZoXVk7e:e1e47lpnnmh7ba*+.@=9afmnooXlk4ee:eeekinonmh4bc*..%,3dfmoqonlk4e:1eef7lXnnmh4dc#...+*=3afimXnonnlkkhmnonmmmgbc*+..&,0bgpZZZoooml<k7Q7hmnonVked3%..&$9'ekVVVVhk4eb1eehioWWqpfd9*+..&=9dekVVhlhk4eeeef7mZWUqifd;#...%>9_ehIVlll74eee:f7mqWWqifc3#...&=c_ekVVllhkeee1efhmqWWoifa3%........@$>9a(e7pWUUqi7:d03**%@....%=9ab4klpWWZonXVVVVXmpigfac,&...&#=30(4[lllVl<kkk77hmZWWqmfd>+.",
|
||||||
|
".+*;~]^svvELGHBtyysxxABvDEDHxz~%@&,!]zxDvvDHCAxyxxBCGDEEEEts[)=..+=!:rxHCHHCCAtyyxxAAHDDLvts/_>+.&-~]rxHvHHCCAAyxyxAAGvDvvAs/_>+.#-~|IxHCHBHCBAxyxyAAvDLvvtz/)=+.%-'FzyBGCHBCAyxxxttBGvvDGtz^)*..&9~FztHHHBCCAyyxxAtHGDLDHxKF'*..+%-;{ryvvvvGHtysssxCHGvvGGK],+.+*c)/sAHGGGLvvHAAAAAHGvDDtyrF;$..%,~]rxACCCCAAyssxyAGDEEGtK/~=+..%-'FzyACCBCAyxsxxtAGEEEEtIF~>...%-)FzyCCCBCAtysyyAAHDEEvyI{;$+.+#-)/zyCCCCBAxsssytBGDEEvyI{'$.......@*-!)FrsAGuEELAxz^]~;,*%...+>!{/syAHGEELGBCCBCCByssQF)!,%...%>;~FzxtCCCBCCBBBCCAvDEEvGKF-+.",
|
||||||
|
"..*;)FzxvLELLCCCBBABBCHvLvvGs^~&+%-']IADLLGvCByyyABCHvEEEuAsF)>+..$;(/stCBCCCCCABBCCCGvLGGyz/)=+.@>!{rsABCBCCCABBACCHGvLvGxzF~$++@>;)/ztCCCCCCABBBBCHvvLvHyzF'*..@>'{ryBCBCCCCABBCCCCHvDvHsz];*+.&,;]rtACCCCCCCBBCCCCGLvGtsr]!*...+$!{/JGDvHAxszrrzsytHGvDAK{=+..*;)^sBCBCvDLGCCCCCCGLLLLAs/{;%+.@>;]^sAABBCCCABABCCHGGLDyr]'>+.+&>;{rsBBBCCCBAxACCCGvLLDyr{!$+..%,!]ryAAACCCBBABACCHvLLvxr);*+..%-']rxAACBCCCABABCBGvLLGxr{;*.......%>;~]/stHLLEELHAsrF);-,#@..+=;]/sBCCvLLLHCCCBBAxsrF{)!-$+...#-;)FzyCCBCCCCCCBBCCvLELDts/-@.",
|
||||||
|
".+&>;(:<OwNNwwJJJPJPJJO6O6P<2~>+.@=-~15wNNNwJKIFF/^IPwwNNY52(;%...&$-~1F[^QKKKJPJPJJJJP6P<}(!-#...@$-~]2^QrKKKJJPJPJJOP6P<2(!>&..+&*-'(F[^QrKKKJJJPJJ868P<:(;>&...#>;)]2^QrKKJJJKJPJJPP65Q:_;>@..+#=;~F}^QrKKKJPJKJJJJJ6PQ:_;,&...+&=;_}[5<<[2{_'~~)]}[<5<4(;*...&>;)2rKKJJJJJJJJJJJJO685[:);=+...&=-)]F^QKJJJJPJ6JJJJJJP[_;-&...@*=-)]/^IKJJJJPPJJJOOJ6P[(;>&...+%=-)]/^IKJJJJPJJJJJJJJK[_;=%...+*=;)]/^KJJJJJPJJJOJJJ8K}_->&.......#>-;~:QIJwNwNNOPQ}(~;,*@....*-~]QPJJwNwwJKKrQ/2{~~;-==*@....&*-!([IJJwwwJJKrKKJJwNNwO5:_$..",
|
||||||
|
"..%=;(2<OSNNSSwYwYYMMMO8<Q[:_-*..@*-a1QOSSNNY8<}1|}[<6MNSO<1!-#...+#=-;_(|2[IPOOYYYOO85[}|(c-$+...@#>-!(|:}QKPOOYYYYY65Q[2(;-*@...@*=-;(_:2QKPOOOYYOO6<[}|_;-#+..+@$=-!((1}QKPOYYYYYO5Q[}(~9-#+...@*>-'((12QIKOwOMYY86<[2(_;>#+....@#>3a(1:((';;->--c'(111_c-#+..&*,'([QIIPK6OYSYSYYO8<[2|~-=%+...&*=-'(([5OwYYYRSRYO6<<[|~-=&....&*,-'_|}POYYRMRYYY8P<<41'-#+...+%*,-'(:[6OwYYYRRYYO6<<4|;,>@...+&*=;~(|[6wYSRRRRRROP<<}('-#+......+&,;~(158MRNNNNMY5}|_;-*@...+%-_:<OYSSNSO5<[[1(!c-,=**#@+....@$,c|[8YSSNMY6<QQ5ORwNNSO7|;*+.",
|
||||||
|
"..%>0b7ioWUUUUUUWWWUTUqpg7ed0,%..+*-cbiqWUUUWjgeb1e4hmqWWjgba-%....&$,90_(e7hmqWUUUWqmhfbd09*%+....&*,90_be4hmZUUUWWWph4fd09=%+....%*,-0a1e7lpZWUUUWqigbbdc3=%....+%*,9a_bekhpWWUUUUqigfba0-$&....+%>=9cdbehinqUUUUWqmgffdc3*%.....@%*,;00aa;3,>>$==,30caa03=%...&*,cbf7hhmmnoWUUWWqoi47bd9-#@....@#>>9adfioWWWUUUUWjmh4fd0,$&....@#>,;abfpqWWUUUWWWjihffac=#.....&*=-9abepqUUUUUUWWjih4fac=$&....&*$-9abgpqWUUUUUUqjik7fa3=%.......+#,cabfiqWTTUUTTWjgeda-=@...@#,0fiqWUUUWjmk4eba;3==$#&@......@*-;bijWUUUWqph7hpqWUWWWjgb3%..",
|
||||||
|
"..%,0ekmoWWUUTUUTUUUUTWph4edc>%..@#30fiZWWUUWoifebf7hnZWWqibc>%....+%=-0adekVpZUUUUWZph4edc->&....+&$=-0adehVnZWUUUWZjh7eb09>#.....@*=39abfhVnZUUUUWZmh4bdc,=&....+&*,90ab4kXnZUUUUUZm7f1d9,=%.....@*,-0d14kVoZWUUUWZmh4edc,=&....+@#$,9c00c9>=*$$$$,,900093*&...&>>017llVXnXZWUUUWWomh4edc,$@....+%*--cdfpZWWUWUUUWZmhkebc,*&....@&*,30d7pZWUUUUUUWomkked9=%+....@%$=9cdgmWWUUUWUUUomh4ed9>#+....@#*39cb7oZUUUUUUUWoVh7ed9=&.......@*3cde7pZWUUUUUUUoiebac=&...@>9aepZWUUUWZVlk4ba3>$$%@........@*,cbiZWUWUWZphhlpWUWUUWqgd3#..",
|
||||||
|
".+*;{rsAGLLvLLEELELELEvtxKrF)3*.+&>;(/yDvELEvvyz^^rsxHvLDGs[);*....+%=-!)]rsAHDDELEDDtsI/F_;-#.....@=-;!)FrstHGLELLLvHxzr/);>#.....+*-;!)FrxAHGLDEELGtJr/]_;>%....+&$-;~)FzsBHDLEDLvvtsr/{~;$&.....@$-!)F/zyAGGLLELDDAsz^F~->&....+&#=-;''';-->=***>,3;!!~;;>%...%>;)^sBCCCCHHLLLLLLHtsz/]'-=@....@%$-'_]rxDLLvLLLELHAtszF~-$&....@%$3;(FKALLLEELLLLGBxsrF~;*+....@#>-')FzADLELLLLDDGBAsz]~-$+....@#>;')FKADLLvLLEELGAysr]',$.......&=;~F^sAvLLELLELvHxz/]);%...@,;{rxDELLLDGtAszF);-$#@+.......+%>;_/sGvLLLDGHttAADDLLLDHK:-#..",
|
||||||
|
".+*;~FrsxBABBBBAHABBBtwsrF])',&..+*;):rsAttAtsz/]]F/rsytxs^{',&.....+%=;!)FrzsyAAAAtxsr/{)!-=&+....+&$-;!)]/zsABABtAysr/])',$@......+#>;;)F^zsAABBAAsz^F{';,%+......+#=;')FrzsABAAtAyz/F{~;,%+.....+@$-'){FrzsABBAtAysrF{)',%+......+&#--;;--$%%&&##=>--;;->#+...@=;'/zytAtytBCBBBAtyz/F{~;,#+.....+#=;!(FKyABBBBBtAysr/]);,#+.....+#>;;(/zyABAHBBBAxsr/F)!,%+.....+%-;!{2zxAABBBBBxyzr/])-*&......@%>;'{^zAABBBBABxyzr/]);,&+......@#,;)]/KytBAABAtysr/{);>%...@$;)1ryAABAtssr/])!->#+..........@$-'{rsAABBAyszzzsxAAAyxz/)-&..",
|
||||||
|
"..@#=-;~)({|{|11:1|((()a!;-,*&+...@*,-!_(((((_!;---;;~_(_~;-=#+.......@*=-;'~)((1(((_~;;->=&@........@&*=--;'~)((((((_!;-,=%+........+@*=,-;'_((((((_!;--=*&+.........+%=,-;~)(({(((__!-->*%.........+%*,--'~_((((((_~!--=*&.........++&&&%&@@++..+.@&#$***%@....+&>-']FFFF{){{{{{(((~;;->$&+........@#$,-!_({({({((__';--$&+.......+@#=,;!_(((11{_()_!--=#%+........@*=-;'()(({{{1))~!;-,*@........+&*=,;~(((1111((_~;;-=%@........+&#*=--!)({|{(1(((!;-,*%+...+@#,;!_((((((~!;--=#&+...........+&*=-;_()(|(((_~__)((((~0-=%...",
|
||||||
|
"...@#*=--------;;;-99---,**%&+....+%*=>,--,3--,==***=,,-,>**&+.........+%#*=>--;;3---,=**%@++.........+@%*>>>------,,,,**#&............+#*=>,-,-----,>**#%++...........@%#$>>,---9,-->>**&+............@%*>>,------>-,>=*#&+.........................++++++.......@%=-!___!;--->---,--=**#&@..........+&#>>,,--------,>>*%&@..........@@*$>>--------,,>=*%+..........+@%**,-----;----=>$$#&..........+@&%>,>----;9---==**%&...........+&#*==-3-----3-,,=*#%......+&*$>=-----,->**#&&..............+%**>>---------,3----,==*#@...",
|
||||||
|
"....+%#*$*>*>,>>,,==>$$***#%@.......&%*$$=$**$$######***$$%&@...........+&%***>=>>=$>$*&&@+.............@&#**$>>$>==$$$*&@+.............@&%##$*>>>$>*$*&@+..............@&#**$$**>*$=**&@+.............+&&%**$>$>$>$***%&@.........................................@*=39333,>=,=*$==$$*&&&+............+@&#$*>*=$$$$*=**#&+.............&*$$$>**$>>>**$*%@..............&%*$$====,>*>***%&+............@@%*$$=>>=-=*>**#%@.............@%#$***,*,$$*$$*#&@+........@%*$$>$$>*=$*&@.................@%%#***$>$=$>>**=$*$=*$%@....",
|
||||||
|
"......@&*$*$***********%%@++.........@@%*#****%&@&&@&%&%%#&+..............+@#*##$***%*&+.................+++&##%**##**%++..................+%#$****%*#@+.................+@&%$$$$*$*##+..................+@@%%#*****$*%%@..........................................+@**>>,=$>$$***##**%&+................@&#***$=****#&@++..............+&##*****###$*%&@@..............+@%**##*$#**##&@@...............+&%#*#***%$$%$#@@+.............++@%#$$**$=*$*%&@@+..........+&%*%**%*#%@+...................+@&#*$*****#*$*****##&@.....",
|
||||||
|
".......+@%&%%%%**##%%&@................+&&%%%&@+..+..+.+@&@.................&%%&%%%%&@+...................+.+@%%&%%&&%&.....................+@#####%%@+...................+@@%######%%+.....................&&%%&%&&%%&&+...........................................+%*$$*%%%%**#%%%%&@+..................+&%#%%*%%#&@+...................@%&#**%%%&%%&+.................@&&%&%&%%%%&&+...................+&%%%##&&#&&&+................++&&&&%&#%*##@...............+@#%%#%&#&+......................+&&&%&%&%&&%%&%&#%%&+.....",
|
||||||
|
"..............+.+........................+...................................+.+................................++++++......................................................+@&&&&&&@...........................+.+...................................................++++++.++++++..+......................++++.++.........................+.++++..........................++..............................++.......+.......................+.+.+.......................+..+............................+.+.++++..+.+..........",
|
||||||
|
".............................................................................................................................................................................++++++++........................................................................................................................................................................................................................+..................................................................................................................",
|
||||||
|
"...........................................................................................................................................................................+@@@@&&@&+.......................................................................................................................................................................................................................+++.................................................................................................................",
|
||||||
|
".........+@@@@@++.................................+@+@+........................+@++........................................................................................+@%####%%&+...................................................................................+++@+@+..................................+@@@@++....................+@@@++++....................................................++@@+++.................................+@++@++.........................+@+............................................",
|
||||||
|
"........+&%##**#&@+...........................+@&%%**%%@...................+@%%*#*#&+.....................................................................................+%$*,,>,=>$%@.................................................................................@%##**#*%+..............................+&####%##&+.................+@***$*#&@+.................................................@&*#*$#%@+..............................@&#****%%+.................+@&%#%**%@...........................................",
|
||||||
|
"........&=--;;;;-$#&+.......................+@#=--;;;;,$&+...............+%=--;!;;;>$%@...................+&#******%%&@..................................................+#-;'~{){)!;=#+..............................................................................+%=--;;;;--*&+..........................@%*=-;;';--$#@..............+&==-';';;>##@..............................................+&=>-;;;;-$#@...........................@&*>-;;;;--*@..............+@#=-;;;;;-=%+.........................................",
|
||||||
|
".......%$-;!)]])!-,=#@....................+&#*-;;~)]]);>*@..............+%>>;')]]]~;,*&................+&&#$$-------->*%+.................+@@&&&@+..++...................%=;'{F/^//]~-$#+.............................................................................@*,-!~{])!;-=&.........................+&*=-;)]])~;-=#@.............@*,;~)]]]~;-*#&................+@&@@@@@+@@@.................&$>;!)]{);-=$+.........................&*$--~)]{~!->$&............+%==-;){]{)'-$%+.................+@@@@@@@&&@+...........",
|
||||||
|
"......+&#=-;!)(~;,=$%@+...................+&#*=--;~)~;-*%@..............@%$=-!){_)'->*&................@%%#>=->>,,,,->=#&+..............@@@&&&&&@@@@@@+.................+%*-;)(F[F});,*%+............................................................................+&*>-;!)();,=$%+........................@&#*,-'))';-=$#@............+&*$-;')_)'-=$%@..............@@&@&&&&@@@@@&++..............+%$=-;~_)!-=**@.........................@%$>-;)))';-**&+...........+&*=,-~)))!;>*%@................++&&&&&&&&&&@+..........",
|
||||||
|
".....++%*$-;_((_;->*#&+..................+%#*$>;!~~((',$#+.............+&$=-;~~(1(!-=*%+..............+@#*>,-;;;-;;-;-,=*#@............+@&%#%%%&&&%&&&@@................@%*,;_1}}[1(;->*&............................................................................+&#$>;'((_;-,=#&+......................+&#$>-;_((_;->*&+............@%*=-;((1(~;-**&+............++&%%#&%&&&&&%&%@@+............+%*>-!(11~;->*#+.......................+&#*=-'~|(~-,>#%+..........+@%$>-;_(|(~;,$#%+..............+@&&##%&%%%%%%&@+........",
|
||||||
|
"......@%*>-cdbbda;9,$#@+................+@%$>-cadbbb_a-*#@............@%#$,;adbeebdc9=*@.............+&%$=,9cdddadaaa0;3=$%+..........+@%$$$=**$$#$$##%@+...............@#>3cdb4774ba3>$#+...........................................................................@%*>,;0beba!93=%&+.....................@#*=-;abbbd!3>*&.............&#>,;abeebd0;>*#&...........+%%#$***$###$#*###%@+...........@%*>-cbbeda;9,*%.......................@*>>-cabbb_c-*#%+..........+%*=-;0bbebbc9>*#&.............+&%#$$$$*####*$$#&+.......",
|
||||||
|
"......@#>=cae[k4ee(ac=$&................+%=,3'be4444ea9>*&............@%*-ade47kkke(a9=*&............&*,30~bf7ggkgg74ebac=$#+.......+@%=,3ccc93=,33cc3=#@...............@*,cd47kkk74bac=*@...........................................................................@%$>90b4444e{ac3*%@...................&*=30db14k4ea93$&............&*>3ab47kkk4eda3=*&.........+%*>-cc093,,,3cc-3=*$&+..........+#$,ca:474eeda9$%....................+%*>9aa|e4k4ba9>*&@.........+%*>9d:27kkk41d93$%@...........+%*,39c'c3-,,-c99=#@+......",
|
||||||
|
"......@*-;)FzxCAAAsz]~-=%+............+%*>;~]rsACBAsrF'-,#+..........@$-;)/sACBABAAsr]!-=@..........&=-~]/zstGvvvvGHAAsr]~;=%......@#=-;){/^rF{)){F//{;-$@............+&$-']ryBCCAyszr]!>#+............+&&&&&&%@@@&&&&&%@+.................+@&%%%%&%&&&%@+...........@#-;~{^xABAxyz/);-#%+...............+&=-~{/zyyAAAs/);-#..........+%=-']rstBBCCAAs^);-$@......+@#-;~{F/r/])))]/^F)~;-$%+.........@=-;)]zxCAAxsr]!-#.................+&*,;~]rzyABByr{~->*@........+%>;!]rxBCCBBAsr]~-,#+.........&*-;)]F/^^{)))]//F~-$&+.....",
|
||||||
|
"......&*,;~FzyACBBts/);-*@............&#=-!]/zACBBtsr]~;=#+.........@#>-']rxBBCCCCAxrF~;=#+........+%=;)/zsAHvDLDLDvCCyz/);,%+.....@*,;)]/rzzrF]]FrzrF~-=%+...........@#>-)/zxBABAyyzrF~-$&.........+&##$$>>>$*$$$*>$$$**%+............+@###*====>,=>>$**&@@.........+#>-!)rsBACBAyr]~-,*#@..............&*-;)FzxyBABtz/);-%+.........+#=;)]zyBCBCBCCxz]~;,%+.....+*>-'{F/zzr/F]F/zz^])!;-$&.........&#-;~FzyBCAByzF)-$%................@*>-!)/zytBBAsr{'-$&+........&=-;)/sBCCCBCAyz/);,#@........+#,-~)F^zsz^F]F/rz/);>*+.....",
|
||||||
|
"......&%$=-!{/^rrr//(;,=*@...........+&#=,-~{F/rKr^F(~->$@.........+&#=,;~]/rKKrIrr/1);>#&+.........&*-!):[QP8JOOOJJKI/])!,*@......+%*-;'(]F}F{_){{F]);>*@+...........@#=,;)F/r^r/^FF|~->%@........++&#*****=$*##$***=$***%@+..........&&%**>>>>=>>=*=$*$#@@.........+&*>-;)F^rrrr[]);-=#%&+............@#*,-!)F/rrrQ/]';=*&..........@#*,;)F/rIKzIrr/F);-$%+.....+#*,-!){F}F|_({{FF{)';,>#%+........+&$>-~]F^rrr/F~;>*&................&$=,;~{F/rr^/F~->#&.........@%*=-!(/QrKrIrI/F);-$#+.........@*=-;')]FF]_((]F1);=*&+.....",
|
||||||
|
"......@%#>,;_(2}[Q[}(;->#&+.........+@%#$,;~_:2[[21_~-,*%&.........+&$>-;_(2[[[[[[[}:_-=$&+.........&$=;(:1[[<<<PKP<Q[1(;->*@.......&*=;'(_:1:|(|(:1_!-*#%+...........+%$=;~1}2[[Q[}(~;-*#@........@%#*$,>,,>,,===>,,>,,>=**%+.......+@&#*$>=,,--,-,->,>=*$&+.........@#=-;_(:2[Q[[1~!;>*#&+...........&**=-;~(}[[[2}|~;,>*&.........+&#>,;_}[[[[[[[[2|~!-,*&.....+%$,-;~_|}::(((|111(~;-=*%+........+@#=-'~112[[}|_-,$&...............+&*>-;~|}[[[:|~;,*#+.........+&$,;'(1[[[[[[21|~->*@..........@*>-;_(|::|1((_|(_->#&......",
|
||||||
|
"......&#*=-cdb:e7hk4ba;,*%@..........@$*,-0d:f4474eda9,$#@.........+&*-;0dbe474f4e74eb0,>#@........+&$,;def4747khhhk4fbd;>$#@......@#=-cabbeeeeee1eeba;>$%+..........+&*>-cab44<kh4ebdc-$#+.......+%*$,399c9c;c9999c9c;c93>*#+.....+&##$>,3cccc;c00;09cc3=*%@........&%$$-;ad1f4kk7fbac9=>*&+........+&%*>,;abb47<ke:ba;,>=%+.......+&$*,90bf74444477f:bac9=&.....@%$,90abbeebbbb:febbaa9>*%@........+&$=-0d1ee774edc,*%...............@%*-cabe4<74bd0->%&+.........@%$,;0be4744ff4eba3>*&.........+@#=-cabeefeeeebeda;=*@......",
|
||||||
|
"....+&%=>c'dbe4<lVlk4|a93$*@........@*=-ca1e4k<lkk4ed!9=*%.........&$,c_be4kkkkkkkkkked;,*&+.......@#=cd:4kkkkkhVVVlh4eda9=#&.....@#=3ad:e4kkk7k77774:a3=*&.........+%#=3cae[khllVlk4dac,*%.......&*>3cadb(bbddddd(b(bbd(ac9=#.....&**,39c_dbb:b1b:b(bbda03>#+......&*$=3cd1eekhlVhk4:dac3>$%.......@#*,3;a_b}kklllh4e1dac3=%.......@*=,3a(4hIlhkkk<hk4e1d03#+...+&$=3a(:ek4kk[474k74ee(ac>*@........@%*,ca|e4<llh7ba3>#+.............&*>3;db2klllkedc3=$&..........@%=3~be7klhkkkk4e(03*&.........+%*>9abe4kkk77744ed9,$&......",
|
||||||
|
"....&=,;)]^zsxtBCCHAAsr]);-$&......@*-~{/rsxACACCBtxr/{;--%+......+*-!{rzyACCCABCCCAts/{!-$&......@#,;{^sACCBCCCCHGBCAsrF~;,*+....%,;)FrssAACHBBCCCAxz/);-#+.......+%-;!{/rstCCCHCBAxz/{~->%+....+$-!{/zsssssszszssssssssz^]'>@...%>-')]F/zzssyyxsxyssssz/{!,&.....&$-;~]/rsyyCCHBCBAyzr/]);-%.....@*-;~{F^zsAACHCCAAxsz^]);-%.....@*-;)]/zyACACABHCBBAszrF);%...+*;']/zsyBBBABABBCBxyzz/]'-*+......@*,;~{^zytACBCxzF);=&............&$;'{FrsxtCBAAz/);-$@..........#,;)FrstBCABBBBys/{;-%.........&*-!)FrstCCCCBByxz^);-%......",
|
||||||
|
"...@%=-)]rsyBGvGLGLHCAs/{!-,#+....+%-;]/zsAHvGLvGHCByrF);-$%+.....&=-)FzyBBGGLLGvHCCBy^{'->*&.....@=-;{/xtCCCGLLvLGHCCxz]);,*&....&-;)/zyBCCvvGLGCCCAz/);-$&.......@$-;]/zyACvvLvLvCByzF)!-=#@...&=;)/sAHGGHHAAAAABHGGGGHAxr];#..+%-;)FrzstCHGHGGGGGHGGGts/);*....+#=;~]/zytBGGvGvvGHCtxzr/);$+...@#=;']rzstCGvGLLvGGHAyszF);*....@#,;)FrsACGvGLvLGvvGCBys/{;*+..%>;)FrxyBCGvvLGLGHHCAAsrF~-=%......&*-~)/rxGGLvvGHs/);>#...........@*,;)FzyHGvLLGHs^{!-#@..........%-'{/zxBGGLLLGHxz/);=#+........&=-']/zxBGGvGvHAyz/);>#+.....",
|
||||||
|
"..+@%*,;{}QKJwNwNNNwJKr:);-$%+....+&=-)][QKwwNNNNwJKI/_;->*&+.....&*>;(/QIJwwNNNwwwKr[{'-=*&@......&*=;)/IrKwwNwNNNwJK/}~;,$#&...+@*-'{/IKJwwNNNwwJJr[('->*&......+@*=-'][IKJwNwNNwwKI/('-=$%+...@=-_}POwwNNwJJzKJJwwNNwwJI[{;%..@%>-~|F^IPwwwwwNNwNwwNNY5}~-#....+#*-;(F[IPwwNNwNwNwwPI/}]~-%....@#*-!)}/IPwwwNwNNNwwJKQ/1'-#....@%=-;1/QIJwwwNwNNNwwJKI^]'-%...%*>;(FQIPwwwNNNNNwwJKI^});-*@......@#>;!(25wwNNNw6[_-=*@...........@#=-!(2IOwNNNwJ[|'-=&..........+@*-!)1QPwNNwNwJQ1~-=#&.........@%>-'(:[6wNNNNwP[|~->$&......",
|
||||||
|
"...@&$=;(}[<8OSSwSSOOPQ}(;-=$&.....%=3~1}Q5OYSwwSwOP<[(!-=$#+.....@*=;_}[Q5OSwSNSOOPQ[|~;-$#@.....+@*>-_:[QI6YSNNwYO6KQ:(;-=*@....@$>;(}[<8OSSNSSYOP<}(~-=$&.......@%=-_1}Q5OOSwSSYO6<[1';-*%@...@*-015OwRNSYO8KPPOOwYMRY65[:;*..@*,9_1[Q<6YSSRRMRSSSNNNY51~-%+...@*>-'1}[<6OYNNNwSwYOP5<Qe(;*+...@*>3!:}[<6OwSSNwwSSOP<<[:~;$+...@$>-~1}<K8MNwwSNNSSY65<[:~;%...&=-!|}Q<KORwNwSNNSRPP<Q[|!-=&......+&*-c~1<8RNNNN64_3>#&...........+&>-;_|<8YNNNM64~-=$&...........@*=-;(15OSNNNR52(;-$@+.........+%*-'_(}5OSNNNR5}_;-*&++.....",
|
||||||
|
"...@#*,;de47iipppmpmppmgbd0-*&....+%=;a:7hhipppppmpppied0;=*@....+&$>cae4hiipppjjpppmgfda3>*@......@%>30|f7h5ppppjpmppi7bd;3*&....@*>cde4hipppppppjppheda3=#+......@%=-ae44hippppppjnmifba;,*@...@*3cbgippjjjoqqqjXppppppppmga$+.@*-afgppppjjjppippjqUTTqjed9*....@*=9dgijjjopjppijjpompppgfc=+...&*-0dgijppjjpjipijjjXppigbc=+..+@*,!bgipjojjjjpijjojopppgb0=...%>9afippjojppippjjojjjpied9,&......+&#>9cdfipqqTWjgd9>#&...........+&*-30dfimqWTWjgac,*&...........@#$-90deijqUUqjea9,$@...........&%=-0abgijqUUqpba;,*&.......",
|
||||||
|
"...&%>3a14klll5hilhmooomked03*@...+#-0bekkllhh5ihmXZomhe|ac>&.....%*,cb4k<h5hih5kmnZoXkeba9=%+....+&$>cd:47khhhhhilXoZXi7edc,&...+@>3a17kh5h5hihimoZom7eda9*&+.....&*>c(4kll5hhh5hmnooph4bdc=&..+&=3ab7lVVVXmqWUWWnmlhhhmmoqib>+.%,0bgpqZZomlggf4ghVjUTTTjgb0$+..+%*90bioZWqnmmhihhVVXZZWZngb3%..+%,9dfpoWZoXm5hhghhVnoZWZpgd3#..+%=3afmqZWonm5hghhlmnoZWqngb,@.+%3afioZWZnm6ihghlmnoWWWoiea3#.......@*=-9abfgjWUWqgb03=&............@*$,cabegpWUUjgbc3*&...........+&*,,0abfijWUWjgb;=*&...........@%$=3;abfipWUWjgb9,$&.......",
|
||||||
|
"..+#,;~]zyAACCCBBABBDDvHxsr/~-%..+#-'FryBACCBBtBBBGvDGAyz/{;-@....*-'{rsACCCABABAHHLDvtyz/{;>&....&#-;{/zxtBCABBtABGDLDAxzr]!-@..+%-)/zyABCBAABBBAvEvGtszF);$&...+&=-!]rsACCCBBABBAGLDGAyz^]'>@..#-~FrxBCCCCCDEEEEGABBBBCvEEwQ-&+*!]zADEELGCAsI^rzsAHuuEuuV/{,+..@=3~FKtEEELvCAAyxABBGDEEEvAr(=++#-!{/sGEEELHCtyyyyBAGDEEEvyr($+.&=3)FsHvEELGCBtyxAACCLEEEGyr'@.+=)/stEuELvHCAyxAAHGvEEEvxK]'=.......@#>3'(}rsGLEuvyI{!-$+...........@#>-'(FKsGuEuDy[{'-*@..........+%=-;!|2ryGuEEvs^{;-#...........@&=,;~|/zyvuEuGK^);-#.......",
|
||||||
|
"..+*>;)/ztBCABCCABBBGLvGAxz/);*+..%-)]ryABBCCBBBACHLLGBss^]!-#...+*;!]ryBBBBBABBBCGLLGBys/{!-#+...&$,;(/zyBABCBABBCHGLGBAsrF~-#..+*;)FzyBBCCBCBABHvLLHAxz^);-#....%>-~]rxAABCCBBBACGLLvBxsr]!-%..%;)FryBACCCCvEEELvCBtAABGvEA^;++$)FztHLLLGAsr/FF^rsxtuvGtz/)>@..@$;)FKALELLCCBAxyyACCLLELvtz]>++*-~]rsGLEEGHCBAxxyACHLLELGtr{=..&>;_/KGLELGHCCAxyACCCGLLuGx^;&.@-)/JALEELHCCBxyxBCBvELEDAzF'$+.......@$-;~]^JtLEEvxr]'-$&...........@#*-;)F^stLLuvyr{!-=&..........+&*=-;)]QsGLEuGs^{!>#+...........+%>-;)FIsGLEDHs/{!>%.......",
|
||||||
|
"...%=-;(F^QrKIKKPKPJwwwPQ}]);$&...&=-~]FrIKKKKIPIPwwwOI[F(!-*&....&=-!(//rIKKKIPI8OwwPI2F)!-=@....@&=-;)F/QrIKPKPIPOwwOP[/]_-#&..+%=;~]/QrKKKIKIPPwwMJQ[F);,*%....@*=-!(/^IrIKKIPKPOwwOI}F|'-=&..@=;_]/QrIKPJMNSNwJIIQrIIJMY81>+.%-_:<JwwwP[}(!;;'_(:[[4[2(!-%...+#=;~26SwNwJKI^^Q^IKPwwwNO<1;*..%=-'1[8wNNwKKIrQ^QIKPOwNwJQ|!#+.@*,;([6wNNwJKrI^[/IKJJNww8Q|-+..*;(}6wNNwJKKrQ^QrKPwwNNO51_;%.........&*>-!)25wNwOQ|!->&@............@&$>-!([8www8[|!-$#@...........+%#*=-'(}6www6[(;-*%+............+%$>-!|[6wSSP}(;,$@.......",
|
||||||
|
"..+&*=;_:2[Q5688Y6YRMNM5[:)!-$&..+%=-;(}[QI66OM8MMMNM6[}|(;=*&....%>-'(}[QI686M6YMRNM8[21_;=*&....@#*-;(1}[Q868R6RMRNRO52|_;-$@...#,-_|}[Q58OY8OORRNR5[:__-=#@....@%$-;(}[Q<8O6Y6YYMNM6<2|(;=*@..%,;_1}QQI66MRNNNR8KQQQ<<8MM5b=..&-!(<8SSO<}(_;;-c!_d|:21(~;-%+...#=3a15RNNOPIQQ[QQQI5ONNS8[(c*..&*-c_e5RNNOPI<QQQQQQPOSNR84(;%..+*=9_f8YNSOKIQQQQQQQ6OSSY84~,+.+%;_b5MNNR65QQQQQQIIOMNNO<1'-%.........@%=,-'1<YNR84_;-*#+............+&%$=9_15OSR64_;,*%+............+&$>,-_|5MNR8e_;>$&+............+@**--a15YNR5e~->%@.......",
|
||||||
|
"...&>,cdekhimqUUUTUUTTqjgfba3=&...%=;0b44iioqUUUUUTTqjgfbd0,*&...+#=3ab77imqWUUTUUTTUjgfbac>*&....+#*-0bekhipWUUUUUTTTqifbbc3$@...%>;de4himqqUUUqTTTUjgeba9=*@....@*=9ab4ghijqUUUUUTTTjgfe_0,%@..&-0be4hhmoqTTTTTUjmhkhlmjWqib>++&,0bgjWWqigbbdacaadbbefbbac-*...+#-cdfjqTTqpl5lkhhllmjUTUjgb9#..&*-0dgpqTUqpVlmlhllhmjWTUjgd;%+.@$-0dgjUTWqmll5hhlhlpqUUqpg0,+.+%3afiqTTWjVh5hhhllloqTUjiba3#.........@%*>3cfijUWjgd9-*#@.............@%$=-abiqUqjgdc-*#@.............@#*,3afiqUqpf09,$#@.............@$$,9afiqUqpea;,$%+......",
|
||||||
|
"..+#=caehlmnoqWqUqUqUUqjh7ed9=&...#,0b7hmmnoqUUqUqUUUqik4b!9>%...@$9a|7lVmnqWqUqUWWUqji7e1c3>&....&*3cdehmmXoqWqUqWWWUqph7:a9=&..+*3ae7lVmXqWqWWWWWUqjh7ed;3*&...+&*-0b7kVmoqWUqWqqUUWolkf1a9>@.+*0(4<VVXmoWUTTTTWoXVXVVXqUqpf,+.&-abhpWUqnlh742eeee477h77eba$+..@=30bgjUTTWoXlVXVVVlXoqUWjiba*+.&=3cbgjUTTWoXnXXXlVVXoWWWjgb0#.+%=30bgjUTUZnXVlVlVVVnqUUWp7b,@.+$cdgjqTTWoXVVlVlVlXnZWUqifd;%.........@#>3cdfpqUUjiba9,*%@............&#=,caeiWUUogbc9,*&@............@*>30dgpqUWjgba9=*&+...........+&*=-abgpWUWjgb09=#@......",
|
||||||
|
"..&>!{/stGGLvDDDDDDDDvDGAys^{;*..+>)/ztvLvDDDGDDDvDvvHBxsrF'-=@..%-)/sxDDDvvDDDvvvvDDGCtsr]!-#...+#-~FzyGGvLvGvDvvvvDvvHByz/)-%..@-)/stvDDLGvDDvGvvDGGCtsr{'-%...+*-)FzAvvvvDDvvDDvvDDGBtsrF~-#.@,/sABBCBCGvDEEuEELHCBCBHHvGx[;++%9)/sAGDvDvGHABBABABHGHGtAzF;+..%-~]QJvuuEEGHCBCBCCCHGGDDHyz],+.#-_FQsuuEuEvHHGHCCCCCGvDvHxr{=++*;_FKxuuEEEGBCCCCCCCHGDvvHsr!@.@-(/JGuEEEvHBCCCCHBHGGvvHAz/_>.......+%*,-~{^sGLEEvAK/)'-,*&..........+#,;~{/JtEEEvAK])'-=*@.........+@#-;~]rsGEEEvyrF);-=%+.........+&*-;~]rsGEEEGsrF);-=%+....",
|
||||||
|
"..%-!FrxGLLLvCAAAxAACCBCBts^);*+.+,)^JALuEGHBtyytBACBCABszF);=&..&;{/sHGLLvHCtAyytCHCBAAsr]~-*+...*;)FKtvLLLvCBtAxAACCCCAxz/);*..+,{rsHLLLvCBAtxAACCCCAAs^{!-*+...*;)/stvLELGBAAxtBBBCCCAxzF)-%.@-FsBCCCCBCtALEEEEvBCCCCCCCAy^-@.#-~:rxBCHvvLGCCCCCCHvvDLGAs^-@..&-~]^sGEEEEvCCCCCCCBBCCBCAsr{=++&-~FrsGEEELGCCBCCCCCCCCBCtsr(>++#;)FryvuEELGCCBCCCCBCCCCCBs^'&.+,{^KvuEELvCCCCCCCCBCCCCAxz/)=+......&#=-;)]^JtLEEvAz/{~;,=*&........@#>-')F/JALELvAzF{!;-*%+.......+%*=-;)FrJtLEuvxzF{'->*@........@%*>-;)FrsGLuuGy/F)'-,*#@...",
|
||||||
|
"..@>-~1[8wwwJ<^[/[/QIKKI^/F|!-%..+*;(2PwNNOKQ/[/[^IKKKrQFF(;-*@..@=;(28wNwOII[/[[[KJKK^^/1~-=%....&=;_2<ONNwPI[[/[^QIKIrQ/1_;=%..+$!|[8wNwJIQ/[/[/IKKI^/F{!-*&...+%,;_25OwwwPQ[/[/QIIKKr^}]~;>&.+=)}rIKKKIrQQ6SNSNOJKKKKKKKI[)$+.@#>;_F[II8OwJJJsJzKJJOwJPQF)=+..+*-!([6SNSNJJKzKKKzKKKKKKI[|!*..@*-'|46SNSwJJzKKKKIKKKKKKQ}{!%.+@*-!|7ONSNwJKKzKKzKKKKKKIQF_-+.+*;(}5NSNNwJKKzKKKzKKKKKI[]);*......+&**,-;'(2PYwwO<}(!--=*%@.......+@#=-;!)1[8YNwOQ:)!-,=*&+.......@%*=--;'|[6Mww8Q1_!-,=$%+.......@&#>--;~1[6www6[|_;--=#%@...",
|
||||||
|
"..@*,0(48SSR8[}}:}2}<KIQ[[1(!-#...#;_1<YNSO5[2:2}[[<I<Q}}|~;,*@..@*c_15YNS8<[}}:}[<5P<Q}21~;=&....%=-!1<OwSY6[}}}:}[<I<Q[}:(;,&..+$9_}5YSR8<}2}:22QII<[2}(!-=&....&=-_1<OSRY5[2:2}2Q<I<Q[2|_;>&..*;:[QIII<Q4<8RNNROPIIQQQQ<[}~$..+#*>3!(|}Q56OJOO6PI<II5<[|_,*...+%=ca:5MNNYOPIIIQQQQI<II<[1(;*..+*=c_}5MNSOPPIIIQQQQQ<K<<[:_-#..@*,c_f5RNSOJPKQQIQQQ<I<I<[:_=+..%-~b<RNNYJPI<IQQQQQ<I<<[}(c-%......+%$,-;!(|}5MNS8<:(_;-,$*@.......@%$>,9~((f5MNR6[:(~;-,$*@.......@%*>-;~_1}5RNR841(!;-,*#@......+@#$,;;_(|45MNM84|(~;->>*@...",
|
||||||
|
"..@*,0dgpqWqji74777hppplk74ea3#..+%3afiqWWqig77ggiijjpih7eb;3*&..&>cafiqUWqih7777gmpjph47ed0,#....&=9cbgjUUqph7777gipjjih74ba-%..+$cdgiWUqji47777gjjjmh77edc=%....&=3afiqWUqig7777hijopik74b0,&++$0ekimpppmipjTTTUqjmmhhhmmiga$...@*$>3cabf4imqWZomlhhh74ba0,#...@*=30bijjqjopmlkhhlhlmpjpied3#..+#=9abijqjoopmlklhhhlpjppied9#..+%=30bijqqojjpikhlmppojopgf0,+..%>0bgjqqqjoXmklhhlhmjjjigbc3%.....+&*>;abbbfgjqTTqigeeb~c3*%......+%*=;0abffgjqTTqigebdac9$&......+%$-cabbefijqTUji7fbba0-=@......+#*,;abbffijUTqqifeb_a;,$&...",
|
||||||
|
".+&=901gnWUWZmVVVVmnoWZoXVl7bc*+..$cbemqUUWoXVVXnnqUUoXVlked9>%+.@>0bgpZUWZnVVVVVmoUWqnVlkea,*+...#=cdfiqWWWnmVVVVXXWUWXmVk7d9#..+=0bgjWUWZXVlVVVnoUWqXllkba3#+..+#30dfmqWUWnXVVVlmoWUqnVVhed3#..=d4kXnZZWqWWUTTTUWZZnXVXnooib$+..+&*=,30(ekVnZWWZnVlhk771ac=%...@#>30b7mnXoZZoXXVVVVXnWWWjgbc%..+%$30bhVnnoZZoXXVlVVnoWUqjgb;#..@#$90bgmmXoZWZnXlXXZZWWUqp7d,+.+#,3dfinnXZZonXVXlVmoWUUqiba-#.....@#>9_e4khlmoUTTUoVlkk7:a9#+.....&*=0d:7kkVmqUTTWpVhkk4ba3#+.....@#,9de7khlmqUTTWnVlk72ba3#+.....%*9cb27khlmqUTUqnVlk74ba,%...",
|
||||||
|
"..#-']rxvEEEGHCCHHHvEELGHCCxr]=+.+=(^stDEEvvHHCGGvDEEDHHCtz/),*..#;{^stEELvvHCCHGvDEEDvCCtz/'=@...#3~/ztDEELDCCBCGGDEEEGCCAy^)=..@-]rsGLEEGHCCHGHGvEELvCAAz]'=+..+*;_/zAEEELvHCHHGvDEEEvHBAs/'$+@-FsAGDLELELEEEEEEEEvGCHCGDDxe,....&=-;!)/zyBvLEEvGCBCAxz^{~-#...@$-;(^sACHLLEvGBCBCHHvEEEDJ/)*..@*-!|^sACHGvLvCCCCCCvDEEEDP^(=++&=-9_}ztCHGvLvHCHGvDEEEEEwse-+..*9_FzxCGvDLLGCCCCHHDEEEuwr{9$....+#-'{^sACBCHvEEEEGHCCAAs/);&....+$-!]rsACACGDEEEEGHCCAAs/)-&....+$-~]rxABCBGDEEEEGCCCBAs/),&....+*-']rxABCBHDEEELHCCCAAz/~>+..",
|
||||||
|
"..%>'{^KAGvvHCCCCBHHGGGHBCAyr(=+.+=)FKAAHGHCCCCBCBGGGGCBBAzF~;%+.@>)FKyBGvvBCCCCBHHGGGCCCyzF'>+..+%-']QyAGvHCBCCCBHGGvGCBBAs/)$+.+-_/sxGvGHCCBCBHHGvGGCCBxr]'>@...%-~FKxHGvGBCBCBHBHGGGCCCAz/'*++>]zyBHGGvGvGvDvDvvGHHBCCCGtz{$+...+&*>;)]rstHCvGGCCBysr/]';>%...+%$;)FryAAAHGHCCCCBCCGvHvAzF;%...&$-)FzyAABHHHCBCCCCHHGGtxzF;#..@#=;']^syACHHHCCCCHGGvvGGxz{-+.+#-!)^sxABHGvHCBCCCCHvGvtJ/);*+....*-!)rsyABCBHvDvGCCABBtsr);*....+$-']rsyBCCBHvLvGCBCBBxs/);*....@$-~]rsxBACCGvLvGCBCBBts/);%....+#;~FrsyBBCCGvLvHBCCBBtsF)=+..",
|
||||||
|
"..+%=-'1}QQQIKIKIKKKIIKKIrQF);*..+%>;):[[IIKKKKKKKKIIIIrQ/|!-=@+.+%>;(}[QIIIQIKKKII<IIIrQF{'-%....+*=-~1[QQIKKIKKIIIIIIKIr/]_-%...*-!(2[<IIKIKKKKII<IIII^/_'-%....&$,-~:[[IKIKKKKKIQIIIIrQ^]~-@..%;)1[IIKIIII<Q[[QQIKKIIQ[2:_>@......+%*>;)]2IKJJKKI/F{~;-$#@+....+&*>;~(]22QIIKKIKKKIQ[4e1d;$+...+%*,;~)]2^QKIKKKKKrQQ[72b';$+..+&#$,-'){:[QQIIIKKIIIQ4}e|_,*....%=;!)]F}[QIIKKKKIIQ442e(!-*@.....@*-;)]F^QrIIIIIIKIrr^/F_;*@.....%=,;)FF^QrIIIIIKKIzr^/])-*@.....#=-!{FFQ^KIKIIIIKIr^^/])>$+....+&=-!{F/QrIKIIIIKIrrr//]'-*...",
|
||||||
|
"...@%*-9(1}[}Q[[Q[[QQQ[[Q[}(',&...@*,9_|2}[[2[Q[Q[[}[[[Q}:~->#@...+*-c_|:2[[[[[Q[Q[[}[[[}|!-=%+...+&*>3~(:}[[[QQ[QQ[[[[[[2:_;=&...&*-0(12}[[Q[Q[Q[[[[[[}}(!-*%+...+*$,9_|22[[[[[Q[Q[}}[[[}|~3*&..%,;_(}[[Q<Q[}:|::2Q[[Q[2:(!3*........@#>-;(1[IP6IQ[2('-=*%+........@#=--;'(:}2[[Q[[[[::(__c-#+....+&**-;;~|2[Q[[[Q[Q[}1__!->@.....+&*==-;~(:2[Q[[[QQ4:|_~;3>&....&**--;!(:}[[[[/[Q[}:(_!c-*#+.....@#=-'_|}}[QQQQQQ[Q[221_!-$@.....@%=;'_|}}QQQQQQ[Q[[}}|_;-#+.....@$=;~(:2}[QQQQQQ[Q[}}|_;-%......@#=;'((:[[QQ<QQQQ[[221('>&+..",
|
||||||
|
"...+%$-;abeef777k7777744f4ea;=%....%$30dbe477777774fff44eb'-=%+....&=30bbf47777774ffefffebc,*@.....+#$,00bff4777777fffef4eb03*@...@#>9abee44777774feee4eed;,$&....+&*$30deef47k77774ffffeeba-*&..&>9cdb74477ffbdbbf47774fb0c=#........@#$9abfipoomhfba;=*&+.........+@#>>39abef7477774bba09,*@......@%#$,9;db47777477feda0c=$&......@%$*=39abef77k774fbdc03,*&.....&#>>,30dbf4777774ebdac->#@......@%=-0d(b47777777747f:bdc,%......@%*-0ab:f7777777744f:bdc,#......@#>3addee7777777744eebd;>#......+%>30db:f477777h47fe:bdc>%...",
|
||||||
|
"...+&*=9adbee4477744eeeeeeba9=&....&=3cdbee447744febeeeebdc,*&.....%*90dbee4474744ee:eef|dc3=%......@=,cdbbee4444744ebeeee|09=@...@*=3adbeef477744eeeeeeba9,*&....+%#$30abeee47777eee:eeeed09*@..@*,c'befeeeebdddbbeeeee:d03=%+......+@*,;b7lnZWWXie1c3>#@...........@&%=>90dbee4444febda;9,*@......+@#*>,9abee4444efebda;3,*@.......@&#$>9adee444eefebac9,*%+.....+&#=,9cdbee4774eebda03>*%+......+%$30adbe47k77k774eebbac,%+.....@#>30adbe47k7k7k44ef1bd0,#+.....+%*-00dbe47k7kk774eebbd0>&......+#=30adbf4k7k7k7k44bbbac=&...",
|
||||||
|
"....@$-;){]F]^rrzrr/^FFFFFF)',%...+&=;~{{]/^rzrrr^^/]FFFF)'3=%.....#=;~{{F/rrrrrrr^F///FF{';>#.....+&=-')]FF^rrrrr^///]FFF{);=@...@#-;~{]]/F^r^rr/^F/F/FF)'-$@.....&#$-'){{//^rrrr^^FFFFFF{';=%..&=-;~{FF/FFFF(({{]/F/FF](!;>&.......+#=;{rxBGDvDvtz/);-#+...........+&%$,-~)]FF^^F/FF{_);3>#@......+@%#>-;~{F/rr^//FF]()!3$#@.......+@#>-;~)]]///F/FF{)!;-=%.......@#$-;!){{F/F//]F]{)';-*&.......+&$-')){F/^rrrzrr///]])!-%......+#>;~){]]^rr^rrrr//FF{)~,*......+*=;~){{F/rrrrrrrr//]])'-#.......%,;~)]]F^rzr^rrr^/F]])'-%...",
|
||||||
|
"....+&*-;!')))(FF{{{{{)))'';>*@....&#=;;~~)]F]F]]{){))'~!'-,$&.....@$--;')){{{{{{]{){))~~;;-=&......&#>-;!~){{]{({{{{))'~~;;>%+....@%=;;!~~){{{]{]{){))~''-$%+......+#,-!~~')){{]{]{)())~'!->#+...%=-;!'_)~)'~'~!''~~~~'~;->*@.......+%=-)FzxBtHGyz/]~;=#+.............+@#,;!'))){{))'~;--,%&.........+@#=;;!)){{{)))~~;;->%+..........@#$-;!~)))))))'';-,$%+.........@#=-;!)'))))))~;;->*&+........&#=--'!_){{(]{]{))~)!'-=%......+@#$,;!!)){{]{]{{{))~'!->&+......+#$-;!~){{{{{F{{){)~!;->%+......@#$;;!~_{{{{(){{))~!!;;$&...",
|
||||||
|
"......+@#==>-,,-----,->==$*&@.......+@%%==>>------,,=>>==**&++......+&%#$=,--------=>=>==*%&@........@@##$==,-,---->-=>>==#%@.......+@%===,=>----,->,===***@+.........&%*===>,,>,,---=====*%@......@##=>=,=,=====>=>=,>=>*%@..........+%*>;~(::|:b_;-=#&@.................@*$=>>>,>=,=>$%&@.............+@%$==---->=>==$%@++............@@@&*===,=>==$*%&&+............+@#*=>====>==>$%%@+...........+@%**>=>-----,-,-==*=*+.........+@%*=>=>->--,,,,===*$%@.........++%*===,,------>>,=*$&&+........++%$>=>----->-->===$#%@+...",
|
||||||
|
".........+&&&%&&%&%&%&&&%&+............@+&&%&&&%%%%%&%%%&&+...........++@&%%*#%%%&##%&&&&@+...........+.+@&&&&%&&&%&&#%&&@+...........++&#%%%&&%&%&%%%%&%&+............@&&##$#%##%%#%*%%&@+..........&&@&&%&%%&%%&%&%&&&&&+.............@#$=--3;,-$*%%&+..................++@&@%%&%%%&@@+.................+@@&@&%&#%&&@+...................++@&&&#%%%@+++.................@&&%#%#%&%@@+................+@%&%%&%%%%##%%%%%@@+............+@&&%&%&&#%%%#%&@+.............+&&&&%%*#%#&&&&@&&.............+++@&&%%#%&&##%#%&&+......",
|
||||||
|
"................+.+.++..........................+..+.....................++.+..++++.+.......................+.+...++..+.+.................++.+.+.++.......................++@@++@@@@+@++..............+..++.......+......+...............++@%%%#%&+++........................+..+.+..+.......................+..+.++.+............................+...........................+.++.+......................+++++.+.++@@....................+..+++..+......................++++.+++@@+++.........................++.++............",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
".........+..+++.+............................................................................................................................+.+..................................+.............................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
".....+@&#%##***#%*#*#*####&@+................+@@@@@@@@+........................................................+@@&@@++....................@%%#%###%@......................+@@&&%%&&+++++......................................................................................................................................................+&&%%%&@+..................@@&&%&@+..............................................................................................................................................",
|
||||||
|
"....+@&&****==,===*=>=**%%%@+..............+@@&&&&&&&%&@+................++&@@++..............................+@&&%&&@@@..................@&#**=***#&+....................+@&&%&&&&&&&&@+................................................................................................................+@@@@@@..............................+@@&&&&&@@+................+&&%&%%&@@+...............................................................+@@++...........@%######&&+..................................................",
|
||||||
|
"...+&%#$$>,,--;--------=$$##@.............+&&####*#*#%#%&@..............@&#&%%#&@+............................+@&%##%%#@&................@&#*$>>,>=*#&+...................&%#$#$*$####%%&@...............................................................................................................@&%%##%&............................+@%##*#$*#&+................@&%%*#*##&%@...........................................................+@%%%&#&@.........@**=>---=>*%@.................................................",
|
||||||
|
"...@#$*,39;ccaaa000c0cc;,=**&............+&##*==>>>>=***%&+...........+&%#$$$*$*&&+.........................+@@%#**=>*$%&+..............+&#$=33999->$*&+................+&#$*==>,,==*=*$#%+............................................................................................................+@%#*=*=$*&+..........................&%$*$>=>>*#&+.............+@&*$>>>>=>*%@+........................................................+@#*=$>*$*&+.......&%*=3;acc93>$*@................................................",
|
||||||
|
"..+#=3cad:beee4e:e1eeeebdac3$@..........@&*>3ccaac09cc9,>**@..........@%=>3cc03,>*#@........................+%$=,-0aac3=*%@.............%$,90~be:bdcc,>#@...............&*>3c'adaaaccc33,**@..........................................................................................................+&*$-9c;c3,=*%+.......................@*>3c9cc0c3>*&.............@#=,99aaac93>*@.......................................................@&*=,caaa9,>%+.....+%=-0dbfee|acc=*&...............................................",
|
||||||
|
"..&,!]/zxAGAGAGAAAAtABttsr^{;$+.......@%=-;']/rrzrr^rr/{~;-=%.......+%=-!)FrrrF{~;->%+.....................@$-;!)FzsyrF'-,*@..........+%>;)]rsyAHysrF);,*&............+%$-'{/rssszz^//FF]~-=%+.............+....+@&&%&@+......................+@&&&@+................................................+#>;!{FrrrF)~;>$%@...................@#>;)]F/rrr^{!-=%+.........+%$-')F/zssz/)!;=%....................+++..+@@@@@@+...................&#>-;~{/sys^{!-*&+...&,'{/stGAAAsrF)-=%+......................+&%%%&%&@&&&%&@@+......",
|
||||||
|
".+#;)/zAGLLLELLGCCCCGGLCByz/)-%......@#=--!]/sttyxysssz/)';-#&......@*-')FrstxrF)~;-$%+...................@#>;~)FIyvGy/);-=%..........&$-!{/sAGLLLAs/]!-=*&...........&$-!)FzstABAxzzrrr/]',#@........@%###%#####**$***#&...................@##**$**#@............................+@@+...............&$-!)FzytsrF)!;-=*&................+&#$-!]/zsytxs/);,*@........+%=-;)FrsAABxzF~;-$#..............+&####*####=$$$$*#@+................&*=-;'{/KAGAsF~;-*&...@>']KwuEEvCAs/{!-=#@..................@&%##$$$>*=$*$>**$*#&+....",
|
||||||
|
"..&,;(}IJwNwNNNwJKJJwwwJI/F_;>&......@%==-;~]/^r^^/^Q/F{!-,$%+......@&*-!)F/r^/_~;->*&+..................+%*=-'~(}5OO<1'-*%@.........@%*>-~12PwwwwP[]~;=*&@...........&*>-~{F^rKrr//}F{]_~-$%+.......+@%*********>*$$**##+................+@&**>*>***&+........................+@@@&&@++............+%*,;~)F^rQF_~;->**@...............+@@**>-~]F/^rr/]'-=#@.......+&%*=-;)F/rKzIF(!->*%+............+@%*******$****=**#&@+.............+@&$$=-;!1[8O6[_;>=*@...+*;~}6wNwwJK/{!-=*%&+.................@@%#****$$*$**$>****&@....",
|
||||||
|
"..%=;_:[8ONNNNYOPIKPJwO6Q2:_;>%.....+&$$--;(1[Q[[Q[QQ[:(!-=*&+......+%$,3~|}[[:1('-,>*&..................@%*>;!((2<66<(;,$%+.........@#*=;'(}<ORRO5[|~;,$#@..........@%$,;'(}[QQIQ[}21:((;-*&+......+%#*$>>,,,>>==,,=>$*#%@...............@%$$>,--->$$%+.....................+&%%%%%%%%&@+..........&#$,-!_:[[}1(_'-=$*%&+............@%%#$>-;_(2}[[[[(;-$#@.......@&#>,-!(:}QQIQ}|';,$$&+.........+&#*$$>>,,,>=>>,,,,>*##@+..........+@%%#*=--9_|46O54_;->*&....%-~b5RSYOPQ[('->$#%&+...............@###$>,-,,=,=,>,=,>>**&+...",
|
||||||
|
"..&=cafgmjoqqWqoojpooomi7f|a3=&....+&#=,;ad:fk<iiiiikheba->*@.......@&#>-0be77efeba;>>#@................@#$=-0dee7ipigd0-$#+........+&$>30bbgipjqpigeba3>*&..........&*=-0dee75hl5iggfebdc,*&......+@#$=,9c;0c9939c0cc3,=*@+.............+%*=3c0aac9=*#@...................@&%%###******##%&@......+&*$-90db7774ebba;,>=#&@.........@@%$$*=,9abf7<774ebc-=*%+.....@#$=,30dee4khkh7eba;=>#&+........@#$=3399;ccc339caaa03*$#@.......+&&%%$$$>,;abbfgipifdc9>*&....%,0bgjqjplh7bac3=$*&&+............+@%$*==c0aa0999900c999,=#@...",
|
||||||
|
"..%,cb4hlXXnnooqWWWZqnXlk4bac=%....@*=-0be7klVVXooZnmVke_9,*&.......+%*,9abeQkllkkedc3=#&+.............&%*,3ab4khhlihfdc3=#&........@#=3;d4khVlmmmllk4(a9=%+........+&=3cdekVVVXVXnXni4:b03$&......+#>-0a(b4ee(ddd|e2bdac,$&+...........@**,0d|e444d0,*&+................+#*$=>-33-333333,==#+.....&*$-9ad|e[kkhlk7ed093>=*%+.....@%**>,39;ad:4klVlk7e1dc3>#&....+#=3;adbekIlVlVVlk7edc3,**@......@*=,;!dd:e4:b(ddfgigfac3=#+.....+&*==>,3330dekhlllih4ed03,#+..+#,cb7imXXVlk4b_cc3,,**%+.........&%*>,99abgii7bdd1e4ee{da03*+..",
|
||||||
|
".+*;]rsBBCBCCBGvEEEEEGHAxsr/);*...@$;'{/sABACCHGvLELGCAz/);-=@.....+%$,;~FrsxAABCByzF)!-$#@..........+&*-;)]rstCBCCBxz/)'-*#@......+#,;)FryACBBAtBBCByz/{;=#@......+#-;)FrsACBCCHGDLvAsr^{!>%.....&#>;)F/zxtAyzzzsxAAxz^])-#@..........+*,;~FrstBBtz/~;=#@.............@%=-;;~){]]]]]]]]])~!;$+..+#=;;){/rzsxACBCCAsr/]{)!;,%+...+#>-!~{]]F^rstCBCAAyzz/F)';=&...&-!)F^zsxACCCCACCBBxr/{~;,$@....@$-!)//zsxyBAszzzyGDGsI]);-%....+*>-'~)){]F/ryACBCCAAsz//]{;#...*c_FQtAAHCCtyzrFF]{)!;-=%&.....+&$-;~)]F/sHvGysrrsxBBxysr/{;#..",
|
||||||
|
"..*!)^syBCCCCCCGDvuvvGBCAyz/];*+..%,!)/zAACCCBBGvLvHHCts/{';>&......&=-;)]rxBCCCCBAsrF);-=#+.........&*,-!]/zyCCCCCAyzF{!->%@......&$-!{/zyBCCCBBACCAyz/{;-*@......&$-!)FzxBCCBCHGvvGtsrF{;,%.....%$-~]/rsyBAByyxyBBAyzrF);=&..........&*,;)FzxCCCCs/);-*@...........+&#=-;'{]F^rrrrrzrrr/F{)-%..&$-!)]/zssxyyABBBBAxzr/]]~;,&...&>-')]/rrzzssyABABBxxsz/]);-#..+=;)FrzsyABAABACBACCAsrF]~-=%....&=;)FrssxBBAByzzzxtGGAz/]);$@...&>;~)F///rrrzyABBBABtxszrrF),+.+*-!{^sACBCCCxyszrr/F])';-*%.....%-;){//zsytGGtzzzsACABtAsz/)=..",
|
||||||
|
"..&,;)]/QKKKKII<<I5POwwPIr2]_;%...%=;~]FrKzKIrIKPKJJKKQF)!->$@......@*=,;~]}rKzKzKrQ/|~-,*%@........+&*=-;)F/IrKzKKr[});-=$%@......@*=-!)]/QKzKKzKzKr2])!-*#@......@*>-;'{/IKzKKJKJPKQ1(';>$@.....@%*-'){F/rrKrrrrzr^F]_~-,*@..........@%$-!)2IJwwJI1!-=%@...........+%*=-;~{{}//[/[/[/[/}F_);%..&*-!)1F[/Q//F/////^/^[F:{~-=&...@=-;){1/[/}FFFF//^QrQ/[F|~;=%...$;)|FQrrIr^/^//^rrKrQ/1)',*&...+%=;~{2^rrrr/FF1::[<IPQ^}]~-$+...@$-~)]:/}/[F}////[^^rIrQ/}]~=+..&>,;)F/QKKzKrI/Q^^}](~';,*&....+%>-~_F2[QII5<[1]F//rKrrrQF{~>..",
|
||||||
|
"..@*-;_1[QIQQQ[[[24<8YY6<Q[:_-#...&=;_1}[QIQ[[2Q<I<QQQ[:(;-=*&.....+@*>-;~12[QIIII[[}1~;->*&+......+&#$>-'(}[QIIIIQQ[:~'->*%@.....+&*,-!_(}[QQIQQIQQ[}(!;,>*&+.....@#*=-'(1[QKIIIII<Q}1~'-=*&+....@#>,;~(1}QQQQQIIQI[1(';-$#&..........@#=-;(:QPYS8<(;=$#@..........+&#$>-;(1[[QQQQQ[QQQQ[}:(;*..&*-'(2}QQQ[}||((|1[[QQ[}:~;>%...&*-'_:[2Q[21_|(1|:2QQQ[21~;=&..+%;(::[QQ[[2::|:12QIQ[[2|!-=%+...&=-_|2[QQQ[}1(1(1:[QQQ[}:_;=%...@$;__}[[QQ[}21|||:2[[QQ[Q}|_>+.+&*=3~(}2QI5KIQQQQQ2}((~;->#+....#=;_12QQQQQQ[2(((1[[QQI[[[:_=+.",
|
||||||
|
"..@*-cde4hlhh77ff47gjqWjmh7ed3#..+%=9d:4hhlhk447hhhhhk4edc-=*&.....+&*,;0de4khhlllhh4ebcc,=*&......+#*,9;a:77hhlllhh4fbac9>$#+....@#>-cabbehkhllhlhh7fbac3>$%+....+&*>-;abekhllllllh7fbda;=$%+....@%=30db:7kkhl5kl5k7eba;3>*&.........+%*=9abfijWUqib0,**&+.........&#*-90abekkh5hhlhhkhhhkfba*+.%*3abf7<kh4ebbbdb147hkk44b0-&...%=;abe7hkk7ebbddb:4khhk7eb0,%..+*cde7<khk4e|:b1efkhhk77ea9=#+...&,9ab77khh4ebbbbbf4hhhh4edc=&...+*9defkhhh74e:bb|b}77h5hh7ea>+..@*>-abe44lmmhhhhkhk4bbba;>*@....#>cde47klhhh4fbdbe4khhlhh4ed>+.",
|
||||||
|
"..@*30d4kVVllhhhhhhmqWWomVl7ba$+.+*-0b4klVVVlhhlVVVlVlh4ed0c,#+....@$9cd1e7klVVVVVVVhke:d0c>$&....+#=9cd|e7lVVVVVVlVVk4e(a;3*&....@*,cd1e[hlVVVVVVXVVk4e1ac3$%....@#>9a|e4klVVVVVVVVVk4ebdc3$&....&>-cd147hlVVVVVVVVlk4eba3=#+.......+&*>3c_ehmoWWqied;3>$#@.......@%=30d1e[hlVVVVVVVVVXVVlked$..&,cd}klVXVlk41b|bekhlVllk4b9$+.+&,9(eklVVVh741b|beklVVllk4b9*...=a1khVVVlh7eeee}klVVlVk7e'3=%...#-014kVVVVh72e:be4hVVVllked9#...@=ab4<lVVVllk4ebe4kklVmVVh7|3+..&$,9_e7hVmXmXVVVVVVkk74eda3=@..+*3ae4hVXmVllk4e1e4klVXVlVh4b3@.",
|
||||||
|
"..%=;{/zACCCHHGGGGvDEEEEvvGtz{,@+&,']zsAHGGvvGHHBCCHHGHAtsrF),&...@*-{^sxABHGGHCCHHGGHBxsrF);$+...#-;{^sxAAHGGHBCHHGGBAtsr]~;$+..@$;'FrxAACHGGHBCCHHHCBAsr]';*+..&=;)FryAABGGHCCHBGGHCAAxrF)-#...&$;)/zyABHGGHCCCHHGHCAAsr{!-&......@*>;'{]^zxtHvGGxK^])!;,=&+....@$-;{/sxBAHGHCCBCGGvHBCCCyzF,++*;{/stAGGGHAssrrrsyCCCCCCyz]-%.+*;{/sAHGGGCAxzrrrsxACCCCByr(-+.@-FztAvvvHAAsszzsxCCCBCBAz/~;#..+$!]rsAGGGGAAszrzzxtBBCCCAx^)=...&-{^sAHvGGHCtyszzytBCHGvvAy^'@..%,;{/sxBHGvHHCCCCBCHHHGtsr]'$..+>!]rsAHGvHHCByszsyACHGvvHAxr'#.",
|
||||||
|
"..&,;)FzyCCBGvLLLLuEuEEEELGGsF-@.%,!]rxBGLLLLLvGCCCCGLvCCAxr{!*..@*-~]zyCCCGLGBCCBGGvGBCByr]!-%..&$;~FztCCGGvGCCCCGLvGCCAs/);>%..@=;{/sACCGGLGCCCBHLvHCBBs/);=+..&>;{/yACCvGLvHBCCGLGCCCAy/{;$@..%-;]rxBCBGGLvBCCBGLGCCAAzF)-*....@#$=;!)]/rzsytBAAsz^F)~!;,$@....%>;~]zyCCGvvvHCCCCLLvCBCBxz{-@+*;)/sAGvLvHByzrrrsyABCCCBtz]!%.+*!{rsAGvLLGBysr^/zyCCCBCByz]-+.@-]zyHGLLGCyxzrzzyACCCCCtsF);*+.+>;]ryBvLLLHAyzrrzsACCCCBByr(>+..@-(/sAHGGGBCCyszsyACCGvDGAs/;@..#,;)/zyAHLLLHCCCABBHvDuvAsr{=+.+$!{/stHGGGCCCyszsyBCHvvGGBsF;@.",
|
||||||
|
"..&*=-~{/IKKwwNNNNuNSuNNNNwP[_>+.@*,;{}IOwNNwNwwJKKJwwwJKI/]_-#..@*>;)/IKJJwwwJKKKJwwwJzK/:~-=&..@*,;)/IKJJwwwJKKJJwwwsKK/|;-*@..&=-'{^KzJJwwwJKJJJwwwJzI/{!-%...&=-']/IKJJwwwKKKJJwwJJzI/{!-%...@=-!{/KKJwwwwJKKJwwwwsKz/_;>#....&%$=-;~)_{]2F[/[/}F(()';->$&....@*,;)2rKJJwwwJKKJJwwwJKKr}{;#+.&>;)2IJwwwJI[F(((]^IzKzKK^]',&.+&=;(}IJwwwJI[F|{(F[rKzKzK^{;*..+>_:[PwwwwKQ/|{]][rKKzKKr});=&...#-!([KONNwPI/}{){F/IKzKzI/(;*....#-'(}IPPPKKK^/}F/QIKPPPI[1'$...@$=;)F[IPwwOI[^[^[QIPPJPIQF'=...&=-~1}IPPJKKrQF2/[QKPPPPI[1;$..",
|
||||||
|
"..@#>-'(}[QI6MNSNSNNNNNSNSY6}_=@.@#,;_:<8wNNNww6KIIIOwOPIQ[:'-%..+*,3~}QKIJwYOPIQI8OOOPII[:!-*@..@*=;_2QKIJOw6IQQIPwJOPKQ[1;-$@..@*-;(}QIKJwOOIQQIJYw6PII2(;>#+..+$,;(2IIPOwY6IQQ<JYOJPIQ[(;>#+..@=-'12QIKJJw6IQIKJwOP5KQ}_;>%....@$=>-!_((|::::e::||{(_(';-=%....%=-;~}QIIOOYJPI<IOwSOPII[:'-%..&>-!|25MwY6[1((___:QQIIIQ[|;=@..%=;~:[6RwO6[}(_~_(}QQKIKQ}(;*+.+*;(}5Oww8<}|(___:[QIQKIQ:!-$&...#=9~:<OwSY6[}(~__(2QIIKIQ}_;%...+%=,;(}[I<IIQ[111:QIIQ<<2:_-%...@%=-'_:}5OO6Q2||||1[<I<IQ[}~$+..@#>-'1}QQIQIQ[2|}}QIII<Q21~-@..",
|
||||||
|
"..@*,9abgimpnqWqqqqqqqUUTUqpga=@.+%=3abgpoZqZqomikhkpppmhh7ed3#..+*-cdfimpjqopi77hijqjpmmkea9>&..@$,cd7immpojmh47hmpoppmm7ec3>@+.&=cabgijppommhh7gmjqjpmm4ba-*...@$3cb7lmpjqoph47hppoppmi7b0-%...&>9degmppnommk77ipooXpmi7bc,#...+@*39cbffggggggggggggfgeebc,#....&=9ab7impoqqpmkhljoqoommkfa,%..@>30beiooomgebdad(e7hhllk4b;=@..&$3cbgmoooi7fb_ddbe7hhllk4b3*..+*cdfijqophfbb0ad:4hhllk7ea3=&...%>9abgmoqoigebdadbekhlllhe_3#....@#=-cbe7hhlih7ff7iilh74bdc,%...@#=3abf7ipji7bb(bbefhhhhh4fd=....@%$9abe47ili44ee7ilih7fbd9$@..",
|
||||||
|
"..&*9ab7ioqooojjjiipipjWUUUpgb,+.@%>3a1kmnnZnnXlh47hlXXXVVl4b9*++&>9deiXoZojmik477hmnoZoomgba,&..&,cdfiXZZnXmik777kmpoZZop7b0,&..@,cb7moqZommh4474kmpoZoom7b0$@.+&-0b7mooZopmh7777hmnoZZom4d0=+.+%-ab7moqZnpmh777khmpooZnifdc$+...#-!bfijjjojqqqqqqojjjjjjif0=+..+#,cdeioqZoppmVVVXnZZZZqomhb0%..&*9cb7lnnnVh7e|bdbeklVVVVkea3&..&=9~b7lnXnlh4ebdbb}klVVVlk:0*+..*cdehXnnXlke1bbbe7lVVVVl4dc>%...%=90:4mnnXlk4ebdb14klVVVVkb0*....+&$>c_bekmnXm5hkipoph4bdc9=&...@*>9a:4kmnnmh4eeee4khVVVll7d>+....@*,0abekmXnmhhhlnnmh4bdc3#...",
|
||||||
|
"..#-~FrxGvEEvGCAxJsJxAGvEEEvxr!&+&*-!]^sAHHGHHBtysssABCBCCCyr(>+.*!]/sHDELDHxsszzzsyAGDEEvtzF)$+.%;]rsGDEEvHtsszzzstHvEELDAzF~$++*!]rsHvEvvAyszzzssyCvvEEHyz]-@..*'FrxGEEvvAyszzzssACDLEGGxr]-@..*~FzADEEEvtyszzzzstHvEEvHsr]-@..+>'/syvuuEEuEuEuEuEEEEuuuNs4-@..%-!]rsHDEEvHBCCCBCGHDLEEEvAK]-.+#,')^stHBHCAysrr/rsxBCCCCtzF;%.+#>;{/stGHHCtxzr^rrsxACCCBAz],+.+=~/ztHHHHAysz^rrzxtCCCCAs^{;*..+#-'{^sABHBCyyzr^rrstACBCCyz(>+...+@*,;~]/stvGGHvGGDGGyz/{;-*@..+#>;)/zxAGvLGAAyxyxyAGvHHAtsF-+.....%>;)FrsAvGvGHvHGvAsrF);-#...",
|
||||||
|
"..%-~]zyGLLGvCxxsszzsstvLLLGy^;%.+*-~]rsCCBHCCBysszsxAACCCCyr),++%!]rJtLELGAssrrrrzsAGLELLAz/)>++#!{rJtLELGtyzr/rrzstHLELutzF)$+.*!FrxGLELvAszrrrzzstHLLuvxzF;@.+*!FryGLEDDyszrr/rzstHLLDGyr{-+..*'/KxHLLuGAszr/rrzsxvLLLGsr{-+..+=~FzxAGHuDvuDuEuuuvuDDvDAz]-+..&-~]rsHLELvCCBBCCCCBCLEELGtz{=@.&=;)FzACCBCBxsrr^rzytCCCCAzF;#+.&-~_/zACBCAAszr/^rzyBCCCBAz]-@.+>~]zyBCBCBxsr/^/zsyBCCCBs/);*+..%-']^sBCCCAAxzrr/rsyBCCCCxr{-.....+%=-;)FzyCGvLLLLGHts/]~-*@....%,')/zyBGLLLBBABBBAGLLEvByr]>+.....@*;!{/zyCCGLLLvGCAzF);-$&...",
|
||||||
|
"..@=;'1Q8wNwPI2F||]1:2Q6wNw8[(,@.+%$-;{2rKJKKQ^/]]]:F^IKKKK^{!*.+&-'1[6wNwO<2]((((1:[PwwNO<1_-%..@-!{[8Yww8Q}{1((({:[PwwwO<:_,%.+#-~1[8www6Q2:((({1:[PwNw8Q|;=+..&-~1Q6wNwP[}](((({2[6Sww6[1~>..+%-):QOwNw642{()({:2Q6wNw6[(!=+...%>;_|e472<<<<<h<<k<<7777e(;*...@*-'|[6wNwOKIrIzKKIIKJwNwJ<1~*..@*>-']QKKKrr/2{()|]/^QKKKr}~-@..@*-;):QKzKI^/]1(({]F^QKKKQF_=+..&>;1[KzKIr2F1){)]F/IzKKIF{!-%...&*-;)}IKKKr^}]((({F2/KKKz/];#.......&*=-;1[IKwwNNwJKQ](;-$+.....@*-;)2[QPYwwJKKKrIKJYNwOI}(;*......+@*,;_|[IJJNwNwKI[|!-,*&+...",
|
||||||
|
"..&*-c(46YSY5}1(____(|}5YSM52_>+.+&#=-'1[IIIQ[}|(~_(:}[QIQQ2_;%+.@=;~:5ORY8[|((~___11<OSY8<1!-%..&=9_25YSR8[((_~___1:<OSR84|!-%+.@=!d}8RSM5}|____~_1}5YSM64(;>+..%,c(}6YYY54((_____|}8YSY54_;*+..%-c146YMO52___!~~(128YSY5}(;$@...@*>3c!a_|b|||1::1|||d__!;-$&+..@$-c_15YSSO<QQQIIQQ[Q5OSR8[(9*+.@%*-;_}QI<Q[:____((}[QIIQ[1'-%..@#$-!|[QIIQ[:_____(}}[IIQ[1;>+.+%=;_}QIIQ2}(____(|}QQIQQ}_;=%...@$=-~:[III[21____((}2[I<Q2_;#.......+%$>;~|[<6RNSO5[:(;-$%+.....@%*-!(1[5ORYO8865868OOO5[|_-&.......@#*>;_:2<OSNSOI2:~;,*#@....",
|
||||||
|
"..%*9;dgpqWqpfbbdaa0dbgiqTWjfd>@.+&#=3ab7hlhh4fbdaad:e4khlk4bc*..&=cafiqWqpgbbd0aaabfiqWWjgba-%..%>cdeiqWqpgbdaaadabfiqWWjgbc,%..&,cdfjqWqpfbdaaaadbfiqWqpgbc$+..&,0bgpqWqigbdaaaadbfpqWqpfbc*+..&3cbgpqWqifbaaccadbgpqWqigdc*....+%*>,,30aadbbbbbbbda033,-=*@...@*>cdfiqWWjihhhllh77gpqWWjgbc*+.+#*-cd4hlh<74ed_ad:f4khlk7e03%..@#*3cb7<lhk7f|daddbe4khlk7bc$...#=;aekhl<7e:da0ddbf7hhl7e0c=&...+#=3ab7hhh44bbda0dbe4khlh7bc*.......@&*,3abfijUTUjieba3=*@......@*$3abf4iqWUUUqUqUqpmil7edc3&......+@#$,9ab4ijUTUjgfda3,$%+....",
|
||||||
|
"..&=3abhjWUWph4e|bb1eehjWUWjgb,@.+%$3;d4llVVlk44:bbeekkVVVlke0=++@,0b7mZWWoi7ebbb1bf7mqWWoifa3%+.&-abgnZWWph4e|b1bee7pZWWoiba3%..&30b7jZWZpheebbbbefhXZWWjhba=+..#9abgoUWZpkeebbbbefhpZWWjgb0>+..#9abhoWWZp7f:dd(befhpWWZp4b0$+....@%#=,390dbeef77febdc9,,=*#@...@*30bgmWWWZXmlmXXVhhhpWUWoifa*..@%>9a:kVVVlhk4e1eeekklVVVkebc*+.+*>-a:kVVVIlk4eb|e}khVVVVked>@..%,914llVVh74e:b1e[kVVVVl4ba3#...&*>9a}kVVVlk72b::e4klVVVVk:a>+.....+&#>-0d1kijUTUoi4da9>#&......&$=c_e7hmqUUUTUUUUWoVlh7eac=&......@%$=3'be7ljWUUjieb0->%@.....",
|
||||||
|
"..*-_FryvEELvAxyzzzzsyBGLEEGx^c%.@=-~]^sBCCCCBAszrrzsBACCCCyzF;@+#;{/sGDELGAAyszzzsxBGLEELxK{~$+.%;]rsGLELvAtssrzzstAGLELGyI];*+.*!:rxGEEEvAxyzzzzsxBvEEEvyQ(-@..*;FKxDEEEGAxszzrzsxHvEEEGy^(-+..*)FztDEEEvAyszrrzsxHGEELGsI{,+....@&**39~(/rsttHGAJrF(!;,=*#@..+#-~]^sGLEEvvGGHBGCCBHvEEELyr_>.+@=-~]zyCBCBCtysszsxBCBCCCAsr(=+.&=-~]zyCCCCBAxszzsyACCCCCAs/;@.+*!{^yCCBCBAtsszsytBCCBCCyr])=+..&=;)FzBCBCCCtyszssyACBCCBxzF;+.....&=,;)F^stCCvEvHtz/{!-#@.....+#-;{/sxCHGDEDDDvDvvHAxsrF)!,@.....+#=-!)FrsAHvEvDGsrF);>*&.....",
|
||||||
|
"..#-'FrxHLLLvCCtxsssACCvLLLGsr;@+@*;)FryACBCCBtxzzzsytCCCCCAs^;@+#;]^stLLLGCCAysssACCvLEEDyr{;*+.%;{/sGvLLDCBAxssxABCGLLLvy^{;#.+*;FrJBLELDCCAxsssABCvLEEvs/),@.+*!]ryGLLLGCBAsssxACHvLLuHs/)=+..*!FIyGLLLGHAyszsstCCHLDuts/(-@.....+@*=-;)FzACGuLLAr]~;-$#&+....&>']rsGLEEELLvGCCACCBvLLLGy^)*+.&$-']rxBCCCCCAyssxACCCBCCBsr{>++&$;~]rxBBCCCAAyxsytBBCCCCAsr;&.+$;)^sACCCCCBxsssxCCBCCCAxr]'>+..%=;~FzxCCCBCBAsssAACCCCBCAs/;@....@*=;!{/ryACCCHHtyzF);>%@.....@=-!{/sAABCHCHtAyxysszrF])!,#+.....@*,;~]/zyBCCCHHtsr]~-=%+.....",
|
||||||
|
"..@*,;(}6OwwJJKI^[[QQKJJwwOP[_>+.+#,;)][rKJKKIr[F1]F2^KJJJKQF_-+.&=;_25ONwwJKKr[^QQKPwwwYJ[(;>&+.@$;_}5OwwwJKKQ[[^IKJJwwwP[_-$@..&=;(2PwwwOJKrI[[[IKPJwwO8[(;*+..&=;(}6OwwwJKrQ[[[IKJOwwO5}~-*...@$!([6wwwOJKI[[2[IKJwwwO5}~;#.......+&%*=-'1[PJwwO<|!-=#@.......+#-!([5wwNNNwwPQIIKKJwwww6[_-&..+&*=;)/IKzKKKrQ/[QrKJJJJKK[{;*..+&$-!{^IKKKzKr[/^QrKJJJJKI/{-+.+%=-~F^KKzKKKI/[QIKKJwJJK/:';%...@#=-~]QKzKKzKrQQ^QrKJJJJKr}_-.....@#*--'{F[QKPJKKI2(!-=%+......+#=-'{F^IKKJII[22::{(~!;-==%+......@#>-;)(FQKKPJKKQ1);,$&@......",
|
||||||
|
"..@#=-c|[P8OJ8P85555888OO654|;*..@#=;_1<5O6O8554:1|}[586OO8<}(,@++*=;([58888P855556666668<1!-$&..+*,!([P8PJP8K655566PO6O5<|;-#+..@#-0|[586O88P555586O8888[1;,%...@*,;|[PPJ6P8K5555668O886[1c>#+..@#-~1<588J885555556P6JP54(;=%+.......+&&$=;(:[88854(-=*@.........%=;_1<6OOwSSY655568PP6P5<:!$@...+&$=;(}[QIPPP5<556PPOYO8<[|!#...@#*-~|}[Q<P655<<5PP6OOO8<[_,@..@*=;_1[[<KPP55<5PPOJOY88<1(;*....@#=-~|}[QIPP65555PPPOOO8<2(=+...+@*>-!(|}<88J6J6<}_;>#&........%,;_(}[QP6P5Q}}:|_!;->=**@........&*=-~(:}<66OJ68Q:!-=%@.......",
|
||||||
|
"...&*,caf7hipoWWUUqTUqqjih7bd9#+.+$,cb7pqUTTUqqigbfgpqUUUUqjge-+++$=9abghimjqWUqoUqUqjmh7fd9,#@..+%=cab7ilpoqWqUqUUqqpli4fd9,#...+&=cae7hipoqWqUqUUqqjih4bd3=#...&*,3cbghinoWWWWqWWWqji77bac=%...+%,;df7hipqWqTTqTqWqpih7ba9=&.........+&*>3abe7i5fba9>#@........+#=9ab75mmoUUUWqWUqWqpmh7fd9$+...+&*>-adefipqqWqqqqWqWUUUjied*....&*>cabe7ijqqqqWqWqWWUUUjie9@..+#*,cdbegpqqWqqqqWqWUUTqjgbc*....+%$,;ab:gijqZqqqqWWWWUUqjge3+...+%*3abfgijUUUqWqifa3=#@.......+#=;de7hijqqoih7f|a93=*$%%@.......+%>3ae47ijqUqWqoie03$#@.......",
|
||||||
|
"...&*,9ab4klnZUTTTTTTTWolk4b09#..+*3dfljqTTTTTqjk77ijUTTTTTZm4c@.+&>-a1ekhXWUTTTTTTUUomh7fac>*@...&$-ab4hkXZWUTTTTTUWolk7eac=#+..+%>3ab4hloWTTTTTTTTWolh7ea9>&...@#=9a|4kVpZWUTTTTUUWolh7ba9=%...+%>9ae7hlnWUTTTTTTUWXVh4ba3*&..........@$=3~be77<7ba3**@........+#=!aekVVXoWTTTTTTTUWolh7:a9*.....@#=3ade7mZWUTTTTUUWUTTTWphb,+..+&$=9~be4mZWUTTUUUUUTTTTqm7a&..@%>,c!b4koWUUTTTUUUUTTTUjl7d>+...+%*=9adb7mZWUTTTTUUUTTTUqm4c@...&*-017lVmoUTTTUWogdc>*&+......@*,a|kVXXZUUZXVlkeac,>$&&+........%$,a|7lVnZUTUUUqpfa9=*@.......",
|
||||||
|
"...&=3!|^stBGDELEEEEEEEGAys/{;$+.&>'FsBvEEEuEEuDtxxBDuEEEuEEGx(#+@%>;(/stAGvEEEEEEEEEvAAszF~-#@...%>;(/zxtGvEEEEEEEEEGBxsr{'-$+...%-;{^zxAGEEEEEEEEEDvtysr]!-#...&=,~{^sxCGLEEEEEEEELvAxs^{!,%...+*3']rstBHDEETEEEEEEDAxs/{;-#.........+%=-!{/zxyxs^('-*@........@>;)FzxCCHGEEEEEEEEEEvHtsr1!$+....&=,;{FrstDEEEEEEEEEEEEEEDtr;@...&=-'{FrsHvEEEEEEEEEEEEEEGx{%..@#,;')FzxDEEEEEEEEEEEEEEEHs/-+...+%$,!{FrsGvEEEEEEEEEEEuEEAx)&..+%-!]zxCCHDEEEEEEGs2)3,*+......&-!]zxACCvEEvHCBtzF);-*&+........+*-~FztCHGEEEEEEvGKF~;>&.......",
|
||||||
|
"...+#-!{/zsAtGDuuuuuDvGHyxz/)-#..@-~FzxBDEuuuuuttssxGuuuEuuHAz)&.+#>-~]rsytGDEuuEuuvGBysz^{!-$+...%>;)FrzttGDvEuuuDvHHtyz/);-%@..+%=;)FrzytGvEuuuEuDvtysr/{;,%+..+#-;)/zsAAGuEuuEuvvGHyyz/);#@...+%-;)/zyAtGLEuuuuvuvAyszF);=&..........@$-;)]/zssrF);-#+........&,;)/zABCBGvEEuEuuEuvtxsz/];*.....+%>-;]/zyGGLvEELLDDEuuuvty/;@...+%$-']^zxGGEuEuEEvEEuuuGAx)&...+#>;~{^stGDvEEEELvEEuuDAts]-+.....&>;)]/KxGvvuEEuEDEEuuDGAs)&...#-!]zyACHDvEDDDvts/~;=#+......@>']ryCCCHvvGHCByr{!-=#+..........#-!FzAABHvEEELDDxz]~-*@.......",
|
||||||
|
"....+%*-;~(:}4[k<h<<4[4}:)_;-#+...%-;{:}4<hhi<4}::11e7hh<k[42(-+..+&$,;~(124[7<k<<<7[[1(~!-$%@....+@#-;~~{2[[[<k<<<[[2:{_!-$%+....+%$-;~)1}4[<<h<<[[[2|(~;-=&+....@*=-;~(:}[2<<<Q<[7[}:(~;>$+.....+#=-!~):24<<5kh<7[42:)~;-=%@...........+%*-;')))~;>*#@.........+#,;(F[KKKP<<<<<<<<[[2:(~;-$+.......%$=-;~1}[<<Q<<Q<<<<<7[2|;#.....+&*=-!_:2[<<<<<<<Q<k<7[}(-@....@#*=-;d2[<Q<<[<<<<<<<42:);*.......@#=-;_:4[<<<<<<<<<k<7[:(,....@*=;{/rIKP6J6PP5Q|'-=%@........#-!)/QKKKPJKKI^/|;,$*@..........+&=,!{^rIKKJJPJPK[|;-=%........",
|
||||||
|
".....+&*$--c0_a__0_(___';-==$&....@#=-9;a__~__a~';''_~_a_a_~;-%+...@&*$>-;00_~__d___a';-,>*%+......+%%*--99aa~__a__a~!;--=*&+.......+#=,-;0aaa~_da_d_~;-,=*%@.....+@%#=--;0aa_0~__~_~!;-,=*@......+@%*$-3c~a~ad_d____';->=*&@.............+&%$>>,->$$%@...........&>;~12QQQ[}:|(_d(d_a~;-->$&+........&#*=-90_a________d__a!-$+......@&**=-90a_a_a__(_d~__~;;#+.....+&**>9c0a__d(a____d__';-$@.......+&#=,-90_a__d__d__d~_'!-#+...@%>-!:}[[QQ<QQQ21~-,#+........+&=-'_:[Q[QQ[[[}|~-*#&+...........@#=-_:2[Q<Q<<[[f|~->#+........",
|
||||||
|
"......+%**==->,3999033,-,>$*%@....+%$>,3,9c99993-3,3333333333=@.....@%#*$=-393399933,9-=**#@........+&%$>,,3339033333,,=$*%@........+&#*$,,3,939c09333==$$*@.......+@%#*$,-9-cc999333,==$$%+.......+&##*=,,-339c9333,,>>$#%@...............@&****#*%&+............%,;_bbf4fbbaaa0909933,=**&@.........+&#*$,,33,3333399c3933=&........+&%*$,,3333333909993,,=&......+@%$*=,,339cc99333cc93,*#+........+@%*>,>339999c9c3c093,#@....@&*-9def44fffffba0,$&..........@#>cdbe4777febbda-*%&............@#=-abef44f4ffeba;,*&+........",
|
||||||
|
".......@&##==->,,>-33>,=$*%%@......@&*>=>,3--,>=>=,=>>,,=>==**@......+%%**=,=,3-9,>,>==$*#@+.........+%#%$=,>9,3,,>,>,=$#%%+.........@%%**==,=9-9>-3,=>**%&+........+@%#**==,9-9,,,=,=>*%&@.........+@%$$*=>,=-39,,>>,$$&%@.................++&&%%&@+............+&*99addbddc0c933-9,>,*$#%&...........+&#***>,>,,,,,,-3,,>=$&.........+@&*=>=,,,,,3,39>>,>>*@........@&#$*>>3-3,-,,,39,,=$*@...........&%*=,=,--9-39,,3,3,=#+....+&*>9aadbbe|bbda03=*&..........&*=99dbbbbebddaa9>>#@+............&#=3!dbbbebddaac9**@.........",
|
||||||
|
".......+@&##$>---,,-,,,>=#&&+......+&#=,>,33>>==$==>3-,-3,,-$%........@&#%*>,,-,3--,,==*%&+...........@%%#*>>3,-3--,,>=#%@&...........&&##=>-,--3->,,==#&@@..........+&&%#=>>-,-3,,,,==#@+..........+&&#*>=>,3,,3--,,,=*%&+...................++@@@+..............&$,;!''_~~'!!;---,,>,=$#&+............+%#**$,,,-3--3-,,>,=*&..........+@##$>-33333-3-333>=#@........@&@#*=,-,-,3-3--,-,,=#+...........+&#>=>3,3-,9-3-,,>==%......+%>;;)~]{{(){);';,*&..........&$>;;))(]{{{();!;-$%+.............&=-;;'){({({~~!;-=%+.........",
|
||||||
|
".........++@%#**#$$*%#%#@@+..........@%%#$#*###%%&##%%$$**%%%+........+..+&%%#*$***%##%%+.................&&###%#**%%%&&++...............@&#%##*%%#%#%&+++.............+++@%%%#%%%%%%%&@+............@&@@@%$$*$$$**##%%&+........................+.................&*==-,-,->=>=>***%#%%&+...............+.+@%%##%%****#%##%&..............+@%%%%%*##*****%%@...........++&%%*$*****#*$%%%&@..............@&*#*$#$===**#%#%&+.......@#$>=-,,---,=-=$#@............&*$>,,->-;---->#%&@+..............@*=>-,---->-->$*%@..........",
|
||||||
|
".....................+.+.................+......+........+..................+.....+............................+..+........................+++....+.............................++++...........................+.....................................................+.+.+.++++.+.++.+................................++..........................++.....+.....................+...+...+.+.....................+..+++++..+............+++++@@+@+.+.+...............+++++@@++++..+++..................+..+++@@@+.+...............",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................",
|
||||||
|
"......................................................+@%%%%@.......................................................................................................................................................................................................................................................................+&%%%%%%#%%%%#%%#%@+........................................................................................................................................................................",
|
||||||
|
"................................................+&%**=>-;;;--$%...........................................................................................................................................................................+@*****#%+...................@%***$$**$**$*#%@.................+@@+.....................+#>,;;;!;;;;;;!!;!;;->=*#&.......................................................................................................................+@&%%%%+.....................................",
|
||||||
|
"........................................+@@&%%%##*=--;!)))~~;-*+.........+@@&&@+@@&%%@+..................................................................................................................................................+%=>----=##@.................&#*=,---;;-;--->=*%@..........+&%%%#**#@....................%,;~))))))))))))))))'!;,=#@...........................................++@@@@++..+@@@+..........................................................@%#*=$>=$##@...................................",
|
||||||
|
"......................................++@&&&%#***$>,-;~)(()';-*+.......@@%&%%&&&&&%%%&@+++...........................++...............................................................................+++@@&&+...........................@#$,---,=**@+................@#$>,----------,>$%@..........@%%&#*$$#&@+..................%-;)(((()~~~_~)_~)((~!-=>%@.......................................+@@@&@&&%&@&@@@@&%@@@@+.....................................................+%#*$>>,==**@...................................",
|
||||||
|
".....................................+&%###$>*$$>=--!(17<7}:(;$+......&&##*#####***$$$#%&+........................++&@@@@+...................................................++&&@@+.................@&%#&%#&#&+........................@#$,-;~!;->#&................+&#=-;!!!!!!!!!;;-=#@..........@&#$*>,=*#&@+................+$;b}4<4}::::|:::2}4[7:_9=$@...................+@+................@%%#%###*#$#*#######%##%&+...................................................@%*>--3;;;-*%+..................................",
|
||||||
|
".....+++@@+......+@@@@+.............@%**$$=,333333;abeijqjpgfd-+.....+#*>>,>=*==,>>,==*$%&+..................+@@@@%&##$#$%&@+..............................................@&%%##%%&+..............+&***$*>$*$&@+......................+&$=3cbebdc,*#&+..............+%*,0dbbbbbbbbbddc-$&+.........&%$=3c99,>$%&+...............@-agjjqjihh777774hijqjjec-*&+.................+@&&&&++...........+*$***>=>,>,=>>==>>===$**%&+.................................................+#*=9;a0ddac>*@..................................",
|
||||||
|
"....@&#*%%#%@@@&%%%####&...........&=>,339caada_addb4hjWWWoPl49&....+#=,9cc0999c90c00c9,**&..........++@@&&&&#*$=>=,33,3,>**&+......+@@&&&&&@+.++@@@@@@@@+...............+&*==,,>==$#%++..........+%$,39399393>*&+....................+%$=3014k7edc-=#&@............+#=3cd4444444744eedc=#&........+#>3cadd~a-=>*&+..............#9biqWWZoVVVVVVVVVoZWWqgb9,*@...............+%*$=****&@.........+#=3-ccc0c0c0cc9c0c00;c93,>*&................................................&*=30dbbeeeed;,#@.............+@#%&&+.............",
|
||||||
|
"..+#=---;--,=$*==---;;->%@........&>!){]]F/rzzrrrrrsxBGLELGHAs)#...&*-;~]/^^F]F]///^//]);-=%+......+#*$>-,,--;;!~~)){{]{{)!;-*+....&*$>,--,-,>=>>---->->,$%@............+%>;!){{{{)'-,$$@+........#-!){]FF/FF{~;,*&+................+&$-;!)/zABBxrF)';-=%@..........%>;~FzAABAABBCBBys/{'-*@......+#-;'{/rzz^{~;->#&@+...........-]KALEELvCBCCBCCCHGLEELxQ(;-#+............+&$>;;!''!;-=%+.......&,~{]F/^/^^^^/^/^^^^///]{)!;*+........+@%**$*$$*$$**#%@+....................%>-!{FrssyAtsr])-*+.........@%*>>;---=%+...........",
|
||||||
|
"..%>-;')~~';--,,-;~))~!--*&+......#;{F/rrzzyytyzzssyBCvLLLvHBz)%..&=-;~]rsysrr/rrrzzzzrF);>*&.....+#=-;-;;;!'~)){]F//rrr/F{);=%...&=--;!!!;;;;!!;;;!;!;;---$#&........+##-;~]/rr//F{!;-=*#@......+=!{F/zsxxssQ]~->*@...............&$--;!)]/xACCAsrF)!--=##+.......&$-;)/yACCBABCBCBAsr]!-=#+.....@>;!)]rsyyz/])!-,$*#%%@@+.....+,FztDLLLHCCCCCCBCCGLLLGyI]~-%.............&*-;!){{))~;-*&+......$~FrsssxyxyxyyAyyxxyyxJsrF{'=+.......+&*,---;-;;;;--=$*@+.........+@@@.....%$-!)FrxtCCCCAs/{!>+........&*=-;'~)~;-=#&..........",
|
||||||
|
"..%==;!~~);-=>*=-;~)();-=*%@......$;(]}/[/IPJJII[//QKKOwNwwKQF;&..@*=-;([PPI[FF2/[/Q^QF(;,*$&.....+#=---;;;;'~))){1F:/[F}F(~-=#...@*=-;;;;;;;;;;;;!!!!;;-->*%&+.......@#*=-':<P65[:~;-=$$#&@+.....*!{}IPJOOO65:;,>#@..............+#*==--;~:IJwwKQ|);;-,=**&+......+%$,;1IJJKKrKzzr//F]'-**&+.....@$=-!)}<66<:(!;,>$*#&&&&@+.....>~}PwwNwJJKKIIrKKKwwNNw<2~->&............+&*>-~({{{)~;,*%+......#_[K6OJOJOJOOwOOOJOOJOO6<}|!$+......+@%$>>>-----;--,=*#&&+........@&&&+...+%*>-'([PJwJwwPQ:)-*........+&#$>-'~~!;,*#&+.........",
|
||||||
|
"..#=-;_(1(';>=>,-;)1:(~;-*%@.....+>_12[[QQ<6YY8<[[[QQPOwwYP<2(=+..@$,-~|5665[:::}Q[QQQ}|!->*%+....%=-3;'~~~_~((1::}[QQQQQ[1_;-&...&$>3'_(_~~~~~~~~_____!;;-=>#@......+%*=-;(48OY6<}(~;,=**#%&....+=!|[5OYMSSR5:c-**@..............&*=,-;!~(}<YRY8[|_!;;--,**&+.....@#*,;|<8OP<QQIQQ[2}_;,$#%+.....&*-;'(e5Y851|_;-=*$*####%%@...+*!:<YSNSJIIIQIQIIIJOwSO<|~9*&............@%#=;_:}}1|_;=$&@......*d<8MOYYYYSSNMSSSSSRRRRO5[1'$+.....+@%**,-;;;!~~~!;-->**&@.......+&%%%&@+@&%$=;~|[6YRSSO6Q|'-%+.......+%$=-!~(((;->*&@.........",
|
||||||
|
"..*30df4gebc99-9!df7gedc-=$&.....+>b47hhimpjqjmi74hhiXpjopm7e0=+..@=3cdeijqp7ff47hhhkh4ea;,=*@....%3abefeegffgggggiiipipiigb0;%..+&>0affgefffegeeffegefebbc3,*&....+@%**,9abgpjopi7bdc;9-,>*%@+..@,0b7ioqqUqqjfa9>*&..............#,90ad_begiqUUji7bbbdaa;3>*&.....@#*9ceiqqphkhk<h44:d0-=*%+.....&*9cdbejqqigbdc;,,,,>,>==$&@...$cfiqTTUjmilimmmmpooWqjgba9=#+...........@&$-0be47fedc-$&@......*agipjjojqqqqqWWqqqjqjjjigbc*+....+@%$>3;adbbeefebbac9,>#&+......@$,==#%%&%#*,0dfgjWUUWjpgd0>%+.......@#*,;dbfeed;-=#&.........",
|
||||||
|
".&,a17ipjmged~adbfipnhedc3*%+....&c:klXnZoooojmhhhlmoonXmm7fba>+..#,0de7pZZnhhQhlVlVVlI7edc9=%+...>bgpjjjqjjqjooooooZZWWqqmhfd=+.+=cbgppjjjjjjqjjjqjqjjjig4bc,%+..+%*=3;cade7mXnmlkk4eb(daac,*@..@>ab7lmnooopi7ba3>*&............@,a:e47kkkloUTTWphhkkk4e|a9>%+...&*=3cd7mqZXlllVVVlk4edc3>*&.....#,cdb4ijWqpheeba'aaaaaaa09>*@.+=afjqTTTqXXXoooooZooXomhed03*@...........@$=cdekllk2ba9=$@......%3dfggghiiiipoooopimiiiggba0$.....@%>3cd:ekhijjqjjg7e|d9-*&.....+>adac-****$,3~e7mZUTUjpgfd9-%........&*,cbe7imigba9=&.........",
|
||||||
|
".$~rsBGvDvAsrrrrzsHDDys/{~3$&....%(rtBGvLELvGHCBAACDLvGHtxsr/)-+..=)/zsxGLEDBttAACCCCCCtxrF);,#..+;VwEuuETuuuEDDLLvLEDuuEEDAxr;@+&;{IxvDEEEEEuuEuuuuEUuuuGAz]~$+..%>;~)]/rrsxBCCBCCAyyzzzrr]);*+.%;{^stCBCBHCBxKF(!-=&...........=]rsABBBBHHvEuEEGHBCBBABsr]~>@..+*;!)F^sHDDGBBABCBBtys/])'-$&...+,!]/zytGLLHtszr^//^rrrrr/]'-%++;2suuuuEDHGDvEEELEGGHGCyz^{'-%..........+#-;{/sBBAtyzF~;,%+.....#9_b}^rKsssyHCHHHAAsssKzQ2]~,+...@$-;)FzstAHDEuuuDvBtyr]~;,#@...&!rz/]);;-3;!)^stGEEEEGys^]~3%+......@*-']/yAHDDtz/);$@........",
|
||||||
|
"+={rxHDLLLtJrrzzsyHGvAJ/{';=@....%!zABHLLLLGCCCBBBCGLLHAAsz^]'=@.+>(^zsAGLLGtyABCABCCAACyz/{!-*+.@~zGDEEEEEEEEEEEEEELEEEuLvHy^;@.#-]zAuEEuEuuEEEEEEEEEEEEGtz/'$+.&=;~)F/rzzsyBCCCCCCByssszr/);*+.&-)/zyACCCCCByr/]'-=#@.........+-]zyABCBCCCLEEEEGCCCBCCBxz/)>%..%,!))FrsGDLGBABCCCABAsr/)~;;*%..%,!]rzyBvLLCAyszzrzzzsszzrF~-#+&-^svEEEEvGCvLLLEELLCBBCts/F);%..........@*=;)/stBCBxrF);$%......&-;))F/^rzsytCBCCAyszKr/F])!>+...#,-')/sABCHvLEEEuDHByz/{';=#+..&~^sr/{!;;;;']ryBHvvELHsKF);,%......&*,;~]rxBvLvAs/{;>&........",
|
||||||
|
".*;1IPJwwOP[:F1F2QPwOK1);-=%+....+-(/IJwNwNJKrQ^/QIOwwPI^2F(;-*+..>~F}[KOwYOIQIrKKKKKKKK/}]~;,%..+-15OYRNSNNNNwNNwNNNSNSNS6I})>+.&=':8wNNNNSNNSSRNNNNNuSMPQ2)-%..@=;'(|:}}2[IKKPKKKKI^QQQ/}{!-%..@=;_]^IKKJKKI[]{~;-*%+..........=):/rKzKzKJONNNwJPKKKJzI/F);=%..&,;!_{}QPOwPIQIKKKr^^/F{~;--=&..@=-~]2[IOww8I[[[222[Q[[/[1)-=&.+,{[6SNNNwJJwwNwNwwwwwJJI[:(;-&..........+%#,;_//Kr^F{)->#+......+$>-;;!)_|F2QKJJKQ2}]]())';-#....%=-;_]/^IzJwwNSNROKIQ}{);-*#+..+-]F}]~;-->--!|/IPwNwO5[(!-=#+......+&*=;_FQPJwO5}_-=%@........",
|
||||||
|
"+*_25PJOJ8<42:::2[6O6<(0-=#@......$~:[5OSNY6<}}:}}<6RY6Q[}1_;=&..+>(4<56YMSY855586JO86885<}_;-*+..*_:<<5558RRNSOOOwwNSO855[:(9*++@,015MNNMO88556558pMSNNM<}(~-#+.&>;(:4<<<5558OO8886656555<1_-&..+$-'|[58O8J65Q}1(!-$$+.........+$'1[QQQIIIPJMNNR6II6JJPK[:_;=%+.*;_(1:}[6YY6<Q<PPIQQ[[}:|~';-%..@=;_}}Q<8RMO855555555I55<[|;=&.+>(45MNNROPIPOOOOOOJOOYJ5<4:~-%+.........+&*>;_1[Q[2:(;-*%+......+#*=-,;!_(|}[IKIQ}11((((__!-*+..+%=-!(}[QI<IP6OO886655Q}(!;>#+..@-(24[2d;->,-!(1[<6OO8<|!3=*@.......@%$,;(}5P8654_9-$%+........",
|
||||||
|
".=dijjXmmlh774474ijqjgd9=$%@......$0begoqWqmfeb|bfgjqqpi74ea;=%...3fpjqqUTTUqWqqZqWqWUWqojgfac*+..%,cadbffgpqqon6mnqqjigffba9,#+.@3afiqWqjig7ffffffgjqUqjgba;,&..%3agijqqqqqqTUTUUUqUqUqWqjib9%..+$3abijqUWWqomh7fb;=*@+.........*d47hklllhmjWUUqpmmoWqqpifb;=%.+>0ee77hiqqWpimpoqjmmk5h74bbd;*+.@>0b4hhmoqUUqUqUqUqUqqqWjje0=&.+3egpqUUWjmmlhilllmoqUUWqqjgb0*+..........@*>;de77771d03*&.......+#,9c0aaabef7kl5h4e1bbbbbbb0,@..@$-abf4hhkhlmmmmiipoqopgf_0,*@..+,bgijiga;--9ade7glli5fd;,*#@.......@#$,;bijjmigba9>*%+........",
|
||||||
|
"+$biqZnVVVVlkkhhhVoZoibc,*%+......*014loZWZm7eeeefioWWnmVh7ba3*+.@9gpWWUUTTTUWWWWUWUTTUWWomfb0>+..%=990dbfgmoZXXVXnZZXifbdac-=%..%cbgjWUWohk4eeebffgpqTWjied0>#..%cbhpZWWUUTTTTTTTUUTTTTUWZpe0$+.@=cb7pqUUUUZZXlV<ea9=*@........+>bkVVVVVlVXoWUUWoXnZWUWoVh:a,&.+,:7kllVXoUUonXoWWZnnXVVVhke1d=++#3d4hVXXZZWUUUTTTTTTTUUWWjgc,&+@9elnWUUWZnXVVVVVXXoWUUWWWoif0$..........+%*30b4hVlkeb_9=%+......%90_db1be47klVXmVhk4444k[74(9#..&3a:7klVVVVVXXXVlhmoWZomkfbc=@+.@3ekpWoibd00~de4kllVVl7b0,>#@......+&*=3cfpqZnl7109,*&@........",
|
||||||
|
"+=eJtHCCCCCCCHHGGvvGHx^(;-*@......>{ryAGGvGtszrrrsxvuEDvGHtz/)-@.@;KtGvLEEEEDLvDDGGDDEDDDHyrF{;@..#>c'_1/IsAvGvGCHGHvAsr/](!3,&.+$)/sHEEEvHyszr^^rzsvLELvtz/{;*++$_^sAHvLvEEEEEEEEDEEDEvLvDtz:,+.&;(/sAHLDELvDHCCBzF);=%........+;^AACCCCCCHvEEELGHGDEEEDHtsF'=@&;ztBCCCGvEEvGHGEEvGGHHCBAAys^;@+>(rsBCCHBGLGDvEEEEEEDDvDGAIbc%+&~sBHDLDLDvGHHBCCBHGDvvvDDHtr{-+.........@$-!{rxBCBtsrF)-=@.....+-]rzsxsyABCBHvvvGHAtBBBBBAxr)$.+=)/ytHCCACCBHCBCBAHGDvvGGAzF;#+.@'^xGLvHsr/F/zsACHCCCAs^(;-*@......@#>-'FVADDGts/(!;,=%@.......",
|
||||||
|
".=)FrsxtBCCCBHvLLGGCxz/';=#+.....+-{zxCCCCByzrrrrzyvuEELLGAsr{-+.+-]zABHvEELHCCCBCCCCCCCxsr:);=+..&=,-!)]/rsACCCCCCByzrF(~!--#@..#~/sHuLLvAysr^]FFrsGLLLvys/(;$+.%;]rsyBCCCHvEEEEEHAACCCHCBtr(-@+&-{/zxBCCCCCCBCCtz/~->%+.......@;rtCCBCCABAGLLLLBAAvLELvBAs/)*+@'rtCACBCvLLGBHvLLvCCCCBCCBAs^;%@,]rxBCBCCCCCCCCGLELGtxysz/F~-#+&~rACBCCvvLvHBCCCCCBCCCCCCBs/~*..........%=-~]ryABCAsrF';=&.....@;/sBBBAABACCGLEELGCCCACCCByr)$++>{rxDGHABCCCCCBAyyACBCHGvHJF;#+.@;/sGvLtxzr^rztGLGHCCAs/);-%+......+#=-!FstLLAyzF{~;->*+.......",
|
||||||
|
".&>-'(]2^rKJJwwNwwJQ[:~->#&.......$'2^rIKII/1((((1<8wNNwNw6[1'=@..*;]2[IJwwPI//IrKzKKKI/F{~;,=%+...+&*=,;!|}QKKsKKr[](~--==*%+...+>~:5wNwJI[](';;'([6wwwJQ:~->&..+*-~(2[^IKKJNNNRPQ[QIIIKKI[{'$+.@,;(][QIKKKKJsKKQF)-,*@.........-1/IrIrI/^QJwNNOPQKONNwJKQ2);%.+-|^rrrKPOwwJJJwwwwJJsKKKrQ/F)-@+$']/KKKzIQ^Q^^IPOwO<[::|_';>*+.+-1^IKKJJwwwJKKzKKKKKKKKKQ[F~,&..........+%>-!{/^Kr/F{~->&+.....+-]^rrIrrKKzJwwNNwJKKzKrKrr^];*+.*;:5OwPIQrKKI^Q/[/^QIKPwwJ[_-%...>!26OOPQ21||}<JwJPIQ/]!-=#+........@%*-_}PwOP[:_'->*$%@+......",
|
||||||
|
".+&=-;~1:2<IPJwwwO6[|_;=*%@......+*!|2[Q[Q}:_'!!_(26RNNNwO6[('>...#c_|}46MM522}}QQIQQ[[:(!3=*&+.....+&**-;~|}[QQII[1_;->*#%&.....+*0:5MSR6[:(!---'_:<OMY84('-*&...%=-_(:}}[Q6SNNM<}}}[Q[QQ[2(9#..@=;~(:[[QQQPPI<Q[|;-*#@........+=)2[QQQ[[225OSNO<4<8MSwO<[:'-&++=~2[[QQ5ORRPIIJwwJKIIQIQ[2:(~>@+*!(2QIIQQ}}}}}[<OO64|1_'9=$%&+.+=_2[QIIPOww6I<Q<QQQQQIQ[[1(;*...........@&*,;~:QQQ2:(!-*#+.....+=_2[[QQQQQIP8SNNY8IQQQQ[[[1(;%.+*;|<OO5[[[QQQ[}}|11[}QIOO6f_>&..+%-(<8O52:(((1<8YOIQ21_-=*@+........@*>-~:5MO<e(_;-,>**#&+.....",
|
||||||
|
"..@$>9abbf4hmoWUWqmgba3=$#@.......*cb477kk7edaaadbgpqWWWqjmgba>+..#3abbgpqqjgff7hhhhhk7ed9,=*&+......+%$,3ab4khlhh4:a-,**%@.......=aepqTqjgfd99-9c0fiqWqpgbc3=&...&*3cab:f7hmqqWji7f7khhhhkfac#+.&>cde47khkmppmhked;,*#@.........=b7khkkk74gpqTUqiggjWWWpi7ba3&..*cbe777kpqqnimponmmhhh77eeb_c$++*0bf7hk74eeef47ijpigbac;>$$%@...=ae4kllmoWWopmmmimmmmihh7ba9#+..........@&$,cd7kih7:dc,*#+......=dbef44777k5pqWWjmh774444e|a-%++>cfijpi47kllh7ebbb:e4hijqpga>@...&,0gipgfebbbeijqji7f10-=*@........+#$,9dfiqjieb_ac;3->>*%@....",
|
||||||
|
"..@*=3ad:4kVnoWUUWphedc3=#@.......=d4klllhke1dddbehjZWZXonXh4b,+..%9a|fhjqUjhh7kllVlllk4dc9$$&.......+#*30(e7kVVVlkba3=$%+.......@,dgpWTWohfb_c99abfpqWZog:ac,%...@*,cade4klmXZoni4khlVlVlh4b9$.+%cb4khVlVXnZomh7edc,$#@........+,1kllVllllVoWTUqpmmqUUWomk4d9#.+%cdb44kioWZXVVXnnXVlkk4ebdac3#++,b47[77k447khlhVnXm4ba0,=#&@...+>deklVXnWUUWWqqqZqooooXi7b~,=@..........@$=3afinoni7ba3>*@.....+*cad|beee[7hmXoonlh74eebbdac=@.@,b7lnnVlhmnom44e:ee7khXZWjgd9#...%>cbggefee4kkmoZol7eac,*&+.......+%*=9dekmopiffe4e|d_a9,>#@...",
|
||||||
|
"..&>-'{F^stCHvEEEuvyz/{~;,$@.....+;rxBCBBCAszrrrzsyHLLvvCCCAy^;&..$~FrzyDuEvAtBBCCCCCCtz/);-=&.......@=-'{/stCCCCAx^{!-=&........&'QsvEEuvAsz^{)(]^JtLLEvtz/(;*+..&,-')]rstCCCGGGAttBBCBCCAs/)>++=]zABCBCCGDDGCyzrF);-=%&@......+;zAACCCCCCGDuEEEGHHEEEELCAs/)=.+%!{/rzsyvEDDHACCCCCBAxz^]{~!-*+@'ryyssssssxtCBCCHAtz/{~3=*&+....-(rsACCGEELEuEEEEDEEEvDtz/{'-%+.........%>-~FKtvuvHsr]~-=%+.....*-~({1F//zsxBCGGBtsr^/F]{)!;=&.@!rACHCCACvDDAxzzrrsABHvvEvxr(>+..%,0(2^^zzsABBHLDGxzF)!;=#+......+&=-;{^stCHAAssyBtysr/F)~->%+.",
|
||||||
|
"..%=,;)FrzACGvLEEEGxzrF);->#@....+;^yACBBAAxzrrzsstGvGHBCBBAsr;@.+*'F^zxvuDGBAAABACACAAz]';,$&.......&>-!{/sAACAAAs/_;-$+........&!/xGuELGAyz/]))F^zALELHAK/);*...@*-;~]/sBACCCCGCAACCCHBCyzF;*++={sABCCHHGGGGtsz/]);--=*%&&+...@;ryCCCCCCAHGEEEEvBHvLLGvByz/!*+.#-']/zsxvGLHACBCBCCAysrF)';;,&.@;^zzrrrzzssBCCCCBByr]~;,$&+....+=)^sBCCHGDDuEvuDuEuELvvAK]~;,&..........%>;)/sGLLvtJr]~-#@......@,!'~~){F/rsxCCCCyz^F))'!;>=#+.&~zxACBCCBHGHttzrrrytCCCvvGy[~*...+$;')F/rzxACCGHGAJ/]';,$@.......+*>-'{rsBCBByxstBBByyzr/)!-$@.",
|
||||||
|
"..@#*-;'{}IJwwNNNw6I[2(!;-=*%+....-(/IrrIr^/]|F2/[IPPKI[/F]])!$+..%-~(148OwPIQ/IrzKrKr^])-=$&+.......@*=-!)}rrK^^F]'->#@.........+>_[8wNwOI[:)';!_([PwwwOQ:)-=&...+&$,-!{/rKKsKJKQQIJJwwPIF{!>%+.#!FIKJwwwwwJPQ2F(~;,=>$#%&&++..+>(/^IrQrQQIJNNNYPIIIJJJKI2{!-#..@=-'(F}QPwOPIQrKIzQ^F]);-,=#&+.+*;~)~'){]F[PJwJJI[]_;,*%@+......&,)FQKKKKPP555I5666OJJP[{!-=#+..........%*-;([6wwwP[(;-*&+.......#=>==--!_(F^KKKr[])!--==#&@...@-:^KKKKIKKPP<2|||]FQrKKJPI2(,%+...%*=-')(2IPJwJP5[1~;-=%+........@#$=;)]QrIrQ[F2/^KKPPIQ1~;,*@.",
|
||||||
|
"..@*$,;_(2<8SNNNSSO<Q2(_;->>&+...+*~:[Q[[[2:|(|1}[[QQ[:|_!;--=%+..&>;~125YY522}}[QQQQ[}(;->*@.......+%$>-;(2[Q[}11'-=#%@.........+>~:5MSM6[}|_!!~_(}5ORY6}|0->&...+%=>-;(:[III<QQQ[Q6YSY64|!->%..%;_[IJOwwJPIQ}:__'3->=*$$##%&+..*!(12[[[2}[5YNSO<}2Q<IIQ}|_;*@..@*-!(12[6OO<}2[QIQ[}|(;,**%@....+$,---;')|}5YYO6[(_-,*%@........@=!|[[QQ[4}}:224[Q<II5Q}_3=*@..........+%=,;_}5YSY5|~3=#@........@%#$$$=-;_|2QII[}_;->**&+.....&31}QIIQQQQIQ}((~~(}[QQQII[:0,@....@#>,;;(:<OYO6<}(~;>*&+.........@*=-;(}[QQ[}}(|12[6OYO5:_c,*+.",
|
||||||
|
"..@$=-cabeiqWTTTUqolh4bbac9>#&...+$~b747hk7f:bef774747bdc-,,=*&+..&=9abeiqqjg7fe7khhh7fb93*#+.......@%*>;ab4k<7:b_c-=#&+.........+$0fpqUWjg7bdaaadbfiqWqpgba3=@...@#=,;abeklhhkhh77gpqWqpgba9=@..#cbhmnWWWqnmh4ebda09--,-=*$#%+..#9dbeeeeebfiqWUjiff7hlh4eb03*@..@*3cbf4gpqjiff7hh74ebd9-$*&......%$>=-;adbgjqWqjfda3=*%+........+*cb7khk74ffeeff77hhlhkfa3=*@..........@*=9c_gpqWqif03=*@........+&%##*>-cab4hhl7:a3,*$%@......%9b4khhkkhhh7fbdadbf7hkhhh7b0=&....@%*3;abeiqWqpgba;,$*&..........@$3;dbekk44eebb:fhpqWqigdc-=&+",
|
||||||
|
"..#=30(e4hpqUUTUUWoXVhk4e1d'-*...+=aeklVllhk747klklll7e_9,,$$#@...&,0de7pWqoikkk<llVIlk:a9>*&......+%=3ca|4kllk4bd03>*&+.........@3dgjWTWoVh44eee}4hpqWWohbac=&..+%>9ad|eklVVVVVllhVoZWZnkb'3=&..*a4hXnZWWZZXlh74feebb_aa'0c-=&..#9ab:ee4e47pWUUqih7hlVlked!3*&..&3014khlnqomh4hllVkkeb03=#@+.....&*=>90d:7hjWWWpgba3$*&+........+*cd4khhk774447khkVVVVl4dc,$&.........%*=,;aehpWUqpbc3$$@........+@@%*>,ca14kVVVledc,>#&+......%ceklVXVVVVVl4ebb1e7lVVVVV7b0>&....&$3;abe7pZWZnhe_9,=#+..........*,0_b4hVllhk7[47hmoWWWohfd0-%.",
|
||||||
|
".@>!)/sAAHGvLELDvLDvvGGGAts^{-@..@-{rytCHGHCAACCCCCAAsr]!c->=*@...*;{/zxGEEvHBBACCCCCBtz/);-%......#>;)/rsyBCCxz/F)!-#@..........&'/JHuEEvHAAAtxAtAAGEEEDxK/)-#+.@=)]rzsxBBCCCCCCHHvGvLvGs^{!-%.+>{zACHLDvvvGHHHHHBBtysszzr/]'$+.%;{F//rzzzxGEEEuGxxtAAxs^F);>#++>)/sAHHGGvGtxxBCCCBys^{;-=%......#>-;'{/sxCHDLLts^{;,=%.........@,~FrsyyxxyAttBACHCHCCts/);-&.......@%>-;)FrsAGDDvAK]~3=&+........&%=,;']rsyBCCBts/);-*@.......#~rsAHGGGGCAtxszzzytHHGHBAs/)-#...@$;~]^zytGGDDHs/{~c=&..........+-{FzsABHHHCCBABAGDDuEEvHtz/)=+",
|
||||||
|
".#;)FzyDDGGHCBBtBHGLLLEuDGAs/;&.+&-)/zAGvGvGCCCACACByzF);->=*@+...*;{/zsHuDvHCCCCCCCBBys/);=&.....+*-)FzyAACAByr/]'-*+...........%!/sHDELLHCCCBCACCCvLELHAKF);#.+%;{/stBCCCCCCACCGLLDHCCxzF);$&++=]rsxCCCCCCCHGDLLLLLCCABAxsr{>++&>;'){]//zstuLEvtsszzzr/]'!-=@.+={zxHLGvGHAysstCBBBxzr)'-*&+.....%,-;~]rsBBCCBAsr]';>#@.........@>!)]/rzzsAABBCCvvvBCBAz/)-=@......@#>-;~{/sBCCHHHyr]'->&.........@%>-')/ztBCCCCAs/);=%+.......@;/sALLGLGHByszzzsAHvLGGAsr]'-&...%,;)FzxACCCCAyzF);-#+..........@;FzxtCGGvGBCBCCGLEEEEuLvByr),+",
|
||||||
|
".%-~_[6OwwPKQ[2F2QIwwNNNwOKQ{-@..+*-~1QPOwwJJzKKzKr/])!-=$#&+.....&=;~|[8MwOKIrKKzKKrI/F~->%+......#-'(/QrzIr^F)!-=$@.............-([PMwwJPKKKKzKzKPJwwwJ[|~-*@..&-'|/rzKzIrr^/QIJwYwPKI[1!-=#+..&;~F[rKKJzJKJwwNwwwwJKKIrI/]'*...&*=,--!_126wwwO<21_)~;;-=>#@...$'2<JwwOPQ2F:FQrKr^F]);,*&&......&$,-;)][rI^[}1(~-,*&@+..........#=,-;!~(]/^zzKJwwwPKI^]!-=%.......@#*=-!)FQIKKKKI}(;,=#@.........+&$=-!(}rKzKzKIF~;=*&+........*!1<OwwwwKQ[/2F2/KJwww6Q1);,*@...%>;'{}^KKKIIQ:(;,=#+...........+-(2^KJJwwJJKzKJJwNNNSNwJKQ1;$+",
|
||||||
|
"+*;b4<5665<}:((_(|4558O685<:~=@...%=;~|<586KIIQQQ[2:('-*#%@+......&*-!(}5YY6IQQQIIQQ[2}(;-*&+.....@*;~|}[Q[[21(;->#@+............+$;1<6OOPIQ[2[22[[Q5J88<}_0-*@.+#;(:2QQQ[}}::::[5885Q22(~-=*@+..&>~|}[[Q[Q[Q<5688OOPPIQQ[[}|;*+..@%#$$=,-!1<ORR8<(~;->>>*#&++..+>~1[566P[}((_(2Q[2}|(!-*#@.......%*,;_(1}2[}|(~;->*&+............+&#==-;!(|}QQIORS6Q[}1_3=%@.......&#>-;_(}<II<[}:(!-*%+..........@&#>-;):[QIIIQ[|'-*#@.........%-~:<5665Q2:}[4[<<<5P<[|~3,*&....#3'14[<Q[[}1(_;>$#&............@-_2Q5POJJKIIIIIPP6OMMMO6P[|;*.",
|
||||||
|
"+>bgppig74bbdaaccadfegiiig7ba>@...&*390be777hk444e:(93=#%&+.......@*3cbeiqZpmhhhlhhk74:a;=*&......&,abe7hh44e(03=$&@+.............*9bglmlh7eb|b|b1be4hih7ba;=%@.+*0e77k74eb(dd_bf7gg7fbda9>$#+...@3ae747f4eeeffhghillllhh44ed;*...++&%#*>3cbijUWqgb09>$$*%@+.....,b7ghhg7fd000de474:ba;,*%@+......&=;abbee4e|ac-->$%+..............+&*$>-9_bf<hmoqWjhfbd;,*%@......+%*,;aefkpjpgebda3>%&...........+&#=9cdeklllhh4bc,*$@.........&=3abbffefbfgjjqpi7febdc3-=%.....>0bgppm44ebd~;=$*&@............+,d7ioonmmlhhhkh77ghi5ipojifc*.",
|
||||||
|
".,fpqoik4ebac9999ccabf4Q4[f:a,...+&#>30d:f4h<hhk4ebac=$%&@........&=9ab7pqZoXVVVVVVlk7ed9-*&+.....#9beklllh4bd0,>#%+..............*0bklVVh7e|bddadbb4khk4ba9,$+..=bkhlllk4|ddaadbe774eb(09=*&+...%317kk44eebbee477klVVlVll7edc%....+@@%>=90fiWWUjgb03,$*%+......@3ellhk74ed0c00b774ebd03*&+.......%,0|447k4ed03,=*%++...............+&#*-9abklVXoWWjheba9,$%@+.....@*>3de4lmoZoied09>*#@...........+&$,9'b4llVVVVkbc3>%+.........@*,90abeebe7pZWWom7ebac9,*#@+...@,b7pqoml7:d09,>*%%+............@,bgjWWoXVVVlllk747[hhlnoZpf0*+",
|
||||||
|
"@;IwDDAsz/F)';;;;'~1/zsyxszr]-+...@$,;~F^zsyBAtysz/]'-=#&+........&;~F^sGLLGCCCCCCBCtxzF)3$@......={rstBBBts/F~;-*&+..............>)^sACCtsr/F]{){]^zyyys^F~9=@.+-ryBAAAsz/F]({{Fzssz^F]);-=%....%~/xAyszrr^/F/zssxAACCCBAxz/_=+....++#>-'{IyDEEux[_93=#+.......@'sBCBxys^]'!~{rsxsz/]~;=#+.......*;{rsyyxsz/)!-,*&+.................@#$;!{/sBBHGEDHxz^]~;>*&......%>;)/stCHDDDyrF)!-=#@...........+%=-~{^sBCCCCBs^)'-#+.........@=-;'_//r/rJtDLEvts^](!93=%@....@'rxHDLGtsr])!-,=*&.............@!^xHEvGHCCBBCCtysssxtAGvEtI|=+",
|
||||||
|
"+;rtHAxKr/{!;;---;'~{/rzzrr/{-@...@%=-~{//rssyszz/F);-$+..........@>']^sAGGHBBCBACBAyzr]'-$+.....+=)/zyAAAyzF{!-$#@..............+$;FzAAttr^{{'!!~)]^zssr/{!,#@.+-Fsxyyyzr{'~'~~]FrzrF(~;-$&+....@;/zxszr/F](]F^rzyABAAAttzrF~=+......+$-;)/yGGGxzF)-,#++.......@'ryAxszrF)!;!)/zsz/])!-$+.......+*;{Fzsssz/{';,*%@...................@$-;~FzABCCGGts/F)'-#%+.....+#=;)FzyACHGtJ/{!,>#+............+&=-')/stBBABAs/);=%+.........+&*>;!{FFFFryHDGttI])!;,#@+.....&'^sAGGAyzF);--=*@..............&;/stvvHAABBBtxyzr^zzyytGtw^)=+",
|
||||||
|
"+$ae2e1_!;-=*#%#***=-;!~~~!;-%.....+&*,-;;')))))~';,#%+............#,;~1[<KQQ2//2/F])~';,*@.......&>;))){])~;-*#@+................&=;)]]])~!--=>>,--!)()';-*&+...#-)){{)~;-,,=,,-;'!;;->*#+.......$;~))~!;;---;!')){{F]]]{)~;>@........@#=-~:[<<410-*#@..........$!]])))!;>=>,-;))~;--=*&+........+$-!~)))~;-=*&+......................@%*,;)]F[[[[e1';-=#@+.......@%=-']F^[Q[e(;-=#&................&*>-!(]]F]]{);-$%@............+&*=-;;;;_:}[7}:~;-=*&+.......+-)2[Q4}(~;-=**&+................=~(e4[[}2FF]]])~~!~))1224:~,%.",
|
||||||
|
".&>;;c3,,$$#%+.++@&&**>,=>=*#@......+@&*==------,>>#@..............&*=-'(:::(__'_~!;--,*%@........+*==-----,>*%+..................+#>--;--,==**%*#**=,>>>=%&+....+*,-----,=*###**=>==*##&+........&=,---,===*$>>,,--;;;;--,,=%+........+&*=-0_((a9=*#&+..........+$-----,*$#%#$=>>>=*%%@+.........+@#,-->>->**@+........................@#$=-;!!_~ac3,$#%@.........@%$-;~(||(c99,*#+..................@*=,-;;;;;--=*%&...............&%**>>,-9cc009,$#&@+........+=_(__ac3,=**&+.................+#=9'__a!'!;;;-;--,-,--;0;3>>%+",
|
||||||
|
".+#*==**$#%&+......+@&**$**%&.........+&&*$*******%@...............@&*>9cdba9333333,==$#%@.........@%$$$>=*$$%@....................&*==,=>>*#@@@&&%#*$*##&&@+.....@#$=$*$$%%&&&&&####&@+..........@&**$**##%##*#*$**==,>>$$**@..........@&$>9c009=*$%@............#**=*$*%%@@&&%****%%&+............&**$*$$%%@..........................+&%*>,,3933=>$#%@..........+@#=-0adac3->*%@+..................+&%$==,-,,=**#@+...............++&%%#**=,-3,=**%&+..........=0a033,==*%&....................@#=,9,333-,,,=>$$*$*=>,===$*@.",
|
||||||
|
"..&*#$**%&&+........+@&&@&@+............+@%#****#%@+...............+&#*,99c993,>,===*#&&&@.........@%%*#*$*%@@+....................+&%##$##&@+..++@@&@&&@@+.......+&##*#&&&+@++..+++.++............&%%%&&&@&@@@@&&#*******%&&...........+%#=>33,>=$%&+............&**#*&@@....+@@&&@&@+.............+&###&@@++............................&#**====>**%%%@..........+@&*,90cc3==*%@+....................+@&#*******#&@...................+&&%##$*==**&@...........+%33,,==$#&@.....................+%*=====$=$=*$**#$%##**>*$*&+.",
|
||||||
|
"..+&%%%#&@+............+.+...............+@&%#%&&@+.................+&**=>>>=$*****##&&&&...........+&&&%#%%+......................+@&%&&&&+..........++@@+.........@&&&&&++.......................@@&@++.......+@%&#**%&&&@+...........+&&&%***$%#&@+............&&&&+........+++..+.................@@@+++..............................@&%#****%%#&@@+............+%*>>=>$**@+......................+@&&%###*%##@+....................+@&&%#%**%%+.............&$$$$**%@+.......................&#***#%%*#*%&%&&@@%&%**%#&@..",
|
||||||
|
"....+++................................................................++@@++++.+.++......................+.............................+..........................................................................+.+++....................++++.+..........................................................................................+.++++++...................+.+@+++++................................++.............................++++................++....+...........................+++.++.+.++++.+..++++++...."};
|
||||||
|
|
@ -1,533 +0,0 @@
|
||||||
if get_option('resize-pool')
|
|
||||||
config_h.set('USE_RESIZE_POOL', '1')
|
|
||||||
endif
|
|
||||||
|
|
||||||
srcs_toytoolkit = [
|
|
||||||
'window.c',
|
|
||||||
color_management_v1_client_protocol_h,
|
|
||||||
color_management_v1_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
text_cursor_position_client_protocol_h,
|
|
||||||
text_cursor_position_protocol_c,
|
|
||||||
relative_pointer_unstable_v1_client_protocol_h,
|
|
||||||
relative_pointer_unstable_v1_protocol_c,
|
|
||||||
pointer_constraints_unstable_v1_client_protocol_h,
|
|
||||||
pointer_constraints_unstable_v1_protocol_c,
|
|
||||||
single_pixel_buffer_v1_client_protocol_h,
|
|
||||||
single_pixel_buffer_v1_protocol_c,
|
|
||||||
tablet_unstable_v2_client_protocol_h,
|
|
||||||
tablet_unstable_v2_protocol_c,
|
|
||||||
ivi_application_client_protocol_h,
|
|
||||||
ivi_application_protocol_c,
|
|
||||||
viewporter_client_protocol_h,
|
|
||||||
viewporter_protocol_c,
|
|
||||||
]
|
|
||||||
deps_toytoolkit = [
|
|
||||||
dep_wayland_client,
|
|
||||||
dep_lib_cairo_shared,
|
|
||||||
dep_matrix_c,
|
|
||||||
dep_xkbcommon,
|
|
||||||
dependency('wayland-cursor'),
|
|
||||||
cc.find_library('util'),
|
|
||||||
]
|
|
||||||
lib_toytoolkit = static_library(
|
|
||||||
'toytoolkit',
|
|
||||||
srcs_toytoolkit,
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: deps_toytoolkit,
|
|
||||||
install: false,
|
|
||||||
)
|
|
||||||
dep_toytoolkit = declare_dependency(
|
|
||||||
link_with: lib_toytoolkit,
|
|
||||||
dependencies: deps_toytoolkit,
|
|
||||||
)
|
|
||||||
dep_gbm = dependency('gbm', required: false, version: '>= 21.3')
|
|
||||||
|
|
||||||
simple_clients_enabled = get_option('simple-clients')
|
|
||||||
simple_build_all = simple_clients_enabled.contains('all')
|
|
||||||
|
|
||||||
simple_clients = [
|
|
||||||
{
|
|
||||||
'name': 'damage',
|
|
||||||
'sources': [
|
|
||||||
'simple-damage.c',
|
|
||||||
viewporter_client_protocol_h,
|
|
||||||
viewporter_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'dmabuf-feedback',
|
|
||||||
'sources': [
|
|
||||||
'simple-dmabuf-feedback.c',
|
|
||||||
'../libweston/pixel-formats.c',
|
|
||||||
linux_dmabuf_unstable_v1_client_protocol_h,
|
|
||||||
linux_dmabuf_unstable_v1_protocol_c,
|
|
||||||
presentation_time_client_protocol_h,
|
|
||||||
presentation_time_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [
|
|
||||||
dep_wayland_client,
|
|
||||||
dep_libshared,
|
|
||||||
dep_pixman,
|
|
||||||
dep_libdrm,
|
|
||||||
dependency('libudev', version: '>= 136'),
|
|
||||||
# gbm_bo_get_fd_for_plane() from 21.1.0
|
|
||||||
dependency('gbm', version: '>= 21.1.1',
|
|
||||||
required: simple_build_all or simple_clients_enabled.contains('dmabuf-feedback'),
|
|
||||||
not_found_message: 'dmabuf-feedback requires gbm which was not found. If you rather not build this, drop "dmabuf-feedback" from simple-clients option.',
|
|
||||||
disabler: true)
|
|
||||||
],
|
|
||||||
'deps': [ 'egl', 'glesv2', 'gbm' ],
|
|
||||||
'options': [ 'renderer-gl' ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'dmabuf-egl',
|
|
||||||
'sources': [
|
|
||||||
'simple-dmabuf-egl.c',
|
|
||||||
linux_dmabuf_unstable_v1_client_protocol_h,
|
|
||||||
linux_dmabuf_unstable_v1_protocol_c,
|
|
||||||
linux_explicit_synchronization_unstable_v1_client_protocol_h,
|
|
||||||
linux_explicit_synchronization_unstable_v1_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
weston_direct_display_client_protocol_h,
|
|
||||||
weston_direct_display_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [
|
|
||||||
dep_wayland_client,
|
|
||||||
dep_libdrm,
|
|
||||||
dep_libm,
|
|
||||||
dep_matrix_c,
|
|
||||||
],
|
|
||||||
'deps': [ 'egl', 'glesv2', 'gbm' ],
|
|
||||||
'options': [ 'renderer-gl' ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'dmabuf-v4l',
|
|
||||||
'sources': [
|
|
||||||
'simple-dmabuf-v4l.c',
|
|
||||||
linux_dmabuf_unstable_v1_client_protocol_h,
|
|
||||||
linux_dmabuf_unstable_v1_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
weston_direct_display_client_protocol_h,
|
|
||||||
weston_direct_display_protocol_c,
|
|
||||||
viewporter_client_protocol_h,
|
|
||||||
viewporter_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [ dep_wayland_client, dep_libdrm_headers ],
|
|
||||||
'deps': [ 'wayland-cursor' ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'egl',
|
|
||||||
'sources': [
|
|
||||||
'simple-egl.c',
|
|
||||||
fractional_scale_v1_client_protocol_h,
|
|
||||||
fractional_scale_v1_protocol_c,
|
|
||||||
tearing_control_v1_client_protocol_h,
|
|
||||||
tearing_control_v1_protocol_c,
|
|
||||||
viewporter_client_protocol_h,
|
|
||||||
viewporter_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
ivi_application_client_protocol_h,
|
|
||||||
ivi_application_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [
|
|
||||||
dep_libm,
|
|
||||||
dep_libshared,
|
|
||||||
dep_matrix_c,
|
|
||||||
dep_wayland_client,
|
|
||||||
],
|
|
||||||
'deps': [ 'egl', 'wayland-egl', 'glesv2', 'wayland-cursor' ],
|
|
||||||
'options': [ 'renderer-gl' ]
|
|
||||||
},
|
|
||||||
# weston-simple-im is handled specially separately due to install_dir and odd window.h usage
|
|
||||||
{
|
|
||||||
'name': 'shm',
|
|
||||||
'sources': [
|
|
||||||
'simple-shm.c',
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
ivi_application_client_protocol_h,
|
|
||||||
ivi_application_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'timing',
|
|
||||||
'sources': [
|
|
||||||
'simple-timing.c',
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
commit_timing_v1_client_protocol_h,
|
|
||||||
commit_timing_v1_protocol_c,
|
|
||||||
fifo_v1_client_protocol_h,
|
|
||||||
fifo_v1_protocol_c,
|
|
||||||
presentation_time_client_protocol_h,
|
|
||||||
presentation_time_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'touch',
|
|
||||||
'sources': [
|
|
||||||
'simple-touch.c',
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if dep_vulkan.found() and prog_glslang.found()
|
|
||||||
srcs_simple_vulkan_shaders = [
|
|
||||||
'simple_vulkan_vertex_shader.vert',
|
|
||||||
'simple_vulkan_fragment_shader.frag',
|
|
||||||
]
|
|
||||||
|
|
||||||
simple_vulkan_shaders = []
|
|
||||||
foreach s : srcs_simple_vulkan_shaders
|
|
||||||
simple_vulkan_shaders += custom_target(s + '.spv.h',
|
|
||||||
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
|
||||||
input: s,
|
|
||||||
output: '@BASENAME@.spv.h',
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
simple_clients += {
|
|
||||||
'name': 'vulkan',
|
|
||||||
'sources': [
|
|
||||||
'simple-vulkan.c',
|
|
||||||
simple_vulkan_shaders,
|
|
||||||
fractional_scale_v1_client_protocol_h,
|
|
||||||
fractional_scale_v1_protocol_c,
|
|
||||||
tearing_control_v1_client_protocol_h,
|
|
||||||
tearing_control_v1_protocol_c,
|
|
||||||
viewporter_client_protocol_h,
|
|
||||||
viewporter_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [
|
|
||||||
dep_vulkan,
|
|
||||||
dep_libm,
|
|
||||||
dep_libshared,
|
|
||||||
dep_matrix_c,
|
|
||||||
dep_wayland_client,
|
|
||||||
],
|
|
||||||
'deps': [ 'vulkan', 'wayland-cursor' ],
|
|
||||||
'options': [ 'renderer-gl' ]
|
|
||||||
}
|
|
||||||
|
|
||||||
srcs_simple_dmabuf_vulkan_shaders = [
|
|
||||||
'simple_dmabuf_vulkan_vertex_shader.vert',
|
|
||||||
'simple_dmabuf_vulkan_fragment_shader.frag',
|
|
||||||
]
|
|
||||||
|
|
||||||
simple_dmabuf_vulkan_shaders = []
|
|
||||||
foreach s : srcs_simple_dmabuf_vulkan_shaders
|
|
||||||
simple_dmabuf_vulkan_shaders += custom_target(s + '.spv.h',
|
|
||||||
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
|
||||||
input: s,
|
|
||||||
output: '@BASENAME@.spv.h',
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
simple_clients += {
|
|
||||||
'name': 'dmabuf-vulkan',
|
|
||||||
'sources': [
|
|
||||||
'simple-dmabuf-vulkan.c',
|
|
||||||
simple_dmabuf_vulkan_shaders,
|
|
||||||
linux_dmabuf_unstable_v1_client_protocol_h,
|
|
||||||
linux_dmabuf_unstable_v1_protocol_c,
|
|
||||||
linux_explicit_synchronization_unstable_v1_client_protocol_h,
|
|
||||||
linux_explicit_synchronization_unstable_v1_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
weston_direct_display_client_protocol_h,
|
|
||||||
weston_direct_display_protocol_c,
|
|
||||||
],
|
|
||||||
'dep_objs': [
|
|
||||||
dep_vulkan,
|
|
||||||
dep_libdrm_headers,
|
|
||||||
dep_libm,
|
|
||||||
dep_libdrm,
|
|
||||||
dep_libshared,
|
|
||||||
dep_matrix_c,
|
|
||||||
dep_wayland_client,
|
|
||||||
dep_libweston_private, # for pixel-formats.h
|
|
||||||
],
|
|
||||||
'deps': [ 'vulkan', 'wayland-cursor', 'gbm' ],
|
|
||||||
'options': [ 'renderer-gl' ]
|
|
||||||
}
|
|
||||||
endif
|
|
||||||
|
|
||||||
foreach t : simple_clients
|
|
||||||
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
|
|
||||||
t_name = 'weston-simple-' + t.get('name')
|
|
||||||
t_deps = t.get('dep_objs', [])
|
|
||||||
foreach depname : t.get('deps', [])
|
|
||||||
dep = dependency(depname, required: false)
|
|
||||||
if not dep.found()
|
|
||||||
error('@0@ requires @1@ which was not found. If you rather not build this, drop "@2@" from simple-clients option.'.format(t_name, depname, t.get('name')))
|
|
||||||
endif
|
|
||||||
t_deps += dep
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
foreach optname : t.get('options', [])
|
|
||||||
if not get_option(optname)
|
|
||||||
error('@0@ requires option @1@ which is not enabled. If you rather not build this, drop "@2@" from simple-clients option.'.format(t_name, optname, t.get('name')))
|
|
||||||
endif
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
executable(
|
|
||||||
t_name, t.get('sources'),
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: t_deps,
|
|
||||||
install: true
|
|
||||||
)
|
|
||||||
endif
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
if simple_build_all or simple_clients_enabled.contains('im')
|
|
||||||
executable(
|
|
||||||
'weston-simple-im', [
|
|
||||||
'simple-im.c',
|
|
||||||
input_method_unstable_v1_client_protocol_h,
|
|
||||||
input_method_unstable_v1_protocol_c,
|
|
||||||
],
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: [
|
|
||||||
dep_libshared,
|
|
||||||
dep_wayland_client,
|
|
||||||
dep_xkbcommon,
|
|
||||||
dependency('wayland-cursor'),
|
|
||||||
dependency('cairo')
|
|
||||||
],
|
|
||||||
install: true,
|
|
||||||
install_dir: dir_libexec
|
|
||||||
)
|
|
||||||
endif
|
|
||||||
|
|
||||||
tools_enabled = get_option('tools')
|
|
||||||
tools_list = [
|
|
||||||
{
|
|
||||||
'name': 'calibrator',
|
|
||||||
'sources': [ 'calibrator.c' ],
|
|
||||||
'deps': [ dep_toytoolkit, dep_matrix_c ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'debug',
|
|
||||||
'sources': [
|
|
||||||
'weston-debug.c',
|
|
||||||
weston_debug_client_protocol_h,
|
|
||||||
weston_debug_protocol_c,
|
|
||||||
],
|
|
||||||
'deps': [ dep_wayland_client ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'terminal',
|
|
||||||
'sources': [ 'terminal.c' ],
|
|
||||||
'deps': [ dep_toytoolkit ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'touch-calibrator',
|
|
||||||
'sources': [
|
|
||||||
'touch-calibrator.c',
|
|
||||||
weston_touch_calibration_client_protocol_h,
|
|
||||||
weston_touch_calibration_protocol_c,
|
|
||||||
],
|
|
||||||
'deps': [ dep_toytoolkit, dep_matrix_c ],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
foreach t : tools_list
|
|
||||||
if tools_enabled.contains(t.get('name'))
|
|
||||||
executable(
|
|
||||||
'weston-@0@'.format(t.get('name')),
|
|
||||||
t.get('sources'),
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: t.get('deps', []),
|
|
||||||
install: true
|
|
||||||
)
|
|
||||||
endif
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
demo_clients = [
|
|
||||||
{ 'basename': 'clickdot' },
|
|
||||||
{
|
|
||||||
'basename': 'cliptest',
|
|
||||||
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'basename': 'color',
|
|
||||||
'add_sources': [
|
|
||||||
color_management_v1_client_protocol_h,
|
|
||||||
color_management_v1_protocol_c,
|
|
||||||
single_pixel_buffer_v1_client_protocol_h,
|
|
||||||
single_pixel_buffer_v1_protocol_c,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'basename': 'constraints',
|
|
||||||
'add_sources': [
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'basename': 'content_protection',
|
|
||||||
'add_sources': [
|
|
||||||
weston_content_protection_client_protocol_h,
|
|
||||||
weston_content_protection_protocol_c,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{ 'basename': 'dnd' },
|
|
||||||
{
|
|
||||||
'basename': 'editor',
|
|
||||||
'add_sources': [
|
|
||||||
text_input_unstable_v1_client_protocol_h,
|
|
||||||
text_input_unstable_v1_protocol_c,
|
|
||||||
],
|
|
||||||
'deps': [ 'pangocairo', 'gobject-2.0' ]
|
|
||||||
},
|
|
||||||
{ 'basename': 'eventdemo' },
|
|
||||||
{ 'basename': 'flower' },
|
|
||||||
{
|
|
||||||
'basename': 'fullscreen',
|
|
||||||
},
|
|
||||||
{ 'basename': 'image' },
|
|
||||||
{
|
|
||||||
'basename': 'multi-resource',
|
|
||||||
'add_sources': [
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'basename': 'presentation-shm',
|
|
||||||
'add_sources': [
|
|
||||||
presentation_time_client_protocol_h,
|
|
||||||
presentation_time_protocol_c,
|
|
||||||
xdg_shell_client_protocol_h,
|
|
||||||
xdg_shell_protocol_c,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ 'basename': 'resizor' },
|
|
||||||
{
|
|
||||||
'basename': 'scaler',
|
|
||||||
'add_sources': [
|
|
||||||
viewporter_client_protocol_h,
|
|
||||||
viewporter_protocol_c,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ 'basename': 'smoke' },
|
|
||||||
{ 'basename': 'stacking' },
|
|
||||||
{
|
|
||||||
'basename': 'subsurfaces',
|
|
||||||
'deps': [ 'egl', 'glesv2', 'wayland-egl' ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'basename': 'tablet',
|
|
||||||
'add_sources': [
|
|
||||||
tablet_unstable_v2_client_protocol_h,
|
|
||||||
tablet_unstable_v2_protocol_c,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ 'basename': 'transformed' },
|
|
||||||
]
|
|
||||||
|
|
||||||
if get_option('demo-clients')
|
|
||||||
foreach t : demo_clients
|
|
||||||
t_name = 'weston-' + t.get('basename')
|
|
||||||
t_srcs = [ t.get('basename') + '.c' ] + t.get('add_sources', [])
|
|
||||||
t_deps = [ dep_toytoolkit, t.get('dep_objs', []) ]
|
|
||||||
foreach depname : t.get('deps', [])
|
|
||||||
dep = dependency(depname, required: false)
|
|
||||||
if not dep.found()
|
|
||||||
error('@0@ requires \'@1@\' which was not found. If you rather not build this, set \'-Ddemo-clients=false\'.'.format(t_name, depname))
|
|
||||||
endif
|
|
||||||
t_deps += dep
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
executable(
|
|
||||||
t_name, t_srcs,
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: t_deps,
|
|
||||||
install: true
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('shell-desktop')
|
|
||||||
exe_keyboard = executable(
|
|
||||||
'weston-keyboard',
|
|
||||||
'keyboard.c',
|
|
||||||
text_input_unstable_v1_client_protocol_h,
|
|
||||||
text_input_unstable_v1_protocol_c,
|
|
||||||
input_method_unstable_v1_client_protocol_h,
|
|
||||||
input_method_unstable_v1_protocol_c,
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: dep_toytoolkit,
|
|
||||||
install_dir: get_option('libexecdir'),
|
|
||||||
install: true
|
|
||||||
)
|
|
||||||
env_modmap += 'weston-keyboard=@0@;'.format(exe_keyboard.full_path())
|
|
||||||
|
|
||||||
exe_shell_desktop = executable(
|
|
||||||
'weston-desktop-shell',
|
|
||||||
'desktop-shell.c',
|
|
||||||
weston_desktop_shell_client_protocol_h,
|
|
||||||
weston_desktop_shell_protocol_c,
|
|
||||||
tablet_unstable_v2_client_protocol_h,
|
|
||||||
tablet_unstable_v2_protocol_c,
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: dep_toytoolkit,
|
|
||||||
install_dir: get_option('libexecdir'),
|
|
||||||
install: true
|
|
||||||
)
|
|
||||||
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('shell-desktop') or get_option('shell-kiosk') or get_option('shell-ivi')
|
|
||||||
exe_shooter = executable(
|
|
||||||
'weston-screenshooter',
|
|
||||||
'screenshot.c',
|
|
||||||
weston_output_capture_client_protocol_h,
|
|
||||||
weston_output_capture_protocol_c,
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: [
|
|
||||||
dep_client_buffer,
|
|
||||||
dep_toytoolkit,
|
|
||||||
dep_libweston_private, # for pixel-formats.h
|
|
||||||
dep_pixman,
|
|
||||||
],
|
|
||||||
install_dir: get_option('bindir'),
|
|
||||||
install: true
|
|
||||||
)
|
|
||||||
env_modmap += 'weston-screenshooter=@0@;'.format(exe_shooter.full_path())
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('shell-ivi')
|
|
||||||
exe_shell_ivi_ui = executable(
|
|
||||||
'weston-ivi-shell-user-interface',
|
|
||||||
'ivi-shell-user-interface.c',
|
|
||||||
ivi_hmi_controller_client_protocol_h,
|
|
||||||
ivi_hmi_controller_protocol_c,
|
|
||||||
ivi_application_client_protocol_h,
|
|
||||||
ivi_application_protocol_c,
|
|
||||||
include_directories: common_inc,
|
|
||||||
dependencies: dep_toytoolkit,
|
|
||||||
install: true,
|
|
||||||
install_dir: get_option('libexecdir')
|
|
||||||
)
|
|
||||||
env_modmap += 'weston-ivi-shell-user-interface=@0@;'.format(exe_shell_ivi_ui.full_path())
|
|
||||||
endif
|
|
||||||
|
|
@ -1,31 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2011 Benjamin Franzke
|
* Copyright © 2011 Benjamin Franzke
|
||||||
* Copyright © 2010, 2013 Intel Corporation
|
* Copyright © 2010, 2013 Intel Corporation
|
||||||
* Copyright © 2021 Collabora, Ltd.
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -36,18 +33,12 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <poll.h>
|
#include <sys/poll.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "shared/os-compatibility.h"
|
#include "../shared/os-compatibility.h"
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
|
||||||
|
|
||||||
static int running = 1;
|
|
||||||
|
|
||||||
struct device {
|
struct device {
|
||||||
enum { KEYBOARD, POINTER } type;
|
enum { KEYBOARD, POINTER } type;
|
||||||
|
|
@ -66,9 +57,9 @@ struct display {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
|
struct wl_shell *shell;
|
||||||
struct wl_seat *seat;
|
struct wl_seat *seat;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
struct xdg_wm_base *wm_base;
|
|
||||||
uint32_t formats;
|
uint32_t formats;
|
||||||
struct wl_list devices;
|
struct wl_list devices;
|
||||||
};
|
};
|
||||||
|
|
@ -77,9 +68,7 @@ struct window {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
int width, height;
|
int width, height;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct wl_shell_surface *shell_surface;
|
||||||
struct xdg_surface *xdg_surface;
|
|
||||||
bool wait_for_configure;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -92,6 +81,20 @@ static const struct wl_buffer_listener buffer_listener = {
|
||||||
buffer_release
|
buffer_release
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
xzalloc(size_t s)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
p = calloc(1, s);
|
||||||
|
if (p == NULL) {
|
||||||
|
fprintf(stderr, "%s: out of memory\n", program_invocation_short_name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
attach_buffer(struct window *window, int width, int height)
|
attach_buffer(struct window *window, int width, int height)
|
||||||
{
|
{
|
||||||
|
|
@ -104,8 +107,8 @@ attach_buffer(struct window *window, int width, int height)
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
fd = os_create_anonymous_file(size);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
size, strerror(errno));
|
size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,54 +126,27 @@ attach_buffer(struct window *window, int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
|
handle_ping(void *data, struct wl_shell_surface *shell_surface,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
wl_shell_surface_pong(shell_surface, serial);
|
||||||
|
|
||||||
xdg_surface_ack_configure(surface, serial);
|
|
||||||
|
|
||||||
if (window->wait_for_configure) {
|
|
||||||
|
|
||||||
attach_buffer(window, window->width, window->height);
|
|
||||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
|
|
||||||
window->wait_for_configure = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
|
||||||
handle_xdg_surface_configure,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
handle_configure(void *data, struct wl_shell_surface *shell_surface,
|
||||||
{
|
uint32_t edges, int32_t width, int32_t height)
|
||||||
xdg_wm_base_pong(shell, serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_wm_base_listener wm_base_listener = {
|
|
||||||
xdg_wm_base_ping,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|
||||||
int32_t width, int32_t height,
|
|
||||||
struct wl_array *state)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
|
||||||
{
|
{
|
||||||
running = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
static const struct wl_shell_surface_listener shell_surface_listener = {
|
||||||
handle_toplevel_configure,
|
handle_ping,
|
||||||
handle_toplevel_close,
|
handle_configure,
|
||||||
|
handle_popup_done
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct window *
|
static struct window *
|
||||||
|
|
@ -183,19 +159,19 @@ create_window(struct display *display, int width, int height)
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
window->surface = wl_compositor_create_surface(display->compositor);
|
window->surface = wl_compositor_create_surface(display->compositor);
|
||||||
|
window->shell_surface = wl_shell_get_shell_surface(display->shell,
|
||||||
|
window->surface);
|
||||||
|
|
||||||
window->xdg_surface =
|
if (window->shell_surface)
|
||||||
xdg_wm_base_get_xdg_surface(display->wm_base, window->surface);
|
wl_shell_surface_add_listener(window->shell_surface,
|
||||||
assert(window->xdg_surface);
|
&shell_surface_listener, window);
|
||||||
|
|
||||||
xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
|
wl_shell_surface_set_title(window->shell_surface, "simple-shm");
|
||||||
|
|
||||||
window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
|
wl_shell_surface_set_toplevel(window->shell_surface);
|
||||||
assert(window->xdg_toplevel);
|
|
||||||
xdg_toplevel_add_listener(window->xdg_toplevel,
|
wl_surface_damage(window->surface, 0, 0, width, height);
|
||||||
&xdg_toplevel_listener, window);
|
attach_buffer(window, width, height);
|
||||||
xdg_toplevel_set_title(window->xdg_toplevel, "multi-resource");
|
|
||||||
window->wait_for_configure = true;
|
|
||||||
wl_surface_commit(window->surface);
|
wl_surface_commit(window->surface);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
|
|
@ -204,11 +180,7 @@ create_window(struct display *display, int width, int height)
|
||||||
static void
|
static void
|
||||||
destroy_window(struct window *window)
|
destroy_window(struct window *window)
|
||||||
{
|
{
|
||||||
if (window->xdg_surface)
|
wl_shell_surface_destroy(window->shell_surface);
|
||||||
xdg_surface_destroy(window->xdg_surface);
|
|
||||||
if (window->xdg_toplevel)
|
|
||||||
xdg_toplevel_destroy(window->xdg_toplevel);
|
|
||||||
|
|
||||||
wl_surface_destroy(window->surface);
|
wl_surface_destroy(window->surface);
|
||||||
free(window);
|
free(window);
|
||||||
}
|
}
|
||||||
|
|
@ -235,10 +207,9 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
d->compositor =
|
d->compositor =
|
||||||
wl_registry_bind(registry,
|
wl_registry_bind(registry,
|
||||||
id, &wl_compositor_interface, 1);
|
id, &wl_compositor_interface, 1);
|
||||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
} else if (strcmp(interface, "wl_shell") == 0) {
|
||||||
d->wm_base = wl_registry_bind(registry,
|
d->shell = wl_registry_bind(registry,
|
||||||
id, &xdg_wm_base_interface, 1);
|
id, &wl_shell_interface, 1);
|
||||||
xdg_wm_base_add_listener(d->wm_base, &wm_base_listener, d);
|
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
d->shm = wl_registry_bind(registry,
|
d->shm = wl_registry_bind(registry,
|
||||||
id, &wl_shm_interface, 1);
|
id, &wl_shm_interface, 1);
|
||||||
|
|
@ -287,11 +258,6 @@ create_display(void)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!display->wm_base) {
|
|
||||||
fprintf(stderr, "xdg-shell required!\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_init(&display->devices);
|
wl_list_init(&display->devices);
|
||||||
|
|
||||||
return display;
|
return display;
|
||||||
|
|
@ -340,8 +306,6 @@ static void
|
||||||
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
uint32_t format, int fd, uint32_t size)
|
uint32_t format, int fd, uint32_t size)
|
||||||
{
|
{
|
||||||
/* Just so we don’t leak the keymap fd */
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -443,8 +407,8 @@ destroy_display(struct display *display)
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
if (display->wm_base)
|
if (display->shell)
|
||||||
xdg_wm_base_destroy(display->wm_base);
|
wl_shell_destroy(display->shell);
|
||||||
|
|
||||||
if (display->seat)
|
if (display->seat)
|
||||||
wl_seat_destroy(display->seat);
|
wl_seat_destroy(display->seat);
|
||||||
|
|
@ -458,6 +422,7 @@ destroy_display(struct display *display)
|
||||||
free(display);
|
free(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int running = 1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
signal_int(int signum)
|
signal_int(int signum)
|
||||||
|
|
@ -480,13 +445,12 @@ create_device(struct display *display, const char *time_desc, int type)
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
start_time = strtoul(time_desc, &tail, 10);
|
start_time = strtoul(time_desc, &tail, 10);
|
||||||
if (errno || tail == time_desc)
|
if (errno)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (*tail == ':') {
|
if (*tail == ':') {
|
||||||
time_desc = tail + 1;
|
end_time = strtoul(tail + 1, &tail, 10);
|
||||||
end_time = strtoul(time_desc, &tail, 10);
|
if (errno || *tail != '\0')
|
||||||
if (errno || tail == time_desc || *tail != '\0')
|
|
||||||
goto error;
|
goto error;
|
||||||
} else if (*tail != '\0') {
|
} else if (*tail != '\0') {
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
||||||
368
clients/nested-client.c
Normal file
|
|
@ -0,0 +1,368 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2013 Intel Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <wayland-egl.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
|
#include "../shared/platform.h"
|
||||||
|
|
||||||
|
struct window;
|
||||||
|
struct seat;
|
||||||
|
|
||||||
|
struct nested_client {
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
EGLContext egl_context;
|
||||||
|
EGLConfig egl_config;
|
||||||
|
EGLSurface egl_surface;
|
||||||
|
struct program *color_program;
|
||||||
|
|
||||||
|
GLuint vert, frag, program;
|
||||||
|
GLuint rotation;
|
||||||
|
GLuint pos;
|
||||||
|
GLuint col;
|
||||||
|
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct wl_egl_window *native;
|
||||||
|
int width, height;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define POS 0
|
||||||
|
#define COL 1
|
||||||
|
|
||||||
|
static GLuint
|
||||||
|
create_shader(const char *source, GLenum shader_type)
|
||||||
|
{
|
||||||
|
GLuint shader;
|
||||||
|
GLint status;
|
||||||
|
|
||||||
|
shader = glCreateShader(shader_type);
|
||||||
|
if (shader == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
glShaderSource(shader, 1, (const char **) &source, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (!status) {
|
||||||
|
char log[1000];
|
||||||
|
GLsizei len;
|
||||||
|
glGetShaderInfoLog(shader, 1000, &len, log);
|
||||||
|
fprintf(stderr, "Error: compiling %s: %*s\n",
|
||||||
|
shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
||||||
|
len, log);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_program(struct nested_client *client,
|
||||||
|
const char *vert, const char *frag)
|
||||||
|
{
|
||||||
|
GLint status;
|
||||||
|
|
||||||
|
client->vert = create_shader(vert, GL_VERTEX_SHADER);
|
||||||
|
client->frag = create_shader(frag, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
client->program = glCreateProgram();
|
||||||
|
glAttachShader(client->program, client->frag);
|
||||||
|
glAttachShader(client->program, client->vert);
|
||||||
|
glBindAttribLocation(client->program, POS, "pos");
|
||||||
|
glBindAttribLocation(client->program, COL, "color");
|
||||||
|
glLinkProgram(client->program);
|
||||||
|
|
||||||
|
glGetProgramiv(client->program, GL_LINK_STATUS, &status);
|
||||||
|
if (!status) {
|
||||||
|
char log[1000];
|
||||||
|
GLsizei len;
|
||||||
|
glGetProgramInfoLog(client->program, 1000, &len, log);
|
||||||
|
fprintf(stderr, "Error: linking:\n%*s\n", len, log);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
client->rotation =
|
||||||
|
glGetUniformLocation(client->program, "rotation");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char vertex_shader_text[] =
|
||||||
|
"uniform mat4 rotation;\n"
|
||||||
|
"attribute vec4 pos;\n"
|
||||||
|
"attribute vec4 color;\n"
|
||||||
|
"varying vec4 v_color;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = rotation * pos;\n"
|
||||||
|
" v_color = color;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char color_fragment_shader_text[] =
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"varying vec4 v_color;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_FragColor = v_color;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static void
|
||||||
|
render_triangle(struct nested_client *client, uint32_t time)
|
||||||
|
{
|
||||||
|
static const GLfloat verts[3][2] = {
|
||||||
|
{ -0.5, -0.5 },
|
||||||
|
{ 0.5, -0.5 },
|
||||||
|
{ 0, 0.5 }
|
||||||
|
};
|
||||||
|
static const GLfloat colors[3][3] = {
|
||||||
|
{ 1, 0, 0 },
|
||||||
|
{ 0, 1, 0 },
|
||||||
|
{ 0, 0, 1 }
|
||||||
|
};
|
||||||
|
GLfloat angle;
|
||||||
|
GLfloat rotation[4][4] = {
|
||||||
|
{ 1, 0, 0, 0 },
|
||||||
|
{ 0, 1, 0, 0 },
|
||||||
|
{ 0, 0, 1, 0 },
|
||||||
|
{ 0, 0, 0, 1 }
|
||||||
|
};
|
||||||
|
static const int32_t speed_div = 5;
|
||||||
|
static uint32_t start_time = 0;
|
||||||
|
|
||||||
|
if (client->program == 0)
|
||||||
|
create_program(client, vertex_shader_text,
|
||||||
|
color_fragment_shader_text);
|
||||||
|
|
||||||
|
if (start_time == 0)
|
||||||
|
start_time = time;
|
||||||
|
|
||||||
|
angle = ((time - start_time) / speed_div) % 360 * M_PI / 180.0;
|
||||||
|
rotation[0][0] = cos(angle);
|
||||||
|
rotation[0][2] = sin(angle);
|
||||||
|
rotation[2][0] = -sin(angle);
|
||||||
|
rotation[2][2] = cos(angle);
|
||||||
|
|
||||||
|
glClearColor(0.4, 0.4, 0.4, 1.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glUseProgram(client->program);
|
||||||
|
|
||||||
|
glViewport(0, 0, client->width, client->height);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(client->rotation, 1, GL_FALSE,
|
||||||
|
(GLfloat *) rotation);
|
||||||
|
|
||||||
|
glVertexAttribPointer(POS, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||||
|
glVertexAttribPointer(COL, 3, GL_FLOAT, GL_FALSE, 0, colors);
|
||||||
|
glEnableVertexAttribArray(POS);
|
||||||
|
glEnableVertexAttribArray(COL);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(POS);
|
||||||
|
glDisableVertexAttribArray(COL);
|
||||||
|
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_callback(void *data, struct wl_callback *callback, uint32_t time);
|
||||||
|
|
||||||
|
static const struct wl_callback_listener frame_listener = {
|
||||||
|
frame_callback
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_callback(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
struct nested_client *client = data;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
callback = wl_surface_frame(client->surface);
|
||||||
|
wl_callback_add_listener(callback, &frame_listener, client);
|
||||||
|
|
||||||
|
render_triangle(client, time);
|
||||||
|
|
||||||
|
eglSwapBuffers(client->egl_display, client->egl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
|
uint32_t name, const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
struct nested_client *client = data;
|
||||||
|
|
||||||
|
if (strcmp(interface, "wl_compositor") == 0) {
|
||||||
|
client->compositor =
|
||||||
|
wl_registry_bind(registry, name,
|
||||||
|
&wl_compositor_interface, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_handle_global_remove(void *data, struct wl_registry *registry,
|
||||||
|
uint32_t name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
registry_handle_global,
|
||||||
|
registry_handle_global_remove
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct nested_client *
|
||||||
|
nested_client_create(void)
|
||||||
|
{
|
||||||
|
static const EGLint context_attribs[] = {
|
||||||
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EGLint config_attribs[] = {
|
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
|
EGL_RED_SIZE, 1,
|
||||||
|
EGL_GREEN_SIZE, 1,
|
||||||
|
EGL_BLUE_SIZE, 1,
|
||||||
|
EGL_ALPHA_SIZE, 1,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
EGLint major, minor, n;
|
||||||
|
EGLBoolean ret;
|
||||||
|
|
||||||
|
struct nested_client *client;
|
||||||
|
|
||||||
|
client = malloc(sizeof *client);
|
||||||
|
if (client == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
client->width = 250;
|
||||||
|
client->height = 250;
|
||||||
|
|
||||||
|
client->display = wl_display_connect(NULL);
|
||||||
|
|
||||||
|
client->registry = wl_display_get_registry(client->display);
|
||||||
|
wl_registry_add_listener(client->registry,
|
||||||
|
®istry_listener, client);
|
||||||
|
|
||||||
|
/* get globals */
|
||||||
|
wl_display_roundtrip(client->display);
|
||||||
|
|
||||||
|
client->egl_display =
|
||||||
|
weston_platform_get_egl_display(EGL_PLATFORM_WAYLAND_KHR,
|
||||||
|
client->display, NULL);
|
||||||
|
if (client->egl_display == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = eglInitialize(client->egl_display, &major, &minor);
|
||||||
|
if (!ret)
|
||||||
|
return NULL;
|
||||||
|
ret = eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
|
if (!ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = eglChooseConfig(client->egl_display, config_attribs,
|
||||||
|
&client->egl_config, 1, &n);
|
||||||
|
if (!ret || n != 1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
client->egl_context = eglCreateContext(client->egl_display,
|
||||||
|
client->egl_config,
|
||||||
|
EGL_NO_CONTEXT,
|
||||||
|
context_attribs);
|
||||||
|
if (!client->egl_context)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
client->surface = wl_compositor_create_surface(client->compositor);
|
||||||
|
|
||||||
|
client->native = wl_egl_window_create(client->surface,
|
||||||
|
client->width, client->height);
|
||||||
|
|
||||||
|
client->egl_surface = weston_platform_create_egl_surface(client->egl_display,
|
||||||
|
client->egl_config,
|
||||||
|
client->native, NULL);
|
||||||
|
|
||||||
|
eglMakeCurrent(client->egl_display, client->egl_surface,
|
||||||
|
client->egl_surface, client->egl_context);
|
||||||
|
|
||||||
|
wl_egl_window_resize(client->native,
|
||||||
|
client->width, client->height, 0, 0);
|
||||||
|
|
||||||
|
frame_callback(client, NULL, 0);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nested_client_destroy(struct nested_client *client)
|
||||||
|
{
|
||||||
|
eglMakeCurrent(client->egl_display,
|
||||||
|
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||||
|
EGL_NO_CONTEXT);
|
||||||
|
|
||||||
|
wl_egl_window_destroy(client->native);
|
||||||
|
|
||||||
|
wl_surface_destroy(client->surface);
|
||||||
|
|
||||||
|
if (client->compositor)
|
||||||
|
wl_compositor_destroy(client->compositor);
|
||||||
|
|
||||||
|
wl_registry_destroy(client->registry);
|
||||||
|
wl_display_flush(client->display);
|
||||||
|
wl_display_disconnect(client->display);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct nested_client *client;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (getenv("WAYLAND_SOCKET") == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"must be run by nested, don't run standalone\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = nested_client_create();
|
||||||
|
if (client == NULL)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
while (ret != -1)
|
||||||
|
ret = wl_display_dispatch(client->display);
|
||||||
|
|
||||||
|
nested_client_destroy(client);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1140
clients/nested.c
Normal file
|
|
@ -3,29 +3,27 @@
|
||||||
* Copyright © 2010 Intel Corporation
|
* Copyright © 2010 Intel Corporation
|
||||||
* Copyright © 2014 Collabora, Ltd.
|
* Copyright © 2014 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -35,15 +33,12 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "shared/helpers.h"
|
#include "../shared/os-compatibility.h"
|
||||||
#include <libweston/zalloc.h>
|
#include "presentation_timing-client-protocol.h"
|
||||||
#include "shared/timespec-util.h"
|
|
||||||
#include "shared/os-compatibility.h"
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
#include "presentation-time-client-protocol.h"
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
|
||||||
|
|
||||||
enum run_mode {
|
enum run_mode {
|
||||||
RUN_MODE_FEEDBACK,
|
RUN_MODE_FEEDBACK,
|
||||||
|
|
@ -67,12 +62,12 @@ struct display {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct xdg_wm_base *wm_base;
|
struct wl_shell *shell;
|
||||||
|
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
uint32_t formats;
|
uint32_t formats;
|
||||||
|
|
||||||
struct wp_presentation *presentation;
|
struct presentation *presentation;
|
||||||
clockid_t clk_id;
|
clockid_t clk_id;
|
||||||
|
|
||||||
struct wl_list output_list; /* struct output::link */
|
struct wl_list output_list; /* struct output::link */
|
||||||
|
|
@ -81,7 +76,7 @@ struct display {
|
||||||
struct feedback {
|
struct feedback {
|
||||||
struct window *window;
|
struct window *window;
|
||||||
unsigned frame_no;
|
unsigned frame_no;
|
||||||
struct wp_presentation_feedback *feedback;
|
struct presentation_feedback *feedback;
|
||||||
struct timespec commit;
|
struct timespec commit;
|
||||||
struct timespec target;
|
struct timespec target;
|
||||||
uint32_t frame_stamp;
|
uint32_t frame_stamp;
|
||||||
|
|
@ -100,15 +95,12 @@ struct window {
|
||||||
int width, height;
|
int width, height;
|
||||||
enum run_mode mode;
|
enum run_mode mode;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct xdg_surface *xdg_surface;
|
struct wl_shell_surface *shell_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
|
||||||
uint32_t configure_serial;
|
|
||||||
|
|
||||||
struct buffer *buffers;
|
struct buffer *buffers;
|
||||||
int num_buffers;
|
int num_buffers;
|
||||||
int next;
|
int next;
|
||||||
int refresh_nsec;
|
int refresh_nsec;
|
||||||
int commit_delay_msecs;
|
|
||||||
|
|
||||||
struct wl_callback *callback;
|
struct wl_callback *callback;
|
||||||
struct wl_list feedback_list;
|
struct wl_list feedback_list;
|
||||||
|
|
@ -145,14 +137,14 @@ create_shm_buffers(struct display *display, struct buffer **buffers,
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
fd = os_create_anonymous_file(size);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
size, strerror(errno));
|
size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (data == MAP_FAILED) {
|
if (data == MAP_FAILED) {
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
fprintf(stderr, "mmap failed: %m\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -184,67 +176,44 @@ create_shm_buffers(struct display *display, struct buffer **buffers,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_wm_base_handle_ping(void *data, struct xdg_wm_base *xdg_wm_base,
|
handle_ping(void *data, struct wl_shell_surface *shell_surface,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
xdg_wm_base_pong(xdg_wm_base, serial);
|
wl_shell_surface_pong(shell_surface, serial);
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
|
||||||
.ping = xdg_wm_base_handle_ping,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_surface,
|
|
||||||
uint32_t serial)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
|
|
||||||
window->configure_serial = serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
|
||||||
.configure = xdg_surface_handle_configure,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|
||||||
int32_t width, int32_t height,
|
|
||||||
struct wl_array *states)
|
|
||||||
{
|
|
||||||
/* noop */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
handle_configure(void *data, struct wl_shell_surface *shell_surface,
|
||||||
|
uint32_t edges, int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "presentation-shm exiting\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
static void
|
||||||
.configure = xdg_toplevel_handle_configure,
|
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
|
||||||
.close = xdg_toplevel_handle_close,
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_shell_surface_listener shell_surface_listener = {
|
||||||
|
handle_ping,
|
||||||
|
handle_configure,
|
||||||
|
handle_popup_done
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct window *
|
static struct window *
|
||||||
create_window(struct display *display, int width, int height,
|
create_window(struct display *display, int width, int height,
|
||||||
enum run_mode mode, int commit_delay_msecs)
|
enum run_mode mode)
|
||||||
{
|
{
|
||||||
struct window *window;
|
struct window *window;
|
||||||
char title[128];
|
char title[128];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
snprintf(title, sizeof(title),
|
snprintf(title, sizeof(title),
|
||||||
"presentation-shm: %s [Delay %i msecs]", run_mode_name[mode],
|
"presentation-shm: %s", run_mode_name[mode]);
|
||||||
commit_delay_msecs);
|
|
||||||
|
|
||||||
window = zalloc(sizeof *window);
|
window = calloc(1, sizeof *window);
|
||||||
if (!window)
|
if (!window)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
window->commit_delay_msecs = commit_delay_msecs;
|
|
||||||
window->mode = mode;
|
window->mode = mode;
|
||||||
window->callback = NULL;
|
window->callback = NULL;
|
||||||
wl_list_init(&window->feedback_list);
|
wl_list_init(&window->feedback_list);
|
||||||
|
|
@ -252,30 +221,16 @@ create_window(struct display *display, int width, int height,
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
window->surface = wl_compositor_create_surface(display->compositor);
|
window->surface = wl_compositor_create_surface(display->compositor);
|
||||||
window->xdg_surface = xdg_wm_base_get_xdg_surface(display->wm_base,
|
window->shell_surface = wl_shell_get_shell_surface(display->shell,
|
||||||
window->surface);
|
window->surface);
|
||||||
|
|
||||||
if (!window->xdg_surface)
|
if (window->shell_surface)
|
||||||
return NULL;
|
wl_shell_surface_add_listener(window->shell_surface,
|
||||||
|
&shell_surface_listener, window);
|
||||||
|
|
||||||
window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
|
wl_shell_surface_set_title(window->shell_surface, title);
|
||||||
|
|
||||||
if (!window->xdg_toplevel)
|
wl_shell_surface_set_toplevel(window->shell_surface);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
xdg_wm_base_add_listener(display->wm_base, &xdg_wm_base_listener,
|
|
||||||
NULL);
|
|
||||||
xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener,
|
|
||||||
window);
|
|
||||||
xdg_toplevel_add_listener(window->xdg_toplevel, &xdg_toplevel_listener,
|
|
||||||
window);
|
|
||||||
|
|
||||||
xdg_toplevel_set_title(window->xdg_toplevel, title);
|
|
||||||
xdg_toplevel_set_min_size(window->xdg_toplevel, width, height);
|
|
||||||
xdg_toplevel_set_max_size(window->xdg_toplevel, width, height);
|
|
||||||
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
wl_display_roundtrip(window->display->display);
|
|
||||||
|
|
||||||
window->num_buffers = 60;
|
window->num_buffers = 60;
|
||||||
window->refresh_nsec = NSEC_PER_SEC / 60; /* 60 Hz guess */
|
window->refresh_nsec = NSEC_PER_SEC / 60; /* 60 Hz guess */
|
||||||
|
|
@ -293,7 +248,7 @@ static void
|
||||||
destroy_feedback(struct feedback *feedback)
|
destroy_feedback(struct feedback *feedback)
|
||||||
{
|
{
|
||||||
if (feedback->feedback)
|
if (feedback->feedback)
|
||||||
wp_presentation_feedback_destroy(feedback->feedback);
|
presentation_feedback_destroy(feedback->feedback);
|
||||||
|
|
||||||
wl_list_remove(&feedback->link);
|
wl_list_remove(&feedback->link);
|
||||||
free(feedback);
|
free(feedback);
|
||||||
|
|
@ -315,7 +270,7 @@ destroy_window(struct window *window)
|
||||||
if (window->callback)
|
if (window->callback)
|
||||||
wl_callback_destroy(window->callback);
|
wl_callback_destroy(window->callback);
|
||||||
|
|
||||||
xdg_surface_destroy(window->xdg_surface);
|
wl_shell_surface_destroy(window->shell_surface);
|
||||||
wl_surface_destroy(window->surface);
|
wl_surface_destroy(window->surface);
|
||||||
|
|
||||||
for (i = 0; i < window->num_buffers; i++)
|
for (i = 0; i < window->num_buffers; i++)
|
||||||
|
|
@ -386,7 +341,7 @@ paint_pixels(void *image, int width, int height, uint32_t phase)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
feedback_sync_output(void *data,
|
feedback_sync_output(void *data,
|
||||||
struct wp_presentation_feedback *presentation_feedback,
|
struct presentation_feedback *presentation_feedback,
|
||||||
struct wl_output *output)
|
struct wl_output *output)
|
||||||
{
|
{
|
||||||
/* not interested */
|
/* not interested */
|
||||||
|
|
@ -399,10 +354,10 @@ pflags_to_str(uint32_t flags, char *str, unsigned len)
|
||||||
uint32_t flag;
|
uint32_t flag;
|
||||||
char sym;
|
char sym;
|
||||||
} desc[] = {
|
} desc[] = {
|
||||||
{ WP_PRESENTATION_FEEDBACK_KIND_VSYNC, 's' },
|
{ PRESENTATION_FEEDBACK_KIND_VSYNC, 's' },
|
||||||
{ WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK, 'c' },
|
{ PRESENTATION_FEEDBACK_KIND_HW_CLOCK, 'c' },
|
||||||
{ WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION, 'e' },
|
{ PRESENTATION_FEEDBACK_KIND_HW_COMPLETION, 'e' },
|
||||||
{ WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY, 'z' },
|
{ PRESENTATION_FEEDBACK_KIND_ZERO_COPY, 'z' },
|
||||||
};
|
};
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
|
@ -423,6 +378,14 @@ timespec_to_ms(const struct timespec *ts)
|
||||||
return (uint32_t)ts->tv_sec * 1000 + ts->tv_nsec / 1000000;
|
return (uint32_t)ts->tv_sec * 1000 + ts->tv_nsec / 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timespec_from_proto(struct timespec *tm, uint32_t tv_sec_hi,
|
||||||
|
uint32_t tv_sec_lo, uint32_t tv_nsec)
|
||||||
|
{
|
||||||
|
tm->tv_sec = ((uint64_t)tv_sec_hi << 32) + tv_sec_lo;
|
||||||
|
tm->tv_nsec = tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
timespec_diff_to_usec(const struct timespec *a, const struct timespec *b)
|
timespec_diff_to_usec(const struct timespec *a, const struct timespec *b)
|
||||||
{
|
{
|
||||||
|
|
@ -434,7 +397,7 @@ timespec_diff_to_usec(const struct timespec *a, const struct timespec *b)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
feedback_presented(void *data,
|
feedback_presented(void *data,
|
||||||
struct wp_presentation_feedback *presentation_feedback,
|
struct presentation_feedback *presentation_feedback,
|
||||||
uint32_t tv_sec_hi,
|
uint32_t tv_sec_hi,
|
||||||
uint32_t tv_sec_lo,
|
uint32_t tv_sec_lo,
|
||||||
uint32_t tv_nsec,
|
uint32_t tv_nsec,
|
||||||
|
|
@ -446,7 +409,7 @@ feedback_presented(void *data,
|
||||||
struct feedback *feedback = data;
|
struct feedback *feedback = data;
|
||||||
struct window *window = feedback->window;
|
struct window *window = feedback->window;
|
||||||
struct feedback *prev_feedback = window->received_feedback;
|
struct feedback *prev_feedback = window->received_feedback;
|
||||||
uint64_t seq = u64_from_u32s(seq_hi, seq_lo);
|
uint64_t seq = ((uint64_t)seq_hi << 32) + seq_lo;
|
||||||
const struct timespec *prevpresent;
|
const struct timespec *prevpresent;
|
||||||
uint32_t commit, present;
|
uint32_t commit, present;
|
||||||
uint32_t f2c, c2p, f2p;
|
uint32_t f2c, c2p, f2p;
|
||||||
|
|
@ -490,7 +453,7 @@ feedback_presented(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
feedback_discarded(void *data,
|
feedback_discarded(void *data,
|
||||||
struct wp_presentation_feedback *presentation_feedback)
|
struct presentation_feedback *presentation_feedback)
|
||||||
{
|
{
|
||||||
struct feedback *feedback = data;
|
struct feedback *feedback = data;
|
||||||
|
|
||||||
|
|
@ -499,34 +462,17 @@ feedback_discarded(void *data,
|
||||||
destroy_feedback(feedback);
|
destroy_feedback(feedback);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wp_presentation_feedback_listener feedback_listener = {
|
static const struct presentation_feedback_listener feedback_listener = {
|
||||||
feedback_sync_output,
|
feedback_sync_output,
|
||||||
feedback_presented,
|
feedback_presented,
|
||||||
feedback_discarded
|
feedback_discarded
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
window_emulate_rendering(struct window *window)
|
|
||||||
{
|
|
||||||
struct timespec delay;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (window->commit_delay_msecs <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delay.tv_sec = window->commit_delay_msecs / 1000;
|
|
||||||
delay.tv_nsec = (window->commit_delay_msecs % 1000) * 1000000;
|
|
||||||
|
|
||||||
ret = nanosleep(&delay, NULL);
|
|
||||||
if (ret)
|
|
||||||
printf("nanosleep failed: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_create_feedback(struct window *window, uint32_t frame_stamp)
|
window_create_feedback(struct window *window, uint32_t frame_stamp)
|
||||||
{
|
{
|
||||||
static unsigned seq;
|
static unsigned seq;
|
||||||
struct wp_presentation *pres = window->display->presentation;
|
struct presentation *pres = window->display->presentation;
|
||||||
struct feedback *feedback;
|
struct feedback *feedback;
|
||||||
|
|
||||||
seq++;
|
seq++;
|
||||||
|
|
@ -534,17 +480,16 @@ window_create_feedback(struct window *window, uint32_t frame_stamp)
|
||||||
if (!pres)
|
if (!pres)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
feedback = zalloc(sizeof *feedback);
|
feedback = calloc(1, sizeof *feedback);
|
||||||
if (!feedback)
|
if (!feedback)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
feedback->window = window;
|
feedback->window = window;
|
||||||
feedback->feedback = wp_presentation_feedback(pres, window->surface);
|
feedback->feedback = presentation_feedback(pres, window->surface);
|
||||||
wp_presentation_feedback_add_listener(feedback->feedback,
|
presentation_feedback_add_listener(feedback->feedback,
|
||||||
&feedback_listener, feedback);
|
&feedback_listener, feedback);
|
||||||
|
|
||||||
feedback->frame_no = seq;
|
feedback->frame_no = seq;
|
||||||
|
|
||||||
clock_gettime(window->display->clk_id, &feedback->commit);
|
clock_gettime(window->display->clk_id, &feedback->commit);
|
||||||
feedback->frame_stamp = frame_stamp;
|
feedback->frame_stamp = frame_stamp;
|
||||||
feedback->target = feedback->commit;
|
feedback->target = feedback->commit;
|
||||||
|
|
@ -560,12 +505,6 @@ window_commit_next(struct window *window)
|
||||||
buffer = window_next_buffer(window);
|
buffer = window_next_buffer(window);
|
||||||
assert(buffer);
|
assert(buffer);
|
||||||
|
|
||||||
if (window->configure_serial) {
|
|
||||||
xdg_surface_ack_configure(window->xdg_surface,
|
|
||||||
window->configure_serial);
|
|
||||||
window->configure_serial = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||||
wl_surface_commit(window->surface);
|
wl_surface_commit(window->surface);
|
||||||
|
|
@ -585,8 +524,6 @@ redraw_mode_feedback(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
if (callback)
|
if (callback)
|
||||||
wl_callback_destroy(callback);
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
window_emulate_rendering(window);
|
|
||||||
|
|
||||||
window->callback = wl_surface_frame(window->surface);
|
window->callback = wl_surface_frame(window->surface);
|
||||||
wl_callback_add_listener(window->callback,
|
wl_callback_add_listener(window->callback,
|
||||||
&frame_listener_mode_feedback, window);
|
&frame_listener_mode_feedback, window);
|
||||||
|
|
@ -599,22 +536,21 @@ static const struct wl_callback_listener frame_listener_mode_feedback = {
|
||||||
redraw_mode_feedback
|
redraw_mode_feedback
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct wp_presentation_feedback_listener feedkick_listener;
|
static const struct presentation_feedback_listener feedkick_listener;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_feedkick(struct window *window)
|
window_feedkick(struct window *window)
|
||||||
{
|
{
|
||||||
struct wp_presentation *pres = window->display->presentation;
|
struct presentation *pres = window->display->presentation;
|
||||||
struct wp_presentation_feedback *fback;
|
struct presentation_feedback *fback;
|
||||||
|
|
||||||
fback = wp_presentation_feedback(pres, window->surface);
|
fback = presentation_feedback(pres, window->surface);
|
||||||
wp_presentation_feedback_add_listener(fback, &feedkick_listener,
|
presentation_feedback_add_listener(fback, &feedkick_listener, window);
|
||||||
window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
feedkick_presented(void *data,
|
feedkick_presented(void *data,
|
||||||
struct wp_presentation_feedback *presentation_feedback,
|
struct presentation_feedback *presentation_feedback,
|
||||||
uint32_t tv_sec_hi,
|
uint32_t tv_sec_hi,
|
||||||
uint32_t tv_sec_lo,
|
uint32_t tv_sec_lo,
|
||||||
uint32_t tv_nsec,
|
uint32_t tv_nsec,
|
||||||
|
|
@ -625,12 +561,11 @@ feedkick_presented(void *data,
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct window *window = data;
|
||||||
|
|
||||||
wp_presentation_feedback_destroy(presentation_feedback);
|
presentation_feedback_destroy(presentation_feedback);
|
||||||
window->refresh_nsec = refresh_nsec;
|
window->refresh_nsec = refresh_nsec;
|
||||||
|
|
||||||
switch (window->mode) {
|
switch (window->mode) {
|
||||||
case RUN_MODE_PRESENT:
|
case RUN_MODE_PRESENT:
|
||||||
window_emulate_rendering(window);
|
|
||||||
window_create_feedback(window, 0);
|
window_create_feedback(window, 0);
|
||||||
window_feedkick(window);
|
window_feedkick(window);
|
||||||
window_commit_next(window);
|
window_commit_next(window);
|
||||||
|
|
@ -643,15 +578,14 @@ feedkick_presented(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
feedkick_discarded(void *data,
|
feedkick_discarded(void *data,
|
||||||
struct wp_presentation_feedback *presentation_feedback)
|
struct presentation_feedback *presentation_feedback)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct window *window = data;
|
||||||
|
|
||||||
wp_presentation_feedback_destroy(presentation_feedback);
|
presentation_feedback_destroy(presentation_feedback);
|
||||||
|
|
||||||
switch (window->mode) {
|
switch (window->mode) {
|
||||||
case RUN_MODE_PRESENT:
|
case RUN_MODE_PRESENT:
|
||||||
window_emulate_rendering(window);
|
|
||||||
window_create_feedback(window, 0);
|
window_create_feedback(window, 0);
|
||||||
window_feedkick(window);
|
window_feedkick(window);
|
||||||
window_commit_next(window);
|
window_commit_next(window);
|
||||||
|
|
@ -662,7 +596,7 @@ feedkick_discarded(void *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wp_presentation_feedback_listener feedkick_listener = {
|
static const struct presentation_feedback_listener feedkick_listener = {
|
||||||
feedback_sync_output,
|
feedback_sync_output,
|
||||||
feedkick_presented,
|
feedkick_presented,
|
||||||
feedkick_discarded
|
feedkick_discarded
|
||||||
|
|
@ -671,8 +605,6 @@ static const struct wp_presentation_feedback_listener feedkick_listener = {
|
||||||
static void
|
static void
|
||||||
firstdraw_mode_burst(struct window *window)
|
firstdraw_mode_burst(struct window *window)
|
||||||
{
|
{
|
||||||
window_emulate_rendering(window);
|
|
||||||
|
|
||||||
switch (window->mode) {
|
switch (window->mode) {
|
||||||
case RUN_MODE_PRESENT:
|
case RUN_MODE_PRESENT:
|
||||||
window_create_feedback(window, 0);
|
window_create_feedback(window, 0);
|
||||||
|
|
@ -718,7 +650,7 @@ display_add_output(struct display *d, uint32_t name, uint32_t version)
|
||||||
{
|
{
|
||||||
struct output *o;
|
struct output *o;
|
||||||
|
|
||||||
o = zalloc(sizeof(*o));
|
o = calloc(1, sizeof(*o));
|
||||||
assert(o);
|
assert(o);
|
||||||
|
|
||||||
o->output = wl_registry_bind(d->registry, name,
|
o->output = wl_registry_bind(d->registry, name,
|
||||||
|
|
@ -728,7 +660,7 @@ display_add_output(struct display *d, uint32_t name, uint32_t version)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
presentation_clock_id(void *data, struct wp_presentation *presentation,
|
presentation_clock_id(void *data, struct presentation *presentation,
|
||||||
uint32_t clk_id)
|
uint32_t clk_id)
|
||||||
{
|
{
|
||||||
struct display *d = data;
|
struct display *d = data;
|
||||||
|
|
@ -736,7 +668,7 @@ presentation_clock_id(void *data, struct wp_presentation *presentation,
|
||||||
d->clk_id = clk_id;
|
d->clk_id = clk_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wp_presentation_listener presentation_listener = {
|
static const struct presentation_listener presentation_listener = {
|
||||||
presentation_clock_id
|
presentation_clock_id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -762,22 +694,21 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
d->compositor =
|
d->compositor =
|
||||||
wl_registry_bind(registry,
|
wl_registry_bind(registry,
|
||||||
name, &wl_compositor_interface, 1);
|
name, &wl_compositor_interface, 1);
|
||||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
} else if (strcmp(interface, "wl_shell") == 0) {
|
||||||
d->wm_base =
|
d->shell = wl_registry_bind(registry,
|
||||||
wl_registry_bind(registry, name,
|
name, &wl_shell_interface, 1);
|
||||||
&xdg_wm_base_interface, 1);
|
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
d->shm = wl_registry_bind(registry,
|
d->shm = wl_registry_bind(registry,
|
||||||
name, &wl_shm_interface, 1);
|
name, &wl_shm_interface, 1);
|
||||||
wl_shm_add_listener(d->shm, &shm_listener, d);
|
wl_shm_add_listener(d->shm, &shm_listener, d);
|
||||||
} else if (strcmp(interface, "wl_output") == 0) {
|
} else if (strcmp(interface, "wl_output") == 0) {
|
||||||
display_add_output(d, name, version);
|
display_add_output(d, name, version);
|
||||||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
} else if (strcmp(interface, "presentation") == 0) {
|
||||||
d->presentation =
|
d->presentation =
|
||||||
wl_registry_bind(registry,
|
wl_registry_bind(registry,
|
||||||
name, &wp_presentation_interface, 2);
|
name, &presentation_interface, 1);
|
||||||
wp_presentation_add_listener(d->presentation,
|
presentation_add_listener(d->presentation,
|
||||||
&presentation_listener, d);
|
&presentation_listener, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -851,8 +782,8 @@ destroy_display(struct display *display)
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
if (display->wm_base)
|
if (display->shell)
|
||||||
xdg_wm_base_destroy(display->wm_base);
|
wl_shell_destroy(display->shell);
|
||||||
|
|
||||||
if (display->compositor)
|
if (display->compositor)
|
||||||
wl_compositor_destroy(display->compositor);
|
wl_compositor_destroy(display->compositor);
|
||||||
|
|
@ -876,12 +807,10 @@ usage(const char *prog, int exit_code)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [mode] [options]\n"
|
fprintf(stderr, "Usage: %s [mode] [options]\n"
|
||||||
"where 'mode' is one of\n"
|
"where 'mode' is one of\n"
|
||||||
" -f\t\trun in feedback mode (default)\n"
|
" -f\trun in feedback mode (default)\n"
|
||||||
" -i\t\trun in feedback-idle mode; sleep 1s between frames\n"
|
" -i\trun in feedback-idle mode; sleep 1s between frames\n"
|
||||||
" -p\t\trun in low-latency presentation mode\n"
|
" -p\trun in low-latency presentation mode\n"
|
||||||
"and 'options' may include\n"
|
"and 'options' may include\n",
|
||||||
" -d msecs\temulate the time used for rendering by a delay \n"
|
|
||||||
"\t\tof the given milliseconds before commit\n\n",
|
|
||||||
prog);
|
prog);
|
||||||
|
|
||||||
fprintf(stderr, "Printed timing statistics, depending on mode:\n"
|
fprintf(stderr, "Printed timing statistics, depending on mode:\n"
|
||||||
|
|
@ -906,7 +835,6 @@ main(int argc, char **argv)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
enum run_mode mode = RUN_MODE_FEEDBACK;
|
enum run_mode mode = RUN_MODE_FEEDBACK;
|
||||||
int i;
|
int i;
|
||||||
int commit_delay_msecs = 0;
|
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (strcmp("-f", argv[i]) == 0)
|
if (strcmp("-f", argv[i]) == 0)
|
||||||
|
|
@ -915,16 +843,12 @@ main(int argc, char **argv)
|
||||||
mode = RUN_MODE_FEEDBACK_IDLE;
|
mode = RUN_MODE_FEEDBACK_IDLE;
|
||||||
else if (strcmp("-p", argv[i]) == 0)
|
else if (strcmp("-p", argv[i]) == 0)
|
||||||
mode = RUN_MODE_PRESENT;
|
mode = RUN_MODE_PRESENT;
|
||||||
else if ((strcmp("-d", argv[i]) == 0) && (i + 1 < argc)) {
|
|
||||||
i++;
|
|
||||||
commit_delay_msecs = atoi(argv[i]);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
usage(argv[0], EXIT_FAILURE);
|
usage(argv[0], EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
display = create_display();
|
display = create_display();
|
||||||
window = create_window(display, 250, 250, mode, commit_delay_msecs);
|
window = create_window(display, 250, 250, mode);
|
||||||
if (!window)
|
if (!window)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,27 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2010 Intel Corporation
|
* Copyright © 2010 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -31,13 +29,11 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "shared/xalloc.h"
|
|
||||||
|
|
||||||
struct spring {
|
struct spring {
|
||||||
double current;
|
double current;
|
||||||
|
|
@ -53,11 +49,6 @@ struct resizor {
|
||||||
struct spring width;
|
struct spring width;
|
||||||
struct spring height;
|
struct spring height;
|
||||||
struct wl_callback *frame_callback;
|
struct wl_callback *frame_callback;
|
||||||
bool pointer_locked;
|
|
||||||
bool locked_frame_callback_registered;
|
|
||||||
struct input *locked_input;
|
|
||||||
float pointer_x;
|
|
||||||
float pointer_y;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -227,162 +218,21 @@ show_menu(struct resizor *resizor, struct input *input, uint32_t time)
|
||||||
x - 10, y - 10, menu_func, entries, 4);
|
x - 10, y - 10, menu_func, entries, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
locked_pointer_handle_motion(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
uint32_t time,
|
|
||||||
float dx,
|
|
||||||
float dy,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct resizor *resizor = data;
|
|
||||||
|
|
||||||
resizor->width.current += dx;
|
|
||||||
resizor->width.previous = resizor->width.current;
|
|
||||||
resizor->width.target = resizor->width.current;
|
|
||||||
|
|
||||||
resizor->height.current += dy;
|
|
||||||
resizor->height.previous = resizor->height.current;
|
|
||||||
resizor->height.target = resizor->height.current;
|
|
||||||
|
|
||||||
widget_schedule_resize(resizor->widget,
|
|
||||||
resizor->width.current,
|
|
||||||
resizor->height.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_pointer_locked(struct window *window, struct input *input, void *data)
|
|
||||||
{
|
|
||||||
struct resizor *resizor = data;
|
|
||||||
|
|
||||||
resizor->pointer_locked = true;
|
|
||||||
input_set_pointer_image(input, CURSOR_BLANK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_pointer_unlocked(struct window *window, struct input *input, void *data)
|
|
||||||
{
|
|
||||||
struct resizor *resizor = data;
|
|
||||||
|
|
||||||
resizor->pointer_locked = false;
|
|
||||||
input_set_pointer_image(input, CURSOR_LEFT_PTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_callback_listener locked_pointer_frame_listener;
|
|
||||||
|
|
||||||
static void
|
|
||||||
locked_pointer_frame_callback(void *data,
|
|
||||||
struct wl_callback *callback,
|
|
||||||
uint32_t time)
|
|
||||||
{
|
|
||||||
struct resizor *resizor = data;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
struct rectangle allocation;
|
|
||||||
float x, y;
|
|
||||||
|
|
||||||
if (resizor->pointer_locked) {
|
|
||||||
widget_get_allocation(resizor->widget, &allocation);
|
|
||||||
|
|
||||||
x = resizor->pointer_x + (allocation.width - allocation.x);
|
|
||||||
y = resizor->pointer_y + (allocation.height - allocation.y);
|
|
||||||
|
|
||||||
widget_set_locked_pointer_cursor_hint(resizor->widget, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_callback_destroy(callback);
|
|
||||||
|
|
||||||
surface = window_get_wl_surface(resizor->window);
|
|
||||||
callback = wl_surface_frame(surface);
|
|
||||||
wl_callback_add_listener(callback,
|
|
||||||
&locked_pointer_frame_listener,
|
|
||||||
resizor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_callback_listener locked_pointer_frame_listener = {
|
|
||||||
locked_pointer_frame_callback
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
button_handler(struct widget *widget,
|
button_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
uint32_t button, enum wl_pointer_button_state state, void *data)
|
uint32_t button, enum wl_pointer_button_state state, void *data)
|
||||||
{
|
{
|
||||||
struct resizor *resizor = data;
|
struct resizor *resizor = data;
|
||||||
struct rectangle allocation;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
struct wl_callback *callback;
|
|
||||||
|
|
||||||
if (button == BTN_RIGHT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
switch (button) {
|
||||||
show_menu(resizor, input, time);
|
case BTN_RIGHT:
|
||||||
} else if (button == BTN_LEFT &&
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||||
state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
show_menu(resizor, input, time);
|
||||||
window_get_allocation(resizor->window, &allocation);
|
break;
|
||||||
|
|
||||||
resizor->width.current = allocation.width;
|
|
||||||
resizor->width.previous = allocation.width;
|
|
||||||
resizor->width.target = allocation.width;
|
|
||||||
|
|
||||||
resizor->height.current = allocation.height;
|
|
||||||
resizor->height.previous = allocation.height;
|
|
||||||
resizor->height.target = allocation.height;
|
|
||||||
|
|
||||||
window_lock_pointer(resizor->window, input);
|
|
||||||
window_set_pointer_locked_handler(resizor->window,
|
|
||||||
handle_pointer_locked,
|
|
||||||
handle_pointer_unlocked);
|
|
||||||
resizor->locked_input = input;
|
|
||||||
|
|
||||||
if (resizor->locked_frame_callback_registered)
|
|
||||||
return;
|
|
||||||
|
|
||||||
surface = window_get_wl_surface(resizor->window);
|
|
||||||
callback = wl_surface_frame(surface);
|
|
||||||
wl_callback_add_listener(callback,
|
|
||||||
&locked_pointer_frame_listener,
|
|
||||||
resizor);
|
|
||||||
resizor->locked_frame_callback_registered = true;
|
|
||||||
} else if (button == BTN_LEFT &&
|
|
||||||
state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
|
||||||
input_set_pointer_image(input, CURSOR_LEFT_PTR);
|
|
||||||
window_unlock_pointer(resizor->window);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_cursor_inv_offset(struct resizor *resizor, float x, float y)
|
|
||||||
{
|
|
||||||
struct rectangle allocation;
|
|
||||||
|
|
||||||
widget_get_allocation(resizor->widget, &allocation);
|
|
||||||
|
|
||||||
resizor->pointer_x = x - (allocation.width - allocation.x);
|
|
||||||
resizor->pointer_y = y - (allocation.height - allocation.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
enter_handler(struct widget *widget,
|
|
||||||
struct input *input,
|
|
||||||
float x, float y, void *data)
|
|
||||||
{
|
|
||||||
struct resizor *resizor = data;
|
|
||||||
|
|
||||||
set_cursor_inv_offset(resizor, x , y);
|
|
||||||
|
|
||||||
return CURSOR_LEFT_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
motion_handler(struct widget *widget,
|
|
||||||
struct input *input, uint32_t time,
|
|
||||||
float x, float y, void *data)
|
|
||||||
{
|
|
||||||
struct resizor *resizor = data;
|
|
||||||
|
|
||||||
set_cursor_inv_offset(resizor, x , y);
|
|
||||||
|
|
||||||
return CURSOR_LEFT_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct resizor *
|
static struct resizor *
|
||||||
resizor_create(struct display *display)
|
resizor_create(struct display *display)
|
||||||
{
|
{
|
||||||
|
|
@ -392,8 +242,6 @@ resizor_create(struct display *display)
|
||||||
resizor->window = window_create(display);
|
resizor->window = window_create(display);
|
||||||
resizor->widget = window_frame_create(resizor->window, resizor);
|
resizor->widget = window_frame_create(resizor->window, resizor);
|
||||||
window_set_title(resizor->window, "Wayland Resizor");
|
window_set_title(resizor->window, "Wayland Resizor");
|
||||||
window_set_appid(resizor->window,
|
|
||||||
"org.freedesktop.weston.wayland-resizor");
|
|
||||||
resizor->display = display;
|
resizor->display = display;
|
||||||
|
|
||||||
window_set_key_handler(resizor->window, key_handler);
|
window_set_key_handler(resizor->window, key_handler);
|
||||||
|
|
@ -402,12 +250,6 @@ resizor_create(struct display *display)
|
||||||
window_set_keyboard_focus_handler(resizor->window,
|
window_set_keyboard_focus_handler(resizor->window,
|
||||||
keyboard_focus_handler);
|
keyboard_focus_handler);
|
||||||
|
|
||||||
widget_set_enter_handler(resizor->widget, enter_handler);
|
|
||||||
widget_set_motion_handler(resizor->widget, motion_handler);
|
|
||||||
|
|
||||||
window_set_locked_pointer_motion_handler(
|
|
||||||
resizor->window, locked_pointer_handle_motion);
|
|
||||||
|
|
||||||
widget_set_button_handler(resizor->widget, button_handler);
|
widget_set_button_handler(resizor->widget, button_handler);
|
||||||
|
|
||||||
resizor->height.previous = 400;
|
resizor->height.previous = 400;
|
||||||
|
|
@ -442,8 +284,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
display = display_create(&argc, argv);
|
display = display_create(&argc, argv);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,36 @@
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
* Copyright © 2013 Collabora, Ltd.
|
* Copyright © 2013 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "viewporter-client-protocol.h"
|
#include "scaler-client-protocol.h"
|
||||||
|
|
||||||
#define BUFFER_SCALE 2
|
#define BUFFER_SCALE 2
|
||||||
static const int BUFFER_WIDTH = 421 * BUFFER_SCALE;
|
static const int BUFFER_WIDTH = 421 * BUFFER_SCALE;
|
||||||
|
|
@ -52,8 +49,9 @@ struct box {
|
||||||
struct widget *widget;
|
struct widget *widget;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
struct wp_viewporter *viewporter;
|
struct wl_scaler *scaler;
|
||||||
struct wp_viewport *viewport;
|
int scaler_version;
|
||||||
|
struct wl_viewport *viewport;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MODE_NO_VIEWPORT,
|
MODE_NO_VIEWPORT,
|
||||||
|
|
@ -85,30 +83,33 @@ set_my_viewport(struct box *box)
|
||||||
src_width = wl_fixed_from_double((RECT_W - 0.5) / BUFFER_SCALE);
|
src_width = wl_fixed_from_double((RECT_W - 0.5) / BUFFER_SCALE);
|
||||||
src_height = wl_fixed_from_double((RECT_H - 0.5) / BUFFER_SCALE);
|
src_height = wl_fixed_from_double((RECT_H - 0.5) / BUFFER_SCALE);
|
||||||
|
|
||||||
|
if (box->scaler_version < 2 && box->mode != MODE_SRC_DST) {
|
||||||
|
fprintf(stderr, "Error: server's wl_scaler interface version "
|
||||||
|
"%d does not support this mode.\n",
|
||||||
|
box->scaler_version);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
switch (box->mode){
|
switch (box->mode){
|
||||||
case MODE_SRC_ONLY:
|
case MODE_SRC_ONLY:
|
||||||
/* In SRC_ONLY mode we're just cropping - in order
|
wl_viewport_set_source(box->viewport, src_x, src_y,
|
||||||
* for the surface size to remain an integer, the
|
|
||||||
* compositor will generate an error if we use a
|
|
||||||
* fractional width or height.
|
|
||||||
*
|
|
||||||
* We use fractional width/height for the other cases
|
|
||||||
* to ensure fractional values are still tested.
|
|
||||||
*/
|
|
||||||
src_width = wl_fixed_from_int(RECT_W / BUFFER_SCALE);
|
|
||||||
src_height = wl_fixed_from_int(RECT_H / BUFFER_SCALE);
|
|
||||||
wp_viewport_set_source(box->viewport, src_x, src_y,
|
|
||||||
src_width, src_height);
|
src_width, src_height);
|
||||||
break;
|
break;
|
||||||
case MODE_DST_ONLY:
|
case MODE_DST_ONLY:
|
||||||
wp_viewport_set_destination(box->viewport,
|
wl_viewport_set_destination(box->viewport,
|
||||||
dst_width, dst_height);
|
dst_width, dst_height);
|
||||||
break;
|
break;
|
||||||
case MODE_SRC_DST:
|
case MODE_SRC_DST:
|
||||||
wp_viewport_set_source(box->viewport, src_x, src_y,
|
if (box->scaler_version < 2) {
|
||||||
src_width, src_height);
|
wl_viewport_set(box->viewport,
|
||||||
wp_viewport_set_destination(box->viewport,
|
src_x, src_y, src_width, src_height,
|
||||||
dst_width, dst_height);
|
dst_width, dst_height);
|
||||||
|
} else {
|
||||||
|
wl_viewport_set_source(box->viewport, src_x, src_y,
|
||||||
|
src_width, src_height);
|
||||||
|
wl_viewport_set_destination(box->viewport,
|
||||||
|
dst_width, dst_height);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(!"not reached");
|
assert(!"not reached");
|
||||||
|
|
@ -121,7 +122,7 @@ resize_handler(struct widget *widget,
|
||||||
{
|
{
|
||||||
struct box *box = data;
|
struct box *box = data;
|
||||||
|
|
||||||
/* Don't resize me */
|
/* Dont resize me */
|
||||||
widget_set_size(box->widget, box->width, box->height);
|
widget_set_size(box->widget, box->width, box->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,11 +187,14 @@ global_handler(struct display *display, uint32_t name,
|
||||||
{
|
{
|
||||||
struct box *box = data;
|
struct box *box = data;
|
||||||
|
|
||||||
if (strcmp(interface, "wp_viewporter") == 0) {
|
if (strcmp(interface, "wl_scaler") == 0) {
|
||||||
box->viewporter = display_bind(display, name,
|
box->scaler_version = version < 2 ? version : 2;
|
||||||
&wp_viewporter_interface, 1);
|
|
||||||
|
|
||||||
box->viewport = wp_viewporter_get_viewport(box->viewporter,
|
box->scaler = display_bind(display, name,
|
||||||
|
&wl_scaler_interface,
|
||||||
|
box->scaler_version);
|
||||||
|
|
||||||
|
box->viewport = wl_scaler_get_viewport(box->scaler,
|
||||||
widget_get_wl_surface(box->widget));
|
widget_get_wl_surface(box->widget));
|
||||||
|
|
||||||
set_my_viewport(box);
|
set_my_viewport(box);
|
||||||
|
|
@ -289,8 +293,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,7 +306,6 @@ main(int argc, char *argv[])
|
||||||
box.window = window_create(d);
|
box.window = window_create(d);
|
||||||
box.widget = window_add_widget(box.window, &box);
|
box.widget = window_add_widget(box.window, &box);
|
||||||
window_set_title(box.window, "Scaler Test Box");
|
window_set_title(box.window, "Scaler Test Box");
|
||||||
window_set_appid(box.window, "org.freedesktop.weston.scaler-test-box");
|
|
||||||
window_set_buffer_scale(box.window, BUFFER_SCALE);
|
window_set_buffer_scale(box.window, BUFFER_SCALE);
|
||||||
|
|
||||||
widget_set_resize_handler(box.widget, resize_handler);
|
widget_set_resize_handler(box.widget, resize_handler);
|
||||||
|
|
@ -317,11 +319,6 @@ main(int argc, char *argv[])
|
||||||
display_set_user_data(box.display, &box);
|
display_set_user_data(box.display, &box);
|
||||||
display_set_global_handler(box.display, global_handler);
|
display_set_global_handler(box.display, global_handler);
|
||||||
|
|
||||||
if (box.mode != MODE_NO_VIEWPORT && !box.viewport) {
|
|
||||||
fprintf(stderr, "compositor doesn't support viewporter\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
display_run(d);
|
display_run(d);
|
||||||
|
|
||||||
widget_destroy(box.widget);
|
widget_destroy(box.widget);
|
||||||
|
|
|
||||||
|
|
@ -1,348 +1,155 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
* Copyright 2022 Collabora, Ltd.
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <cairo.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <pixman.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <fcntl.h>
|
||||||
#include <sys/param.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include "screenshooter-client-protocol.h"
|
||||||
|
#include "../shared/os-compatibility.h"
|
||||||
|
|
||||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
/* The screenshooter is a good example of a custom object exposed by
|
||||||
#include "pixel-formats.h"
|
* the compositor and serves as a test bed for implementing client
|
||||||
#include "shared/client-buffer-util.h"
|
* side marshalling outside libwayland.so */
|
||||||
#include "shared/file-util.h"
|
|
||||||
#include "shared/os-compatibility.h"
|
|
||||||
#include "shared/string-helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "weston-output-capture-client-protocol.h"
|
|
||||||
|
|
||||||
struct screenshooter_app {
|
static struct wl_shm *shm;
|
||||||
struct wl_display *display;
|
static struct screenshooter *screenshooter;
|
||||||
struct wl_registry *registry;
|
static struct wl_list output_list;
|
||||||
struct wl_shm *shm;
|
int min_x, min_y, max_x, max_y;
|
||||||
struct zwp_linux_dmabuf_v1 *dmabuf;
|
int buffer_copy_done;
|
||||||
struct weston_capture_v1 *capture_factory;
|
|
||||||
|
|
||||||
bool verbose;
|
|
||||||
const struct pixel_format_info *requested_format;
|
|
||||||
enum weston_capture_v1_source src_type;
|
|
||||||
enum client_buffer_type buffer_type;
|
|
||||||
|
|
||||||
struct wl_list output_list; /* struct screenshooter_output::link */
|
|
||||||
|
|
||||||
bool retry;
|
|
||||||
bool failed;
|
|
||||||
int waitcount;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct screenshooter_buffer {
|
|
||||||
struct client_buffer *buf;
|
|
||||||
pixman_image_t *image;
|
|
||||||
enum weston_capture_v1_source src_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct screenshooter_output {
|
struct screenshooter_output {
|
||||||
struct screenshooter_app *app;
|
struct wl_output *output;
|
||||||
uint32_t name;
|
struct wl_buffer *buffer;
|
||||||
struct wl_list link; /* struct screenshooter_app::output_list */
|
int width, height, offset_x, offset_y;
|
||||||
|
void *data;
|
||||||
struct wl_output *wl_output;
|
struct wl_list link;
|
||||||
int offset_x, offset_y;
|
|
||||||
|
|
||||||
struct weston_capture_source_v1 *source;
|
|
||||||
|
|
||||||
int buffer_width;
|
|
||||||
int buffer_height;
|
|
||||||
struct wl_array formats;
|
|
||||||
bool formats_done;
|
|
||||||
struct screenshooter_buffer *buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct buffer_size {
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
int min_x, min_y;
|
|
||||||
int max_x, max_y;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct screenshooter_buffer *
|
|
||||||
screenshot_create_shm_buffer(struct screenshooter_app *app,
|
|
||||||
size_t width, size_t height,
|
|
||||||
const struct pixel_format_info *fmt)
|
|
||||||
{
|
|
||||||
struct screenshooter_buffer *buffer;
|
|
||||||
|
|
||||||
assert(width > 0);
|
|
||||||
assert(height > 0);
|
|
||||||
assert(fmt && fmt->bpp > 0);
|
|
||||||
assert(fmt->pixman_format);
|
|
||||||
|
|
||||||
buffer = xzalloc(sizeof *buffer);
|
|
||||||
|
|
||||||
buffer->buf = client_buffer_util_create_shm_buffer(app->shm,
|
|
||||||
fmt,
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
|
|
||||||
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
|
||||||
width, height,
|
|
||||||
buffer->buf->data,
|
|
||||||
buffer->buf->strides[0]);
|
|
||||||
abort_oom_if_null(buffer->image);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct screenshooter_buffer *
|
|
||||||
screenshot_create_udmabuf(struct screenshooter_app *app,
|
|
||||||
int width, int height,
|
|
||||||
const struct pixel_format_info *fmt)
|
|
||||||
{
|
|
||||||
struct screenshooter_buffer* buffer = NULL;
|
|
||||||
|
|
||||||
assert(width > 0);
|
|
||||||
assert(height > 0);
|
|
||||||
assert(fmt);
|
|
||||||
|
|
||||||
buffer = xzalloc(sizeof *buffer);
|
|
||||||
|
|
||||||
buffer->buf = client_buffer_util_create_dmabuf_buffer(app->display,
|
|
||||||
app->dmabuf,
|
|
||||||
fmt,
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
|
|
||||||
if (fmt->pixman_format) {
|
|
||||||
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
|
||||||
width, height,
|
|
||||||
buffer->buf->data,
|
|
||||||
buffer->buf->strides[0]);
|
|
||||||
abort_oom_if_null(buffer->image);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
screenshooter_buffer_destroy(struct screenshooter_buffer *buffer)
|
|
||||||
{
|
|
||||||
if (!buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (buffer->image)
|
|
||||||
pixman_image_unref(buffer->image);
|
|
||||||
|
|
||||||
client_buffer_util_destroy_buffer(buffer->buf);
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
capture_source_handle_format(void *data,
|
|
||||||
struct weston_capture_source_v1 *proxy,
|
|
||||||
uint32_t drm_format)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output = data;
|
|
||||||
uint32_t *fmt;
|
|
||||||
|
|
||||||
assert(output->source == proxy);
|
|
||||||
|
|
||||||
if (output->formats_done) {
|
|
||||||
wl_array_release(&output->formats);
|
|
||||||
wl_array_init(&output->formats);
|
|
||||||
output->formats_done = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt = wl_array_add(&output->formats, sizeof(uint32_t));
|
|
||||||
assert(fmt);
|
|
||||||
*fmt = drm_format;
|
|
||||||
|
|
||||||
if (output->app->verbose) {
|
|
||||||
const struct pixel_format_info *fmt_info;
|
|
||||||
|
|
||||||
fmt_info = pixel_format_get_info(drm_format);
|
|
||||||
assert(fmt_info);
|
|
||||||
printf("Got format %s / 0x%x\n", fmt_info->drm_format_name,
|
|
||||||
drm_format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
capture_source_handle_formats_done(void *data,
|
|
||||||
struct weston_capture_source_v1 *proxy)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output = data;
|
|
||||||
|
|
||||||
output->formats_done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
capture_source_handle_size(void *data,
|
|
||||||
struct weston_capture_source_v1 *proxy,
|
|
||||||
int32_t width, int32_t height)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output = data;
|
|
||||||
|
|
||||||
assert(width > 0);
|
|
||||||
assert(height > 0);
|
|
||||||
|
|
||||||
output->buffer_width = width;
|
|
||||||
output->buffer_height = height;
|
|
||||||
|
|
||||||
if (output->app->verbose)
|
|
||||||
printf("Got size %dx%d\n", width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
capture_source_handle_complete(void *data,
|
|
||||||
struct weston_capture_source_v1 *proxy)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output = data;
|
|
||||||
|
|
||||||
output->app->waitcount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
capture_source_handle_retry(void *data,
|
|
||||||
struct weston_capture_source_v1 *proxy)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output = data;
|
|
||||||
|
|
||||||
output->app->waitcount--;
|
|
||||||
output->app->retry = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
capture_source_handle_failed(void *data,
|
|
||||||
struct weston_capture_source_v1 *proxy,
|
|
||||||
const char *msg)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output = data;
|
|
||||||
|
|
||||||
output->app->waitcount--;
|
|
||||||
/* We don't set app.failed here because there could be other
|
|
||||||
* outputs we still want to capture!
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (msg)
|
|
||||||
fprintf(stderr, "Output capture error: %s\n", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct weston_capture_source_v1_listener capture_source_handlers = {
|
|
||||||
.format = capture_source_handle_format,
|
|
||||||
.formats_done = capture_source_handle_formats_done,
|
|
||||||
.size = capture_source_handle_size,
|
|
||||||
.complete = capture_source_handle_complete,
|
|
||||||
.retry = capture_source_handle_retry,
|
|
||||||
.failed = capture_source_handle_failed,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_output(struct screenshooter_app *app, uint32_t output_name, uint32_t version)
|
display_handle_geometry(void *data,
|
||||||
|
struct wl_output *wl_output,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int physical_width,
|
||||||
|
int physical_height,
|
||||||
|
int subpixel,
|
||||||
|
const char *make,
|
||||||
|
const char *model,
|
||||||
|
int transform)
|
||||||
{
|
{
|
||||||
struct screenshooter_output *output;
|
struct screenshooter_output *output;
|
||||||
|
|
||||||
version = MIN(version, 4);
|
output = wl_output_get_user_data(wl_output);
|
||||||
output = xzalloc(sizeof *output);
|
|
||||||
output->app = app;
|
|
||||||
output->name = output_name;
|
|
||||||
output->wl_output = wl_registry_bind(app->registry, output_name,
|
|
||||||
&wl_output_interface, version);
|
|
||||||
abort_oom_if_null(output->wl_output);
|
|
||||||
|
|
||||||
output->source = weston_capture_v1_create(app->capture_factory,
|
if (wl_output == output->output) {
|
||||||
output->wl_output,
|
output->offset_x = x;
|
||||||
app->src_type);
|
output->offset_y = y;
|
||||||
abort_oom_if_null(output->source);
|
}
|
||||||
weston_capture_source_v1_add_listener(output->source,
|
}
|
||||||
&capture_source_handlers, output);
|
|
||||||
|
|
||||||
wl_array_init(&output->formats);
|
static void *
|
||||||
|
xmalloc(size_t size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
wl_list_insert(&app->output_list, &output->link);
|
p = malloc(size);
|
||||||
|
if (p == NULL) {
|
||||||
|
fprintf(stderr, "%s: out of memory\n",
|
||||||
|
program_invocation_short_name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_output(struct screenshooter_output *output)
|
display_handle_mode(void *data,
|
||||||
|
struct wl_output *wl_output,
|
||||||
|
uint32_t flags,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int refresh)
|
||||||
{
|
{
|
||||||
weston_capture_source_v1_destroy(output->source);
|
struct screenshooter_output *output;
|
||||||
|
|
||||||
wl_array_release(&output->formats);
|
output = wl_output_get_user_data(wl_output);
|
||||||
|
|
||||||
if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
|
if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT)) {
|
||||||
wl_output_release(output->wl_output);
|
output->width = width;
|
||||||
else
|
output->height = height;
|
||||||
wl_output_destroy(output->wl_output);
|
}
|
||||||
|
|
||||||
screenshooter_buffer_destroy(output->buffer);
|
|
||||||
wl_list_remove(&output->link);
|
|
||||||
free(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct wl_output_listener output_listener = {
|
||||||
|
display_handle_geometry,
|
||||||
|
display_handle_mode
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
screenshot_done(void *data, struct screenshooter *screenshooter)
|
||||||
|
{
|
||||||
|
buffer_copy_done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct screenshooter_listener screenshooter_listener = {
|
||||||
|
screenshot_done
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_global(void *data, struct wl_registry *registry,
|
handle_global(void *data, struct wl_registry *registry,
|
||||||
uint32_t name, const char *interface, uint32_t version)
|
uint32_t name, const char *interface, uint32_t version)
|
||||||
{
|
{
|
||||||
struct screenshooter_app *app = data;
|
static struct screenshooter_output *output;
|
||||||
|
|
||||||
if (strcmp(interface, wl_output_interface.name) == 0) {
|
if (strcmp(interface, "wl_output") == 0) {
|
||||||
create_output(app, name, version);
|
output = xmalloc(sizeof *output);
|
||||||
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
|
output->output = wl_registry_bind(registry, name,
|
||||||
app->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
&wl_output_interface, 1);
|
||||||
/*
|
wl_list_insert(&output_list, &output->link);
|
||||||
* Not listening for format advertisements,
|
wl_output_add_listener(output->output, &output_listener, output);
|
||||||
* weston_capture_source_v1.format event tells us what to use.
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
*/
|
shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||||
} else if (strcmp(interface, weston_capture_v1_interface.name) == 0) {
|
} else if (strcmp(interface, "screenshooter") == 0) {
|
||||||
app->capture_factory = wl_registry_bind(registry, name,
|
screenshooter = wl_registry_bind(registry, name,
|
||||||
&weston_capture_v1_interface,
|
&screenshooter_interface, 1);
|
||||||
2);
|
|
||||||
} else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) {
|
|
||||||
if (version < 3)
|
|
||||||
return;
|
|
||||||
app->dmabuf = wl_registry_bind(registry, name,
|
|
||||||
&zwp_linux_dmabuf_v1_interface,
|
|
||||||
3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
||||||
{
|
{
|
||||||
/* Dynamic output removals will just fail the respective shot. */
|
/* XXX: unimplemented */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
|
@ -350,390 +157,153 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
handle_global_remove
|
handle_global_remove
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static struct wl_buffer *
|
||||||
screenshooter_output_capture(struct screenshooter_output *output)
|
create_shm_buffer(int width, int height, void **data_out)
|
||||||
{
|
{
|
||||||
const struct pixel_format_info *fmt_info = NULL;
|
struct wl_shm_pool *pool;
|
||||||
uint32_t *fmt;
|
struct wl_buffer *buffer;
|
||||||
|
int fd, size, stride;
|
||||||
|
void *data;
|
||||||
|
|
||||||
screenshooter_buffer_destroy(output->buffer);
|
stride = width * 4;
|
||||||
|
size = stride * height;
|
||||||
|
|
||||||
wl_array_for_each(fmt, &output->formats) {
|
fd = os_create_anonymous_file(size);
|
||||||
fmt_info = pixel_format_get_info(*fmt);
|
if (fd < 0) {
|
||||||
assert(fmt_info);
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
|
size);
|
||||||
if (fmt_info == output->app->requested_format ||
|
return NULL;
|
||||||
output->app->requested_format == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
fmt_info = NULL;
|
|
||||||
}
|
|
||||||
if (!fmt_info) {
|
|
||||||
fprintf(stderr, "No supported format found\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output->app->verbose)
|
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
printf("Creating buffer with format %s / 0x%x and size %ux%u\n",
|
if (data == MAP_FAILED) {
|
||||||
fmt_info->drm_format_name, fmt_info->format,
|
fprintf(stderr, "mmap failed: %m\n");
|
||||||
output->buffer_width, output->buffer_height);
|
close(fd);
|
||||||
|
return NULL;
|
||||||
if (output->app->buffer_type == CLIENT_BUFFER_TYPE_SHM) {
|
|
||||||
output->buffer = screenshot_create_shm_buffer(output->app,
|
|
||||||
output->buffer_width,
|
|
||||||
output->buffer_height,
|
|
||||||
fmt_info);
|
|
||||||
} else if (output->app->buffer_type == CLIENT_BUFFER_TYPE_DMABUF) {
|
|
||||||
output->buffer = screenshot_create_udmabuf(output->app,
|
|
||||||
output->buffer_width,
|
|
||||||
output->buffer_height,
|
|
||||||
fmt_info);
|
|
||||||
}
|
}
|
||||||
abort_oom_if_null(output->buffer);
|
|
||||||
|
|
||||||
weston_capture_source_v1_capture(output->source,
|
pool = wl_shm_create_pool(shm, fd, size);
|
||||||
output->buffer->buf->wl_buffer);
|
close(fd);
|
||||||
output->app->waitcount++;
|
buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride,
|
||||||
|
WL_SHM_FORMAT_XRGB8888);
|
||||||
|
wl_shm_pool_destroy(pool);
|
||||||
|
|
||||||
|
*data_out = data;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
screenshot_write_png(const struct buffer_size *buff_size,
|
write_png(int width, int height)
|
||||||
struct wl_list *output_list)
|
|
||||||
{
|
{
|
||||||
pixman_image_t *shot;
|
int output_stride, buffer_stride, i;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
struct screenshooter_output *output;
|
void *data, *d, *s;
|
||||||
FILE *fp;
|
struct screenshooter_output *output, *next;
|
||||||
char filepath[PATH_MAX];
|
|
||||||
|
|
||||||
shot = pixman_image_create_bits(PIXMAN_a8r8g8b8,
|
buffer_stride = width * 4;
|
||||||
buff_size->width, buff_size->height,
|
|
||||||
NULL, 0);
|
|
||||||
abort_oom_if_null(shot);
|
|
||||||
|
|
||||||
wl_list_for_each(output, output_list, link) {
|
data = xmalloc(buffer_stride * height);
|
||||||
client_buffer_util_maybe_sync_dmabuf_start(output->buffer->buf);
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
wl_list_for_each_safe(output, next, &output_list, link) {
|
||||||
output->buffer->image, /* src */
|
output_stride = output->width * 4;
|
||||||
NULL, /* mask */
|
s = output->data;
|
||||||
shot, /* dest */
|
d = data + (output->offset_y - min_y) * buffer_stride +
|
||||||
0, 0, /* src x,y */
|
(output->offset_x - min_x) * 4;
|
||||||
0, 0, /* mask x,y */
|
|
||||||
output->offset_x, output->offset_y, /* dst x,y */
|
|
||||||
output->buffer_width, output->buffer_height);
|
|
||||||
|
|
||||||
client_buffer_util_maybe_sync_dmabuf_end(output->buffer->buf);
|
for (i = 0; i < output->height; i++) {
|
||||||
|
memcpy(d, s, output_stride);
|
||||||
|
d += buffer_stride;
|
||||||
|
s += output_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data((void *)pixman_image_get_data(shot),
|
surface = cairo_image_surface_create_for_data(data,
|
||||||
CAIRO_FORMAT_ARGB32,
|
CAIRO_FORMAT_ARGB32,
|
||||||
pixman_image_get_width(shot),
|
width, height, buffer_stride);
|
||||||
pixman_image_get_height(shot),
|
cairo_surface_write_to_png(surface, "wayland-screenshot.png");
|
||||||
pixman_image_get_stride(shot));
|
|
||||||
|
|
||||||
fp = file_create_dated(getenv("XDG_PICTURES_DIR"), "wayland-screenshot-",
|
|
||||||
".png", filepath, sizeof(filepath));
|
|
||||||
if (fp) {
|
|
||||||
fclose (fp);
|
|
||||||
cairo_surface_write_to_png(surface, filepath);
|
|
||||||
}
|
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
pixman_image_unref(shot);
|
free(data);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
screenshot_write_yuv(const struct buffer_size *buff_size,
|
|
||||||
struct wl_list *output_list)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
wl_list_for_each(output, output_list, link) {
|
|
||||||
struct screenshooter_buffer *buffer = output->buffer;
|
|
||||||
char filepath[PATH_MAX];
|
|
||||||
char filepath_prefix[100];
|
|
||||||
int write_offset = 0;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
sprintf(filepath_prefix, "wayland-screenshot-output-%d-", i++);
|
|
||||||
fp = file_create_dated(getenv("XDG_PICTURES_DIR"),
|
|
||||||
filepath_prefix, ".yuv", filepath,
|
|
||||||
sizeof(filepath));
|
|
||||||
if (!fp) {
|
|
||||||
fprintf(stderr, "Writing yuv file for output %d failed\n", i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_buffer_util_maybe_sync_dmabuf_start(buffer->buf);
|
|
||||||
|
|
||||||
for (unsigned int j = 0; j < pixel_format_get_plane_count(buffer->buf->fmt); j++) {
|
|
||||||
int plane_height =
|
|
||||||
buffer->buf->height / pixel_format_hsub(buffer->buf->fmt, j);
|
|
||||||
|
|
||||||
for (int k = 0; k < plane_height; k++) {
|
|
||||||
size_t lines_written;
|
|
||||||
|
|
||||||
lines_written = fwrite(buffer->buf->data + write_offset,
|
|
||||||
buffer->buf->bytes_per_line[j],
|
|
||||||
1, fp);
|
|
||||||
if (lines_written != 1) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Writing yuv file for output %d " \
|
|
||||||
"failed during write(): %s\n",
|
|
||||||
i, strerror(errno));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_offset += buffer->buf->strides[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
client_buffer_util_maybe_sync_dmabuf_end(buffer->buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
screenshot_set_buffer_size(struct buffer_size *buff_size,
|
set_buffer_size(int *width, int *height)
|
||||||
struct wl_list *output_list)
|
|
||||||
{
|
{
|
||||||
struct screenshooter_output *output;
|
struct screenshooter_output *output;
|
||||||
buff_size->min_x = buff_size->min_y = INT_MAX;
|
min_x = min_y = INT_MAX;
|
||||||
buff_size->max_x = buff_size->max_y = INT_MIN;
|
max_x = max_y = INT_MIN;
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
|
||||||
wl_list_for_each_reverse(output, output_list, link) {
|
wl_list_for_each_reverse(output, &output_list, link) {
|
||||||
output->offset_x = position;
|
output->offset_x = position;
|
||||||
position += output->buffer_width;
|
position += output->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_list_for_each(output, output_list, link) {
|
wl_list_for_each(output, &output_list, link) {
|
||||||
buff_size->min_x = MIN(buff_size->min_x, output->offset_x);
|
min_x = MIN(min_x, output->offset_x);
|
||||||
buff_size->min_y = MIN(buff_size->min_y, output->offset_y);
|
min_y = MIN(min_y, output->offset_y);
|
||||||
buff_size->max_x =
|
max_x = MAX(max_x, output->offset_x + output->width);
|
||||||
MAX(buff_size->max_x, output->offset_x + output->buffer_width);
|
max_y = MAX(max_y, output->offset_y + output->height);
|
||||||
buff_size->max_y =
|
|
||||||
MAX(buff_size->max_y, output->offset_y + output->buffer_height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buff_size->max_x <= buff_size->min_x ||
|
if (max_x <= min_x || max_y <= min_y)
|
||||||
buff_size->max_y <= buff_size->min_y)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
buff_size->width = buff_size->max_x - buff_size->min_x;
|
*width = max_x - min_x;
|
||||||
buff_size->height = buff_size->max_y - buff_size->min_y;
|
*height = max_y - min_y;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
int main(int argc, char *argv[])
|
||||||
received_formats_for_all_outputs(struct screenshooter_app *app)
|
|
||||||
{
|
{
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
struct screenshooter_output *output;
|
struct screenshooter_output *output;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
wl_list_for_each(output, &app->output_list, link) {
|
if (getenv("WAYLAND_SOCKET") == NULL) {
|
||||||
if (!output->formats_done)
|
fprintf(stderr, "%s must be launched by weston.\n"
|
||||||
return false;
|
"Use the MOD+S shortcut to take a screenshot.\n",
|
||||||
}
|
program_invocation_short_name);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
all_output_formats_are_yuv(struct wl_list *output_list)
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output;
|
|
||||||
int color_model = -1;
|
|
||||||
|
|
||||||
wl_list_for_each(output, output_list, link) {
|
|
||||||
if (color_model == -1) {
|
|
||||||
color_model = output->buffer->buf->fmt->color_model;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)output->buffer->buf->fmt->color_model != color_model) {
|
|
||||||
fprintf(stderr, "Mixing of RGB and YUV output formats not supported\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(color_model == (int)COLOR_MODEL_RGB ||
|
|
||||||
color_model == (int)COLOR_MODEL_YUV);
|
|
||||||
return color_model == COLOR_MODEL_YUV;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_usage_and_exit(void)
|
|
||||||
{
|
|
||||||
printf("usage flags:\n"
|
|
||||||
"\t'-h,--help'"
|
|
||||||
"\n\t\tprint this help output\n"
|
|
||||||
"\t'-v,--verbose'"
|
|
||||||
"\n\t\tprint additional output\n"
|
|
||||||
"\t'-f,--format=<>'"
|
|
||||||
"\n\t\tthe DRM format name to use without the DRM_FORMAT_ prefix, e.g. RGBA8888 or NV12\n"
|
|
||||||
"\n\t\tIn case of YCbCr formats like NV12, instead of a single .png, the output will consist of raw .yuv files for each output."
|
|
||||||
"\n\t\tThese files do not contain any metadata, however that can be added by converting to .y4m with a command like:"
|
|
||||||
"\n\t\tffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m\n"
|
|
||||||
"\n\t\tNote that this may not work for all YCbCr pixel formats.\n"
|
|
||||||
"\t'-s,--source-type=<>'"
|
|
||||||
"\n\t\tframebuffer to use framebuffer source (default), "
|
|
||||||
"\n\t\twriteback to use writeback source\n"
|
|
||||||
"\t'-b,--buffer-type=<>'"
|
|
||||||
"\n\t\tshm to use a SHM buffer (default), "
|
|
||||||
"\n\t\tdmabuf to use a DMA buffer\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct weston_enum_map source_types [] = {
|
|
||||||
{ "framebuffer", WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER },
|
|
||||||
{ "writeback", WESTON_CAPTURE_V1_SOURCE_WRITEBACK },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct weston_enum_map buffer_types [] = {
|
|
||||||
{ "shm", CLIENT_BUFFER_TYPE_SHM },
|
|
||||||
{ "dmabuf", CLIENT_BUFFER_TYPE_DMABUF },
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct screenshooter_output *output;
|
|
||||||
struct screenshooter_output *tmp_output;
|
|
||||||
struct buffer_size buff_size = {};
|
|
||||||
struct screenshooter_app app = {};
|
|
||||||
int c, option_index;
|
|
||||||
|
|
||||||
app.src_type = WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER;
|
|
||||||
app.buffer_type = CLIENT_BUFFER_TYPE_SHM;
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{"help", no_argument, NULL, 'h'},
|
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
|
||||||
{"format", required_argument, NULL, 'f'},
|
|
||||||
{"source-type", required_argument, NULL, 's'},
|
|
||||||
{"buffer-type", required_argument, NULL, 'b'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "hvf:s:b:",
|
|
||||||
long_options, &option_index)) != -1) {
|
|
||||||
const struct weston_enum_map *entry;
|
|
||||||
|
|
||||||
switch(c) {
|
|
||||||
case 'v':
|
|
||||||
app.verbose = true;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
app.requested_format = pixel_format_get_info_by_drm_name(optarg);
|
|
||||||
if (!app.requested_format) {
|
|
||||||
fprintf(stderr, "Unknown format %s\n", optarg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
entry = weston_enum_map_find_name(source_types,
|
|
||||||
optarg);
|
|
||||||
if (!entry)
|
|
||||||
print_usage_and_exit();
|
|
||||||
|
|
||||||
app.src_type = entry->value;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
entry = weston_enum_map_find_name(buffer_types,
|
|
||||||
optarg);
|
|
||||||
if (!entry)
|
|
||||||
print_usage_and_exit();
|
|
||||||
|
|
||||||
app.buffer_type = entry->value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print_usage_and_exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_init(&app.output_list);
|
|
||||||
|
|
||||||
app.display = wl_display_connect(NULL);
|
|
||||||
if (app.display == NULL) {
|
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.registry = wl_display_get_registry(app.display);
|
display = wl_display_connect(NULL);
|
||||||
wl_registry_add_listener(app.registry, ®istry_listener, &app);
|
if (display == NULL) {
|
||||||
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
/* Process wl_registry advertisements */
|
|
||||||
wl_display_roundtrip(app.display);
|
|
||||||
|
|
||||||
if (!app.capture_factory) {
|
|
||||||
fprintf(stderr, "Error: display does not support weston_capture_v1\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(app.buffer_type == CLIENT_BUFFER_TYPE_SHM && !app.shm) {
|
wl_list_init(&output_list);
|
||||||
fprintf(stderr, "Error: display does not support wl_shm\n");
|
registry = wl_display_get_registry(display);
|
||||||
return -1;
|
wl_registry_add_listener(registry, ®istry_listener, NULL);
|
||||||
}
|
wl_display_dispatch(display);
|
||||||
if (app.buffer_type == CLIENT_BUFFER_TYPE_DMABUF && !app.dmabuf) {
|
wl_display_roundtrip(display);
|
||||||
fprintf(stderr, "Error: Compositor does not support zwp_linux_dmabuf_v1\n");
|
if (screenshooter == NULL) {
|
||||||
|
fprintf(stderr, "display doesn't support screenshooter\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.verbose) {
|
screenshooter_add_listener(screenshooter, &screenshooter_listener, screenshooter);
|
||||||
printf("Taking screenshot with %s source %s buffer\n",
|
|
||||||
(app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER) ? "framebuffer" : "writeback",
|
if (set_buffer_size(&width, &height))
|
||||||
(app.buffer_type == CLIENT_BUFFER_TYPE_SHM) ? "shm" : "dma");
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
wl_list_for_each(output, &output_list, link) {
|
||||||
|
output->buffer = create_shm_buffer(output->width, output->height, &output->data);
|
||||||
|
screenshooter_shoot(screenshooter, output->output, output->buffer);
|
||||||
|
buffer_copy_done = 0;
|
||||||
|
while (!buffer_copy_done)
|
||||||
|
wl_display_roundtrip(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process initial events for wl_output and weston_capture_source_v1 */
|
write_png(width, height);
|
||||||
wl_display_roundtrip(app.display);
|
|
||||||
|
|
||||||
while (!received_formats_for_all_outputs(&app)) {
|
|
||||||
if (app.verbose)
|
|
||||||
printf("Waiting for compositor to send capture source data\n");
|
|
||||||
|
|
||||||
if (wl_display_dispatch(app.display) < 0) {
|
|
||||||
fprintf(stderr, "Error: connection terminated\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
app.retry = false;
|
|
||||||
|
|
||||||
wl_list_for_each(output, &app.output_list, link)
|
|
||||||
screenshooter_output_capture(output);
|
|
||||||
|
|
||||||
while (app.waitcount > 0 && !app.failed) {
|
|
||||||
if (wl_display_dispatch(app.display) < 0)
|
|
||||||
app.failed = true;
|
|
||||||
assert(app.waitcount >= 0);
|
|
||||||
}
|
|
||||||
} while (app.retry && !app.failed);
|
|
||||||
|
|
||||||
if (!app.failed) {
|
|
||||||
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (all_output_formats_are_yuv(&app.output_list))
|
|
||||||
screenshot_write_yuv(&buff_size, &app.output_list);
|
|
||||||
else
|
|
||||||
screenshot_write_png(&buff_size, &app.output_list);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error: screenshot or protocol failure\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_for_each_safe(output, tmp_output, &app.output_list, link)
|
|
||||||
destroy_output(output);
|
|
||||||
|
|
||||||
weston_capture_v1_destroy(app.capture_factory);
|
|
||||||
wl_shm_destroy(app.shm);
|
|
||||||
if (app.dmabuf)
|
|
||||||
zwp_linux_dmabuf_v1_destroy(app.dmabuf);
|
|
||||||
wl_registry_destroy(app.registry);
|
|
||||||
wl_display_disconnect(app.display);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,27 @@
|
||||||
* Copyright © 2011 Benjamin Franzke
|
* Copyright © 2011 Benjamin Franzke
|
||||||
* Copyright © 2010 Intel Corporation
|
* Copyright © 2010 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -35,13 +33,12 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "shared/os-compatibility.h"
|
#include "../shared/os-compatibility.h"
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
#include "xdg-shell-client-protocol.h"
|
||||||
#include "viewporter-client-protocol.h"
|
#include "fullscreen-shell-client-protocol.h"
|
||||||
|
#include "scaler-client-protocol.h"
|
||||||
|
|
||||||
int print_debug = 0;
|
int print_debug = 0;
|
||||||
|
|
||||||
|
|
@ -50,8 +47,9 @@ struct display {
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
int compositor_version;
|
int compositor_version;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct wp_viewporter *viewporter;
|
struct wl_scaler *scaler;
|
||||||
struct xdg_wm_base *wm_base;
|
struct xdg_shell *shell;
|
||||||
|
struct _wl_fullscreen_shell *fshell;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
uint32_t formats;
|
uint32_t formats;
|
||||||
};
|
};
|
||||||
|
|
@ -65,20 +63,17 @@ struct buffer {
|
||||||
enum window_flags {
|
enum window_flags {
|
||||||
WINDOW_FLAG_USE_VIEWPORT = 0x1,
|
WINDOW_FLAG_USE_VIEWPORT = 0x1,
|
||||||
WINDOW_FLAG_ROTATING_TRANSFORM = 0x2,
|
WINDOW_FLAG_ROTATING_TRANSFORM = 0x2,
|
||||||
WINDOW_FLAG_USE_DAMAGE_BUFFER = 0x4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct window {
|
struct window {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
int width, height, border;
|
int width, height, border;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct wp_viewport *viewport;
|
struct wl_viewport *viewport;
|
||||||
struct xdg_surface *xdg_surface;
|
struct xdg_surface *xdg_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
|
||||||
struct wl_callback *callback;
|
struct wl_callback *callback;
|
||||||
struct buffer buffers[2];
|
struct buffer buffers[2];
|
||||||
struct buffer *prev_buffer;
|
struct buffer *prev_buffer;
|
||||||
bool wait_for_configure;
|
|
||||||
|
|
||||||
enum window_flags flags;
|
enum window_flags flags;
|
||||||
int scale;
|
int scale;
|
||||||
|
|
@ -94,9 +89,6 @@ struct window {
|
||||||
|
|
||||||
static int running = 1;
|
static int running = 1;
|
||||||
|
|
||||||
static void
|
|
||||||
redraw(void *data, struct wl_callback *callback, uint32_t time);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
buffer_release(void *data, struct wl_buffer *buffer)
|
buffer_release(void *data, struct wl_buffer *buffer)
|
||||||
{
|
{
|
||||||
|
|
@ -122,14 +114,14 @@ create_shm_buffer(struct display *display, struct buffer *buffer,
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
fd = os_create_anonymous_file(size);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
size, strerror(errno));
|
size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (data == MAP_FAILED) {
|
if (data == MAP_FAILED) {
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
fprintf(stderr, "mmap failed: %m\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -148,39 +140,21 @@ create_shm_buffer(struct display *display, struct buffer *buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_surface_handle_configure(void *data, struct xdg_surface *surface,
|
handle_configure(void *data, struct xdg_surface *surface,
|
||||||
uint32_t serial)
|
int32_t width, int32_t height, struct wl_array *states,
|
||||||
{
|
uint32_t serial)
|
||||||
struct window *window = data;
|
|
||||||
|
|
||||||
xdg_surface_ack_configure(surface, serial);
|
|
||||||
|
|
||||||
if (window->wait_for_configure) {
|
|
||||||
redraw(window, NULL, 0);
|
|
||||||
window->wait_for_configure = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
|
||||||
xdg_surface_handle_configure,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *toplevel,
|
|
||||||
int32_t width, int32_t height,
|
|
||||||
struct wl_array *states)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
handle_close(void *data, struct xdg_surface *xdg_surface)
|
||||||
{
|
{
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||||
xdg_toplevel_handle_configure,
|
handle_configure,
|
||||||
xdg_toplevel_handle_close,
|
handle_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
static float
|
static float
|
||||||
|
|
@ -281,21 +255,12 @@ create_window(struct display *display, int width, int height,
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display->viewporter == NULL && (flags & WINDOW_FLAG_USE_VIEWPORT)) {
|
if (display->scaler == NULL && (flags & WINDOW_FLAG_USE_VIEWPORT)) {
|
||||||
fprintf(stderr, "Compositor does not support wp_viewport");
|
fprintf(stderr, "Compositor does not support wl_viewport");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display->compositor_version <
|
window = calloc(1, sizeof *window);
|
||||||
WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION &&
|
|
||||||
(flags & WINDOW_FLAG_USE_DAMAGE_BUFFER)) {
|
|
||||||
fprintf(stderr, "wl_surface.damage_buffer unsupported in "
|
|
||||||
"wl_surface version %d\n",
|
|
||||||
display->compositor_version);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
window = zalloc(sizeof *window);
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
@ -313,44 +278,32 @@ create_window(struct display *display, int width, int height,
|
||||||
window->surface = wl_compositor_create_surface(display->compositor);
|
window->surface = wl_compositor_create_surface(display->compositor);
|
||||||
|
|
||||||
if (window->flags & WINDOW_FLAG_USE_VIEWPORT)
|
if (window->flags & WINDOW_FLAG_USE_VIEWPORT)
|
||||||
window->viewport = wp_viewporter_get_viewport(display->viewporter,
|
window->viewport = wl_scaler_get_viewport(display->scaler,
|
||||||
window->surface);
|
window->surface);
|
||||||
|
|
||||||
if (display->wm_base) {
|
if (display->shell) {
|
||||||
window->xdg_surface =
|
window->xdg_surface =
|
||||||
xdg_wm_base_get_xdg_surface(display->wm_base,
|
xdg_shell_get_xdg_surface(display->shell,
|
||||||
window->surface);
|
window->surface);
|
||||||
|
|
||||||
assert(window->xdg_surface);
|
assert(window->xdg_surface);
|
||||||
|
|
||||||
xdg_surface_add_listener(window->xdg_surface,
|
xdg_surface_add_listener(window->xdg_surface,
|
||||||
&xdg_surface_listener, window);
|
&xdg_surface_listener, window);
|
||||||
|
|
||||||
window->xdg_toplevel =
|
xdg_surface_set_title(window->xdg_surface, "simple-damage");
|
||||||
xdg_surface_get_toplevel(window->xdg_surface);
|
} else if (display->fshell) {
|
||||||
|
_wl_fullscreen_shell_present_surface(display->fshell,
|
||||||
assert(window->xdg_toplevel);
|
window->surface,
|
||||||
|
_WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT,
|
||||||
xdg_toplevel_add_listener(window->xdg_toplevel,
|
NULL);
|
||||||
&xdg_toplevel_listener, window);
|
|
||||||
|
|
||||||
xdg_toplevel_set_title(window->xdg_toplevel, "simple-damage");
|
|
||||||
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
|
||||||
"org.freedesktop.weston.simple-damage");
|
|
||||||
|
|
||||||
window->wait_for_configure = true;
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
} else {
|
} else {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise damage to full surface, so the padding gets painted */
|
/* Initialise damage to full surface, so the padding gets painted */
|
||||||
if (window->flags & WINDOW_FLAG_USE_DAMAGE_BUFFER) {
|
wl_surface_damage(window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
wl_surface_damage_buffer(window->surface, 0, 0,
|
|
||||||
INT32_MAX, INT32_MAX);
|
|
||||||
} else {
|
|
||||||
wl_surface_damage(window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
|
||||||
}
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,12 +318,10 @@ destroy_window(struct window *window)
|
||||||
if (window->buffers[1].buffer)
|
if (window->buffers[1].buffer)
|
||||||
wl_buffer_destroy(window->buffers[1].buffer);
|
wl_buffer_destroy(window->buffers[1].buffer);
|
||||||
|
|
||||||
if (window->xdg_toplevel)
|
|
||||||
xdg_toplevel_destroy(window->xdg_toplevel);
|
|
||||||
if (window->xdg_surface)
|
if (window->xdg_surface)
|
||||||
xdg_surface_destroy(window->xdg_surface);
|
xdg_surface_destroy(window->xdg_surface);
|
||||||
if (window->viewport)
|
if (window->viewport)
|
||||||
wp_viewport_destroy(window->viewport);
|
wl_viewport_destroy(window->viewport);
|
||||||
wl_surface_destroy(window->surface);
|
wl_surface_destroy(window->surface);
|
||||||
free(window);
|
free(window);
|
||||||
}
|
}
|
||||||
|
|
@ -456,32 +407,32 @@ window_get_transformed_ball(struct window *window, float *bx, float *by)
|
||||||
*by = wy;
|
*by = wy;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_90:
|
case WL_OUTPUT_TRANSFORM_90:
|
||||||
*bx = wy;
|
*bx = window->height - wy;
|
||||||
*by = window->width - wx;
|
*by = wx;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_180:
|
case WL_OUTPUT_TRANSFORM_180:
|
||||||
*bx = window->width - wx;
|
*bx = window->width - wx;
|
||||||
*by = window->height - wy;
|
*by = window->height - wy;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_270:
|
case WL_OUTPUT_TRANSFORM_270:
|
||||||
*bx = window->height - wy;
|
*bx = wy;
|
||||||
*by = wx;
|
*by = window->width - wx;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||||
*bx = window->width - wx;
|
*bx = window->width - wx;
|
||||||
*by = wy;
|
*by = wy;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||||
*bx = wy;
|
*bx = window->height - wy;
|
||||||
*by = wx;
|
*by = window->width - wx;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||||
*bx = wx;
|
*bx = wx;
|
||||||
*by = window->height - wy;
|
*by = window->height - wy;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||||
*bx = window->height - wy;
|
*bx = wy;
|
||||||
*by = window->width - wx;
|
*by = wx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -497,27 +448,13 @@ window_get_transformed_ball(struct window *window, float *bx, float *by)
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener;
|
static const struct wl_callback_listener frame_listener;
|
||||||
|
|
||||||
static void
|
|
||||||
set_opaque_region(struct window *window)
|
|
||||||
{
|
|
||||||
struct wl_region *region;
|
|
||||||
|
|
||||||
region = wl_compositor_create_region(window->display->compositor);
|
|
||||||
wl_region_add(region, 0, 0, window->width, window->height);
|
|
||||||
wl_region_subtract(region, window->border, window->border,
|
|
||||||
window->width - 2 * window->border,
|
|
||||||
window->height - 2 * window->border);
|
|
||||||
wl_surface_set_opaque_region(window->surface, region);
|
|
||||||
wl_region_destroy(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
redraw(void *data, struct wl_callback *callback, uint32_t time)
|
redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct window *window = data;
|
||||||
struct buffer *buffer;
|
struct buffer *buffer;
|
||||||
int off_x = 0, off_y = 0;
|
int off_x, off_y, bwidth, bheight, bborder, bpitch, bradius;
|
||||||
int bwidth, bheight, bborder, bpitch, bradius;
|
uint32_t *buffer_data;
|
||||||
float bx, by;
|
float bx, by;
|
||||||
|
|
||||||
buffer = window_next_buffer(window);
|
buffer = window_next_buffer(window);
|
||||||
|
|
@ -556,8 +493,8 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
bborder = window->border * window->scale;
|
bborder = window->border * window->scale;
|
||||||
bradius = window->ball.radius * window->scale;
|
bradius = window->ball.radius * window->scale;
|
||||||
|
|
||||||
|
buffer_data = buffer->shm_data;
|
||||||
if (window->viewport) {
|
if (window->viewport) {
|
||||||
int tx, ty;
|
|
||||||
/* Fill the whole thing with red to detect viewport errors */
|
/* Fill the whole thing with red to detect viewport errors */
|
||||||
paint_box(buffer->shm_data, bpitch, 0, 0, bwidth, bheight,
|
paint_box(buffer->shm_data, bpitch, 0, 0, bwidth, bheight,
|
||||||
0xffff0000);
|
0xffff0000);
|
||||||
|
|
@ -570,44 +507,38 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
bheight /= 2;
|
bheight /= 2;
|
||||||
|
|
||||||
/* Offset the drawing region */
|
/* Offset the drawing region */
|
||||||
tx = (window->width / 3) * window->scale;
|
off_x = (window->width / 3) * window->scale;
|
||||||
ty = (window->height / 5) * window->scale;
|
off_y = (window->height / 5) * window->scale;
|
||||||
switch (window->transform) {
|
switch (window->transform) {
|
||||||
default:
|
default:
|
||||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||||
off_y = ty;
|
buffer_data += off_y * bpitch + off_x;
|
||||||
off_x = tx;
|
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_90:
|
case WL_OUTPUT_TRANSFORM_90:
|
||||||
off_y = bheight - tx;
|
buffer_data += off_x * bpitch + (bwidth - off_y);
|
||||||
off_x = ty;
|
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_180:
|
case WL_OUTPUT_TRANSFORM_180:
|
||||||
off_y = bheight - ty;
|
buffer_data += (bheight - off_y) * bpitch +
|
||||||
off_x = bwidth - tx;
|
(bwidth - off_x);
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_270:
|
case WL_OUTPUT_TRANSFORM_270:
|
||||||
off_y = tx;
|
buffer_data += (bheight - off_x) * bpitch + off_y;
|
||||||
off_x = bwidth - ty;
|
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||||
off_y = ty;
|
buffer_data += off_y * bpitch + (bwidth - off_x);
|
||||||
off_x = bwidth - tx;
|
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||||
off_y = tx;
|
buffer_data += (bheight - off_x) * bpitch +
|
||||||
off_x = ty;
|
(bwidth - off_y);
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||||
off_y = bheight - ty;
|
buffer_data += (bheight - off_y) * bpitch + off_x;
|
||||||
off_x = tx;
|
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||||
off_y = bheight - tx;
|
buffer_data += off_x * bpitch + off_y;
|
||||||
off_x = bwidth - ty;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wp_viewport_set_source(window->viewport,
|
wl_viewport_set_source(window->viewport,
|
||||||
wl_fixed_from_int(window->width / 3),
|
wl_fixed_from_int(window->width / 3),
|
||||||
wl_fixed_from_int(window->height / 5),
|
wl_fixed_from_int(window->height / 5),
|
||||||
wl_fixed_from_int(window->width / 2),
|
wl_fixed_from_int(window->width / 2),
|
||||||
|
|
@ -615,41 +546,30 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Paint the border */
|
/* Paint the border */
|
||||||
paint_box(buffer->shm_data, bpitch, off_x, off_y,
|
paint_box(buffer_data, bpitch, 0, 0, bwidth, bborder, 0xffffffff);
|
||||||
bwidth, bborder, 0xffffffff);
|
paint_box(buffer_data, bpitch, 0, 0, bborder, bheight, 0xffffffff);
|
||||||
paint_box(buffer->shm_data, bpitch, off_x, off_y,
|
paint_box(buffer_data, bpitch,
|
||||||
bborder, bheight, 0xffffffff);
|
bwidth - bborder, 0, bborder, bheight, 0xffffffff);
|
||||||
paint_box(buffer->shm_data, bpitch, off_x + bwidth - bborder, off_y,
|
paint_box(buffer_data, bpitch,
|
||||||
bborder, bheight, 0xffffffff);
|
0, bheight - bborder, bwidth, bborder, 0xffffffff);
|
||||||
paint_box(buffer->shm_data, bpitch, off_x, off_y + bheight - bborder,
|
|
||||||
bwidth, bborder, 0xffffffff);
|
|
||||||
|
|
||||||
/* fill with translucent */
|
/* fill with translucent */
|
||||||
paint_box(buffer->shm_data, bpitch, off_x + bborder, off_y + bborder,
|
paint_box(buffer_data, bpitch, bborder, bborder,
|
||||||
bwidth - 2 * bborder, bheight - 2 * bborder, 0x80000000);
|
bwidth - 2 * bborder, bheight - 2 * bborder, 0x80000000);
|
||||||
|
|
||||||
/* Damage where the ball was */
|
/* Damage where the ball was */
|
||||||
if (window->flags & WINDOW_FLAG_USE_DAMAGE_BUFFER) {
|
wl_surface_damage(window->surface,
|
||||||
window_get_transformed_ball(window, &bx, &by);
|
window->ball.x - window->ball.radius,
|
||||||
wl_surface_damage_buffer(window->surface,
|
window->ball.y - window->ball.radius,
|
||||||
bx - bradius + off_x,
|
window->ball.radius * 2 + 1,
|
||||||
by - bradius + off_y,
|
window->ball.radius * 2 + 1);
|
||||||
bradius * 2 + 1,
|
|
||||||
bradius * 2 + 1);
|
|
||||||
} else {
|
|
||||||
wl_surface_damage(window->surface,
|
|
||||||
window->ball.x - window->ball.radius,
|
|
||||||
window->ball.y - window->ball.radius,
|
|
||||||
window->ball.radius * 2 + 1,
|
|
||||||
window->ball.radius * 2 + 1);
|
|
||||||
}
|
|
||||||
window_advance_game(window, time);
|
window_advance_game(window, time);
|
||||||
|
|
||||||
window_get_transformed_ball(window, &bx, &by);
|
window_get_transformed_ball(window, &bx, &by);
|
||||||
|
|
||||||
/* Paint the ball */
|
/* Paint the ball */
|
||||||
paint_circle(buffer->shm_data, bpitch, off_x + bx, off_y + by,
|
paint_circle(buffer_data, bpitch, bx, by, bradius, 0xff00ff00);
|
||||||
bradius, 0xff00ff00);
|
|
||||||
|
|
||||||
if (print_debug) {
|
if (print_debug) {
|
||||||
printf("Ball now located at (%f, %f)\n",
|
printf("Ball now located at (%f, %f)\n",
|
||||||
|
|
@ -659,25 +579,17 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
bradius);
|
bradius);
|
||||||
|
|
||||||
printf("Buffer damage rectangle: (%d, %d) @ %dx%d\n",
|
printf("Buffer damage rectangle: (%d, %d) @ %dx%d\n",
|
||||||
(int)(bx - bradius) + off_x,
|
(int)(bx - bradius), (int)(by - bradius),
|
||||||
(int)(by - bradius) + off_y,
|
|
||||||
bradius * 2 + 1, bradius * 2 + 1);
|
bradius * 2 + 1, bradius * 2 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Damage where the ball is now */
|
/* Damage where the ball is now */
|
||||||
if (window->flags & WINDOW_FLAG_USE_DAMAGE_BUFFER) {
|
wl_surface_damage(window->surface,
|
||||||
wl_surface_damage_buffer(window->surface,
|
window->ball.x - window->ball.radius,
|
||||||
bx - bradius + off_x,
|
window->ball.y - window->ball.radius,
|
||||||
by - bradius + off_y,
|
window->ball.radius * 2 + 1,
|
||||||
bradius * 2 + 1,
|
window->ball.radius * 2 + 1);
|
||||||
bradius * 2 + 1);
|
|
||||||
} else {
|
|
||||||
wl_surface_damage(window->surface,
|
|
||||||
window->ball.x - window->ball.radius,
|
|
||||||
window->ball.y - window->ball.radius,
|
|
||||||
window->ball.radius * 2 + 1,
|
|
||||||
window->ball.radius * 2 + 1);
|
|
||||||
}
|
|
||||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
|
|
||||||
if (window->display->compositor_version >= 2 &&
|
if (window->display->compositor_version >= 2 &&
|
||||||
|
|
@ -687,7 +599,7 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
window->transform);
|
window->transform);
|
||||||
|
|
||||||
if (window->viewport)
|
if (window->viewport)
|
||||||
wp_viewport_set_destination(window->viewport,
|
wl_viewport_set_destination(window->viewport,
|
||||||
window->width,
|
window->width,
|
||||||
window->height);
|
window->height);
|
||||||
|
|
||||||
|
|
@ -698,8 +610,6 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
if (callback)
|
if (callback)
|
||||||
wl_callback_destroy(callback);
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
set_opaque_region(window);
|
|
||||||
|
|
||||||
window->callback = wl_surface_frame(window->surface);
|
window->callback = wl_surface_frame(window->surface);
|
||||||
wl_callback_add_listener(window->callback, &frame_listener, window);
|
wl_callback_add_listener(window->callback, &frame_listener, window);
|
||||||
wl_surface_commit(window->surface);
|
wl_surface_commit(window->surface);
|
||||||
|
|
@ -723,15 +633,21 @@ struct wl_shm_listener shm_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial)
|
||||||
{
|
{
|
||||||
xdg_wm_base_pong(shell, serial);
|
xdg_shell_pong(shell, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_wm_base_listener wm_base_listener = {
|
static const struct xdg_shell_listener xdg_shell_listener = {
|
||||||
xdg_wm_base_ping,
|
xdg_shell_ping,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define XDG_VERSION 5 /* The version of xdg-shell that we implement */
|
||||||
|
#ifdef static_assert
|
||||||
|
static_assert(XDG_VERSION == XDG_SHELL_VERSION_CURRENT,
|
||||||
|
"Interface version doesn't match implementation version");
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
registry_handle_global(void *data, struct wl_registry *registry,
|
registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
uint32_t id, const char *interface, uint32_t version)
|
uint32_t id, const char *interface, uint32_t version)
|
||||||
|
|
@ -752,13 +668,17 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
wl_registry_bind(registry,
|
wl_registry_bind(registry,
|
||||||
id, &wl_compositor_interface,
|
id, &wl_compositor_interface,
|
||||||
d->compositor_version);
|
d->compositor_version);
|
||||||
} else if (strcmp(interface, "wp_viewporter") == 0) {
|
} else if (strcmp(interface, "wl_scaler") == 0 && version >= 2) {
|
||||||
d->viewporter = wl_registry_bind(registry, id,
|
d->scaler = wl_registry_bind(registry,
|
||||||
&wp_viewporter_interface, 1);
|
id, &wl_scaler_interface, 2);
|
||||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
} else if (strcmp(interface, "xdg_shell") == 0) {
|
||||||
d->wm_base = wl_registry_bind(registry,
|
d->shell = wl_registry_bind(registry,
|
||||||
id, &xdg_wm_base_interface, 1);
|
id, &xdg_shell_interface, 1);
|
||||||
xdg_wm_base_add_listener(d->wm_base, &wm_base_listener, d);
|
xdg_shell_use_unstable_version(d->shell, XDG_VERSION);
|
||||||
|
xdg_shell_add_listener(d->shell, &xdg_shell_listener, d);
|
||||||
|
} else if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
|
||||||
|
d->fshell = wl_registry_bind(registry,
|
||||||
|
id, &_wl_fullscreen_shell_interface, 1);
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
d->shm = wl_registry_bind(registry,
|
d->shm = wl_registry_bind(registry,
|
||||||
id, &wl_shm_interface, 1);
|
id, &wl_shm_interface, 1);
|
||||||
|
|
@ -782,7 +702,7 @@ create_display(int version)
|
||||||
{
|
{
|
||||||
struct display *display;
|
struct display *display;
|
||||||
|
|
||||||
display = zalloc(sizeof *display);
|
display = malloc(sizeof *display);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
fprintf(stderr, "out of memory\n");
|
fprintf(stderr, "out of memory\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -817,11 +737,14 @@ destroy_display(struct display *display)
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
if (display->wm_base)
|
if (display->shell)
|
||||||
xdg_wm_base_destroy(display->wm_base);
|
xdg_shell_destroy(display->shell);
|
||||||
|
|
||||||
if (display->viewporter)
|
if (display->fshell)
|
||||||
wp_viewporter_destroy(display->viewporter);
|
_wl_fullscreen_shell_release(display->fshell);
|
||||||
|
|
||||||
|
if (display->scaler)
|
||||||
|
wl_scaler_destroy(display->scaler);
|
||||||
|
|
||||||
if (display->compositor)
|
if (display->compositor)
|
||||||
wl_compositor_destroy(display->compositor);
|
wl_compositor_destroy(display->compositor);
|
||||||
|
|
@ -852,8 +775,7 @@ print_usage(int retval)
|
||||||
" --scale=SCALE\t\tScale factor for the surface\n"
|
" --scale=SCALE\t\tScale factor for the surface\n"
|
||||||
" --transform=TRANSFORM\tTransform for the surface\n"
|
" --transform=TRANSFORM\tTransform for the surface\n"
|
||||||
" --rotating-transform\tUse a different buffer_transform for each frame\n"
|
" --rotating-transform\tUse a different buffer_transform for each frame\n"
|
||||||
" --use-viewport\tUse wp_viewport\n"
|
" --use-viewport\tUse wl_viewport\n"
|
||||||
" --use-damage-buffer\tUse damage_buffer to post damage\n"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
exit(retval);
|
exit(retval);
|
||||||
|
|
@ -904,7 +826,7 @@ main(int argc, char **argv)
|
||||||
strcmp(argv[i], "-h") == 0) {
|
strcmp(argv[i], "-h") == 0) {
|
||||||
print_usage(0);
|
print_usage(0);
|
||||||
} else if (sscanf(argv[i], "--version=%d", &version) > 0) {
|
} else if (sscanf(argv[i], "--version=%d", &version) > 0) {
|
||||||
if (version < 1 || version > 4) {
|
if (version < 1 || version > 3) {
|
||||||
fprintf(stderr, "Unsupported wl_surface version: %d\n",
|
fprintf(stderr, "Unsupported wl_surface version: %d\n",
|
||||||
version);
|
version);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -928,9 +850,6 @@ main(int argc, char **argv)
|
||||||
} else if (strcmp(argv[i], "--use-viewport") == 0) {
|
} else if (strcmp(argv[i], "--use-viewport") == 0) {
|
||||||
flags |= WINDOW_FLAG_USE_VIEWPORT;
|
flags |= WINDOW_FLAG_USE_VIEWPORT;
|
||||||
continue;
|
continue;
|
||||||
} else if (strcmp(argv[i], "--use-damage-buffer") == 0) {
|
|
||||||
flags |= WINDOW_FLAG_USE_DAMAGE_BUFFER;
|
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
printf("Invalid option: %s\n", argv[i]);
|
printf("Invalid option: %s\n", argv[i]);
|
||||||
print_usage(255);
|
print_usage(255);
|
||||||
|
|
@ -948,13 +867,12 @@ main(int argc, char **argv)
|
||||||
sigint.sa_flags = SA_RESETHAND;
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
sigaction(SIGINT, &sigint, NULL);
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
if (!window->wait_for_configure)
|
redraw(window, NULL, 0);
|
||||||
redraw(window, NULL, 0);
|
|
||||||
|
|
||||||
while (running && ret != -1)
|
while (running && ret != -1)
|
||||||
ret = wl_display_dispatch(display->display);
|
ret = wl_display_dispatch(display->display);
|
||||||
|
|
||||||
fprintf(stderr, "simple-damage exiting\n");
|
fprintf(stderr, "simple-shm exiting\n");
|
||||||
destroy_window(window);
|
destroy_window(window);
|
||||||
destroy_display(display);
|
destroy_display(display);
|
||||||
|
|
||||||
|
|
|
||||||
1166
clients/simple-egl.c
|
|
@ -2,29 +2,27 @@
|
||||||
* Copyright © 2011 Benjamin Franzke
|
* Copyright © 2011 Benjamin Franzke
|
||||||
* Copyright © 2010 Intel Corporation
|
* Copyright © 2010 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -33,189 +31,46 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "shared/os-compatibility.h"
|
#include "../shared/os-compatibility.h"
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
#include "xdg-shell-client-protocol.h"
|
||||||
|
#include "fullscreen-shell-client-protocol.h"
|
||||||
|
|
||||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
#include <sys/types.h>
|
||||||
#define FMT(fmt, bpp, r, g, b, a) { WL_SHM_FORMAT_ ## fmt, #fmt, bpp, { r, g, b, a } }
|
#include "ivi-application-client-protocol.h"
|
||||||
|
#define IVI_SURFACE_ID 9000
|
||||||
#define MAX_BUFFER_ALLOC 2
|
|
||||||
|
|
||||||
struct window;
|
|
||||||
|
|
||||||
struct format {
|
|
||||||
uint32_t code;
|
|
||||||
const char *string;
|
|
||||||
int bpp;
|
|
||||||
uint64_t color[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct display {
|
struct display {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct xdg_wm_base *wm_base;
|
struct xdg_shell *shell;
|
||||||
struct wl_seat *seat;
|
struct _wl_fullscreen_shell *fshell;
|
||||||
struct wl_keyboard *keyboard;
|
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
const struct format *format;
|
uint32_t formats;
|
||||||
bool paint_format;
|
struct ivi_application *ivi_application;
|
||||||
bool has_format;
|
|
||||||
struct window *window;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
struct window *window;
|
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
void *shm_data;
|
void *shm_data;
|
||||||
int busy;
|
int busy;
|
||||||
int width, height;
|
|
||||||
size_t size; /* width * 4 * height */
|
|
||||||
struct wl_list buffer_link; /** window::buffer_list */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct window {
|
struct window {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
int width, height;
|
int width, height;
|
||||||
int init_width, init_height;
|
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct xdg_surface *xdg_surface;
|
struct xdg_surface *xdg_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct ivi_surface *ivi_surface;
|
||||||
struct wl_list buffer_list;
|
struct buffer buffers[2];
|
||||||
struct buffer *prev_buffer;
|
struct buffer *prev_buffer;
|
||||||
struct wl_callback *callback;
|
struct wl_callback *callback;
|
||||||
bool wait_for_configure;
|
|
||||||
bool maximized;
|
|
||||||
bool fullscreen;
|
|
||||||
bool needs_update_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct format shm_formats[] = {
|
|
||||||
/* 8 bpp formats */
|
|
||||||
FMT(R8, 8, 0x00, 0x55, 0xaa, 0xff ),
|
|
||||||
|
|
||||||
/* 16 bpp formats */
|
|
||||||
FMT(R16, 16, 0x0000, 0x5555, 0xaaaa, 0xffff ),
|
|
||||||
FMT(GR88, 16, 0x00ff, 0xff00, 0x0000, 0xffff ),
|
|
||||||
FMT(RG88, 16, 0xff00, 0x00ff, 0x0000, 0xffff ),
|
|
||||||
FMT(RGB565, 16, 0xf800, 0x07e0, 0x001f, 0xffff ),
|
|
||||||
FMT(BGR565, 16, 0x001f, 0x07e0, 0xf800, 0xffff ),
|
|
||||||
FMT(XRGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
|
|
||||||
FMT(ARGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
|
|
||||||
FMT(XBGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
|
|
||||||
FMT(ABGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
|
|
||||||
FMT(RGBX4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
|
|
||||||
FMT(RGBA4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
|
|
||||||
FMT(BGRX4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
|
|
||||||
FMT(BGRA4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
|
|
||||||
FMT(XRGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
|
|
||||||
FMT(ARGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
|
|
||||||
FMT(XBGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
|
|
||||||
FMT(ABGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
|
|
||||||
FMT(RGBX5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
|
|
||||||
FMT(RGBA5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
|
|
||||||
FMT(BGRX5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
|
|
||||||
FMT(BGRA5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
|
|
||||||
|
|
||||||
/* 24 bpp formats */
|
|
||||||
FMT(RGB888, 24, 0xff0000, 0x00ff00, 0x0000ff, 0xffffff ),
|
|
||||||
FMT(BGR888, 24, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff ),
|
|
||||||
|
|
||||||
/* 32 bpp formats */
|
|
||||||
FMT(GR1616, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff ),
|
|
||||||
FMT(RG1616, 32, 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff ),
|
|
||||||
FMT(XRGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
|
|
||||||
FMT(ARGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
|
|
||||||
FMT(XBGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
|
|
||||||
FMT(ABGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
|
|
||||||
FMT(RGBX8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
|
|
||||||
FMT(RGBA8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
|
|
||||||
FMT(BGRX8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
|
|
||||||
FMT(BGRA8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
|
|
||||||
FMT(XRGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
|
|
||||||
FMT(ARGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
|
|
||||||
FMT(XBGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
|
|
||||||
FMT(ABGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
|
|
||||||
FMT(RGBX1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
|
|
||||||
FMT(RGBA1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
|
|
||||||
FMT(BGRX1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
|
|
||||||
FMT(BGRA1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
|
|
||||||
|
|
||||||
/* 64 bpp formats */
|
|
||||||
FMT(XRGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
|
|
||||||
FMT(ARGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
|
|
||||||
FMT(XBGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
|
|
||||||
FMT(ABGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
|
|
||||||
FMT(XRGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
|
|
||||||
FMT(ARGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
|
|
||||||
FMT(XBGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
|
|
||||||
FMT(ABGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int running = 1;
|
static int running = 1;
|
||||||
|
|
||||||
static void
|
|
||||||
redraw(void *data, struct wl_callback *callback, uint32_t time);
|
|
||||||
|
|
||||||
static struct buffer *
|
|
||||||
alloc_buffer(struct window *window, int width, int height)
|
|
||||||
{
|
|
||||||
struct buffer *buffer = calloc(1, sizeof(*buffer));
|
|
||||||
|
|
||||||
buffer->width = width;
|
|
||||||
buffer->height = height;
|
|
||||||
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_buffer(struct buffer *buffer)
|
|
||||||
{
|
|
||||||
if (buffer->buffer)
|
|
||||||
wl_buffer_destroy(buffer->buffer);
|
|
||||||
|
|
||||||
munmap(buffer->shm_data, buffer->size);
|
|
||||||
wl_list_remove(&buffer->buffer_link);
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct buffer *
|
|
||||||
pick_free_buffer(struct window *window)
|
|
||||||
{
|
|
||||||
struct buffer *b;
|
|
||||||
struct buffer *buffer = NULL;
|
|
||||||
|
|
||||||
wl_list_for_each(b, &window->buffer_list, buffer_link) {
|
|
||||||
if (!b->busy) {
|
|
||||||
buffer = b;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prune_old_released_buffers(struct window *window)
|
|
||||||
{
|
|
||||||
struct buffer *b, *b_next;
|
|
||||||
|
|
||||||
wl_list_for_each_safe(b, b_next,
|
|
||||||
&window->buffer_list, buffer_link) {
|
|
||||||
if (!b->busy && (b->width != window->width ||
|
|
||||||
b->height != window->height))
|
|
||||||
destroy_buffer(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
buffer_release(void *data, struct wl_buffer *buffer)
|
buffer_release(void *data, struct wl_buffer *buffer)
|
||||||
{
|
{
|
||||||
|
|
@ -229,31 +84,26 @@ static const struct wl_buffer_listener buffer_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_shm_buffer(struct window *window, struct buffer *buffer,
|
create_shm_buffer(struct display *display, struct buffer *buffer,
|
||||||
const struct format *format)
|
int width, int height, uint32_t format)
|
||||||
{
|
{
|
||||||
struct wl_shm_pool *pool;
|
struct wl_shm_pool *pool;
|
||||||
int fd, size, stride;
|
int fd, size, stride;
|
||||||
void *data;
|
void *data;
|
||||||
int width, height;
|
|
||||||
struct display *display;
|
|
||||||
|
|
||||||
width = window->width;
|
stride = width * 4;
|
||||||
height = window->height;
|
|
||||||
stride = width * (format->bpp / 8);
|
|
||||||
size = stride * height;
|
size = stride * height;
|
||||||
display = window->display;
|
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
fd = os_create_anonymous_file(size);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
size, strerror(errno));
|
size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (data == MAP_FAILED) {
|
if (data == MAP_FAILED) {
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
fprintf(stderr, "mmap failed: %m\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -261,164 +111,52 @@ create_shm_buffer(struct window *window, struct buffer *buffer,
|
||||||
pool = wl_shm_create_pool(display->shm, fd, size);
|
pool = wl_shm_create_pool(display->shm, fd, size);
|
||||||
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
||||||
width, height,
|
width, height,
|
||||||
stride, format->code);
|
stride, format);
|
||||||
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
||||||
wl_shm_pool_destroy(pool);
|
wl_shm_pool_destroy(pool);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
buffer->size = size;
|
|
||||||
buffer->shm_data = data;
|
buffer->shm_data = data;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
handle_configure(void *data, struct xdg_surface *surface,
|
||||||
uint32_t format, int fd, uint32_t size)
|
int32_t width, int32_t height,
|
||||||
|
struct wl_array *states, uint32_t serial)
|
||||||
{
|
{
|
||||||
/* Just so we don’t leak the keymap fd */
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, struct wl_surface *surface,
|
|
||||||
struct wl_array *keys)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, struct wl_surface *surface)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, uint32_t time, uint32_t key,
|
|
||||||
uint32_t state)
|
|
||||||
{
|
|
||||||
struct display *d = data;
|
|
||||||
|
|
||||||
if (key == KEY_F11 && state) {
|
|
||||||
if (d->window->fullscreen)
|
|
||||||
xdg_toplevel_unset_fullscreen(d->window->xdg_toplevel);
|
|
||||||
else
|
|
||||||
xdg_toplevel_set_fullscreen(d->window->xdg_toplevel, NULL);
|
|
||||||
} else if (key == KEY_ESC && state) {
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, uint32_t mods_depressed,
|
|
||||||
uint32_t mods_latched, uint32_t mods_locked,
|
|
||||||
uint32_t group)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_keyboard_listener keyboard_listener = {
|
|
||||||
keyboard_handle_keymap,
|
|
||||||
keyboard_handle_enter,
|
|
||||||
keyboard_handle_leave,
|
|
||||||
keyboard_handle_key,
|
|
||||||
keyboard_handle_modifiers,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|
||||||
enum wl_seat_capability caps)
|
|
||||||
{
|
|
||||||
struct display *d = data;
|
|
||||||
|
|
||||||
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
|
|
||||||
d->keyboard = wl_seat_get_keyboard(seat);
|
|
||||||
wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
|
|
||||||
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
|
|
||||||
wl_keyboard_destroy(d->keyboard);
|
|
||||||
d->keyboard = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_seat_listener seat_listener = {
|
|
||||||
seat_handle_capabilities,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
|
|
||||||
uint32_t serial)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
|
|
||||||
xdg_surface_ack_configure(surface, serial);
|
xdg_surface_ack_configure(surface, serial);
|
||||||
|
|
||||||
if (window->wait_for_configure) {
|
|
||||||
redraw(window, NULL, 0);
|
|
||||||
window->wait_for_configure = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
|
||||||
handle_xdg_surface_configure,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|
||||||
int32_t width, int32_t height,
|
|
||||||
struct wl_array *states)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
uint32_t *p;
|
|
||||||
|
|
||||||
window->fullscreen = false;
|
|
||||||
window->maximized = false;
|
|
||||||
|
|
||||||
wl_array_for_each(p, states) {
|
|
||||||
uint32_t state = *p;
|
|
||||||
switch (state) {
|
|
||||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
|
||||||
window->fullscreen = true;
|
|
||||||
break;
|
|
||||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
|
||||||
window->maximized = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
if (!window->fullscreen && !window->maximized) {
|
|
||||||
window->init_width = width;
|
|
||||||
window->init_height = height;
|
|
||||||
}
|
|
||||||
window->width = width;
|
|
||||||
window->height = height;
|
|
||||||
} else if (!window->fullscreen && !window->maximized) {
|
|
||||||
window->width = window->init_width;
|
|
||||||
window->height = window->init_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->needs_update_buffer = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
handle_delete(void *data, struct xdg_surface *xdg_surface)
|
||||||
{
|
{
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||||
handle_xdg_toplevel_configure,
|
handle_configure,
|
||||||
handle_xdg_toplevel_close,
|
handle_delete,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
|
||||||
|
int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
/* Simple-shm is resizable */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ivi_surface_listener ivi_surface_listener = {
|
||||||
|
handle_ivi_surface_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct window *
|
static struct window *
|
||||||
create_window(struct display *display, int width, int height)
|
create_window(struct display *display, int width, int height)
|
||||||
{
|
{
|
||||||
struct window *window;
|
struct window *window;
|
||||||
int i;
|
|
||||||
|
|
||||||
window = zalloc(sizeof *window);
|
window = calloc(1, sizeof *window);
|
||||||
if (!window)
|
if (!window)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
@ -426,56 +164,56 @@ create_window(struct display *display, int width, int height)
|
||||||
window->display = display;
|
window->display = display;
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
window->init_width = width;
|
|
||||||
window->init_height = height;
|
|
||||||
window->surface = wl_compositor_create_surface(display->compositor);
|
window->surface = wl_compositor_create_surface(display->compositor);
|
||||||
window->needs_update_buffer = false;
|
|
||||||
wl_list_init(&window->buffer_list);
|
|
||||||
|
|
||||||
if (display->wm_base) {
|
if (display->shell) {
|
||||||
window->xdg_surface =
|
window->xdg_surface =
|
||||||
xdg_wm_base_get_xdg_surface(display->wm_base,
|
xdg_shell_get_xdg_surface(display->shell,
|
||||||
window->surface);
|
window->surface);
|
||||||
|
|
||||||
assert(window->xdg_surface);
|
assert(window->xdg_surface);
|
||||||
|
|
||||||
xdg_surface_add_listener(window->xdg_surface,
|
xdg_surface_add_listener(window->xdg_surface,
|
||||||
&xdg_surface_listener, window);
|
&xdg_surface_listener, window);
|
||||||
|
|
||||||
window->xdg_toplevel =
|
xdg_surface_set_title(window->xdg_surface, "simple-shm");
|
||||||
xdg_surface_get_toplevel(window->xdg_surface);
|
|
||||||
assert(window->xdg_toplevel);
|
|
||||||
xdg_toplevel_add_listener(window->xdg_toplevel,
|
|
||||||
&xdg_toplevel_listener, window);
|
|
||||||
|
|
||||||
xdg_toplevel_set_title(window->xdg_toplevel, "simple-shm");
|
} else if (display->fshell) {
|
||||||
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
_wl_fullscreen_shell_present_surface(display->fshell,
|
||||||
"org.freedesktop.weston.simple-shm");
|
window->surface,
|
||||||
|
_WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT,
|
||||||
|
NULL);
|
||||||
|
} else if (display->ivi_application ) {
|
||||||
|
uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
|
||||||
|
window->ivi_surface =
|
||||||
|
ivi_application_surface_create(display->ivi_application,
|
||||||
|
id_ivisurf, window->surface);
|
||||||
|
if (window->ivi_surface == NULL) {
|
||||||
|
fprintf(stderr, "Failed to create ivi_client_surface\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ivi_surface_add_listener(window->ivi_surface,
|
||||||
|
&ivi_surface_listener, window);
|
||||||
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
window->wait_for_configure = true;
|
|
||||||
} else {
|
} else {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
|
||||||
alloc_buffer(window, window->width, window->height);
|
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_window(struct window *window)
|
destroy_window(struct window *window)
|
||||||
{
|
{
|
||||||
struct buffer *buffer, *buffer_next;
|
|
||||||
|
|
||||||
if (window->callback)
|
if (window->callback)
|
||||||
wl_callback_destroy(window->callback);
|
wl_callback_destroy(window->callback);
|
||||||
|
|
||||||
wl_list_for_each_safe(buffer, buffer_next,
|
if (window->buffers[0].buffer)
|
||||||
&window->buffer_list, buffer_link)
|
wl_buffer_destroy(window->buffers[0].buffer);
|
||||||
destroy_buffer(buffer);
|
if (window->buffers[1].buffer)
|
||||||
|
wl_buffer_destroy(window->buffers[1].buffer);
|
||||||
|
|
||||||
if (window->xdg_toplevel)
|
|
||||||
xdg_toplevel_destroy(window->xdg_toplevel);
|
|
||||||
if (window->xdg_surface)
|
if (window->xdg_surface)
|
||||||
xdg_surface_destroy(window->xdg_surface);
|
xdg_surface_destroy(window->xdg_surface);
|
||||||
wl_surface_destroy(window->surface);
|
wl_surface_destroy(window->surface);
|
||||||
|
|
@ -485,34 +223,27 @@ destroy_window(struct window *window)
|
||||||
static struct buffer *
|
static struct buffer *
|
||||||
window_next_buffer(struct window *window)
|
window_next_buffer(struct window *window)
|
||||||
{
|
{
|
||||||
struct buffer *buffer = NULL;
|
struct buffer *buffer;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (window->needs_update_buffer) {
|
if (!window->buffers[0].busy)
|
||||||
int i;
|
buffer = &window->buffers[0];
|
||||||
|
else if (!window->buffers[1].busy)
|
||||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
buffer = &window->buffers[1];
|
||||||
alloc_buffer(window, window->width, window->height);
|
else
|
||||||
|
|
||||||
window->needs_update_buffer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = pick_free_buffer(window);
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!buffer->buffer) {
|
if (!buffer->buffer) {
|
||||||
ret = create_shm_buffer(window, buffer,
|
ret = create_shm_buffer(window->display, buffer,
|
||||||
window->display->format);
|
window->width, window->height,
|
||||||
|
WL_SHM_FORMAT_XRGB8888);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* paint the padding */
|
/* paint the padding */
|
||||||
memset(buffer->shm_data, 0xff,
|
memset(buffer->shm_data, 0xff,
|
||||||
window->width * window->height *
|
window->width * window->height * 4);
|
||||||
(window->display->format->bpp / 8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
@ -564,122 +295,6 @@ paint_pixels(void *image, int padding, int width, int height, uint32_t time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
paint_format(void *image, const struct format *format, int width, int height)
|
|
||||||
{
|
|
||||||
uint64_t *img64 = (uint64_t*) image;
|
|
||||||
uint32_t *img32 = (uint32_t*) image;
|
|
||||||
uint16_t *img16 = (uint16_t*) image;
|
|
||||||
uint8_t *img8 = (uint8_t*) image;
|
|
||||||
uint64_t color;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
#define GET_COLOR(y) \
|
|
||||||
(y < (1 * (height / 4))) ? format->color[0] : \
|
|
||||||
(y < (2 * (height / 4))) ? format->color[1] : \
|
|
||||||
(y < (3 * (height / 4))) ? format->color[2] : \
|
|
||||||
format->color[3]
|
|
||||||
|
|
||||||
switch (format->code) {
|
|
||||||
case WL_SHM_FORMAT_R8:
|
|
||||||
for (i = 0; i < height; i++) {
|
|
||||||
color = GET_COLOR(i);
|
|
||||||
for (j = 0; j < width; j++)
|
|
||||||
img8[i * width + j] = color;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WL_SHM_FORMAT_R16:
|
|
||||||
case WL_SHM_FORMAT_GR88:
|
|
||||||
case WL_SHM_FORMAT_RG88:
|
|
||||||
case WL_SHM_FORMAT_RGB565:
|
|
||||||
case WL_SHM_FORMAT_BGR565:
|
|
||||||
case WL_SHM_FORMAT_XRGB4444:
|
|
||||||
case WL_SHM_FORMAT_ARGB4444:
|
|
||||||
case WL_SHM_FORMAT_XBGR4444:
|
|
||||||
case WL_SHM_FORMAT_ABGR4444:
|
|
||||||
case WL_SHM_FORMAT_RGBX4444:
|
|
||||||
case WL_SHM_FORMAT_RGBA4444:
|
|
||||||
case WL_SHM_FORMAT_BGRX4444:
|
|
||||||
case WL_SHM_FORMAT_BGRA4444:
|
|
||||||
case WL_SHM_FORMAT_XRGB1555:
|
|
||||||
case WL_SHM_FORMAT_ARGB1555:
|
|
||||||
case WL_SHM_FORMAT_XBGR1555:
|
|
||||||
case WL_SHM_FORMAT_ABGR1555:
|
|
||||||
case WL_SHM_FORMAT_RGBX5551:
|
|
||||||
case WL_SHM_FORMAT_RGBA5551:
|
|
||||||
case WL_SHM_FORMAT_BGRX5551:
|
|
||||||
case WL_SHM_FORMAT_BGRA5551:
|
|
||||||
for (i = 0; i < height; i++) {
|
|
||||||
color = GET_COLOR(i);
|
|
||||||
for (j = 0; j < width; j++)
|
|
||||||
img16[i * width + j] = color;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WL_SHM_FORMAT_RGB888:
|
|
||||||
case WL_SHM_FORMAT_BGR888:
|
|
||||||
for (i = 0; i < height; i++) {
|
|
||||||
color = GET_COLOR(i);
|
|
||||||
for (j = 0; j < width; j++) {
|
|
||||||
img8[(i * width + j) * 3 + 0] =
|
|
||||||
(color >> 0) & 0xff;
|
|
||||||
img8[(i * width + j) * 3 + 1] =
|
|
||||||
(color >> 8) & 0xff;
|
|
||||||
img8[(i * width + j) * 3 + 2] =
|
|
||||||
(color >> 16) & 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WL_SHM_FORMAT_GR1616:
|
|
||||||
case WL_SHM_FORMAT_RG1616:
|
|
||||||
case WL_SHM_FORMAT_XRGB8888:
|
|
||||||
case WL_SHM_FORMAT_ARGB8888:
|
|
||||||
case WL_SHM_FORMAT_XBGR8888:
|
|
||||||
case WL_SHM_FORMAT_ABGR8888:
|
|
||||||
case WL_SHM_FORMAT_RGBX8888:
|
|
||||||
case WL_SHM_FORMAT_RGBA8888:
|
|
||||||
case WL_SHM_FORMAT_BGRX8888:
|
|
||||||
case WL_SHM_FORMAT_BGRA8888:
|
|
||||||
case WL_SHM_FORMAT_XRGB2101010:
|
|
||||||
case WL_SHM_FORMAT_ARGB2101010:
|
|
||||||
case WL_SHM_FORMAT_XBGR2101010:
|
|
||||||
case WL_SHM_FORMAT_ABGR2101010:
|
|
||||||
case WL_SHM_FORMAT_RGBX1010102:
|
|
||||||
case WL_SHM_FORMAT_RGBA1010102:
|
|
||||||
case WL_SHM_FORMAT_BGRX1010102:
|
|
||||||
case WL_SHM_FORMAT_BGRA1010102:
|
|
||||||
for (i = 0; i < height; i++) {
|
|
||||||
color = GET_COLOR(i);
|
|
||||||
for (j = 0; j < width; j++)
|
|
||||||
img32[i * width + j] = color;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WL_SHM_FORMAT_XRGB16161616:
|
|
||||||
case WL_SHM_FORMAT_ARGB16161616:
|
|
||||||
case WL_SHM_FORMAT_XBGR16161616:
|
|
||||||
case WL_SHM_FORMAT_ABGR16161616:
|
|
||||||
case WL_SHM_FORMAT_XRGB16161616F:
|
|
||||||
case WL_SHM_FORMAT_ARGB16161616F:
|
|
||||||
case WL_SHM_FORMAT_XBGR16161616F:
|
|
||||||
case WL_SHM_FORMAT_ABGR16161616F:
|
|
||||||
for (i = 0; i < height; i++) {
|
|
||||||
color = GET_COLOR(i);
|
|
||||||
for (j = 0; j < width; j++)
|
|
||||||
img64[i * width + j] = color;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef GET_COLOR
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener;
|
static const struct wl_callback_listener frame_listener;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -688,8 +303,6 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
struct window *window = data;
|
struct window *window = data;
|
||||||
struct buffer *buffer;
|
struct buffer *buffer;
|
||||||
|
|
||||||
prune_old_released_buffers(window);
|
|
||||||
|
|
||||||
buffer = window_next_buffer(window);
|
buffer = window_next_buffer(window);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|
@ -698,12 +311,7 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->display->paint_format)
|
paint_pixels(buffer->shm_data, 20, window->width, window->height, time);
|
||||||
paint_format(buffer->shm_data, window->display->format,
|
|
||||||
window->width, window->height);
|
|
||||||
else
|
|
||||||
paint_pixels(buffer->shm_data, 20, window->width,
|
|
||||||
window->height, time);
|
|
||||||
|
|
||||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
wl_surface_damage(window->surface,
|
wl_surface_damage(window->surface,
|
||||||
|
|
@ -727,8 +335,7 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
||||||
{
|
{
|
||||||
struct display *d = data;
|
struct display *d = data;
|
||||||
|
|
||||||
if (format == d->format->code)
|
d->formats |= (1 << format);
|
||||||
d->has_format = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_shm_listener shm_listener = {
|
struct wl_shm_listener shm_listener = {
|
||||||
|
|
@ -736,15 +343,21 @@ struct wl_shm_listener shm_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial)
|
||||||
{
|
{
|
||||||
xdg_wm_base_pong(shell, serial);
|
xdg_shell_pong(shell, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
static const struct xdg_shell_listener xdg_shell_listener = {
|
||||||
xdg_wm_base_ping,
|
xdg_shell_ping,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define XDG_VERSION 5 /* The version of xdg-shell that we implement */
|
||||||
|
#ifdef static_assert
|
||||||
|
static_assert(XDG_VERSION == XDG_SHELL_VERSION_CURRENT,
|
||||||
|
"Interface version doesn't match implementation version");
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
registry_handle_global(void *data, struct wl_registry *registry,
|
registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
uint32_t id, const char *interface, uint32_t version)
|
uint32_t id, const char *interface, uint32_t version)
|
||||||
|
|
@ -755,19 +368,24 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
d->compositor =
|
d->compositor =
|
||||||
wl_registry_bind(registry,
|
wl_registry_bind(registry,
|
||||||
id, &wl_compositor_interface, 1);
|
id, &wl_compositor_interface, 1);
|
||||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
} else if (strcmp(interface, "xdg_shell") == 0) {
|
||||||
d->wm_base = wl_registry_bind(registry,
|
d->shell = wl_registry_bind(registry,
|
||||||
id, &xdg_wm_base_interface, 1);
|
id, &xdg_shell_interface, 1);
|
||||||
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
|
xdg_shell_use_unstable_version(d->shell, XDG_VERSION);
|
||||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
xdg_shell_add_listener(d->shell, &xdg_shell_listener, d);
|
||||||
d->seat = wl_registry_bind(registry, id,
|
} else if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
|
||||||
&wl_seat_interface, 1);
|
d->fshell = wl_registry_bind(registry,
|
||||||
wl_seat_add_listener(d->seat, &seat_listener, d);
|
id, &_wl_fullscreen_shell_interface, 1);
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
d->shm = wl_registry_bind(registry,
|
d->shm = wl_registry_bind(registry,
|
||||||
id, &wl_shm_interface, 1);
|
id, &wl_shm_interface, 1);
|
||||||
wl_shm_add_listener(d->shm, &shm_listener, d);
|
wl_shm_add_listener(d->shm, &shm_listener, d);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(interface, "ivi_application") == 0) {
|
||||||
|
d->ivi_application =
|
||||||
|
wl_registry_bind(registry, id,
|
||||||
|
&ivi_application_interface, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -782,11 +400,11 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct display *
|
static struct display *
|
||||||
create_display(const struct format *format, bool paint_format)
|
create_display(void)
|
||||||
{
|
{
|
||||||
struct display *display;
|
struct display *display;
|
||||||
|
|
||||||
display = zalloc(sizeof *display);
|
display = malloc(sizeof *display);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
fprintf(stderr, "out of memory\n");
|
fprintf(stderr, "out of memory\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -794,9 +412,7 @@ create_display(const struct format *format, bool paint_format)
|
||||||
display->display = wl_display_connect(NULL);
|
display->display = wl_display_connect(NULL);
|
||||||
assert(display->display);
|
assert(display->display);
|
||||||
|
|
||||||
display->format = format;
|
display->formats = 0;
|
||||||
display->paint_format = paint_format;
|
|
||||||
display->has_format= false;
|
|
||||||
display->registry = wl_display_get_registry(display->display);
|
display->registry = wl_display_get_registry(display->display);
|
||||||
wl_registry_add_listener(display->registry,
|
wl_registry_add_listener(display->registry,
|
||||||
®istry_listener, display);
|
®istry_listener, display);
|
||||||
|
|
@ -848,9 +464,8 @@ create_display(const struct format *format, bool paint_format)
|
||||||
* technique.
|
* technique.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!display->has_format) {
|
if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
|
||||||
fprintf(stderr, "Format '%s' not supported by compositor.\n",
|
fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
|
||||||
format->string);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -863,8 +478,11 @@ destroy_display(struct display *display)
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
if (display->wm_base)
|
if (display->shell)
|
||||||
xdg_wm_base_destroy(display->wm_base);
|
xdg_shell_destroy(display->shell);
|
||||||
|
|
||||||
|
if (display->fshell)
|
||||||
|
_wl_fullscreen_shell_release(display->fshell);
|
||||||
|
|
||||||
if (display->compositor)
|
if (display->compositor)
|
||||||
wl_compositor_destroy(display->compositor);
|
wl_compositor_destroy(display->compositor);
|
||||||
|
|
@ -881,86 +499,19 @@ signal_int(int signum)
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
usage(const char *program)
|
|
||||||
{
|
|
||||||
fprintf(stdout,
|
|
||||||
"Usage: %s [OPTIONS]\n"
|
|
||||||
"\n"
|
|
||||||
"Draw pixels into shared memory buffers using wl_shm\n"
|
|
||||||
"\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -h, --help Show this help\n"
|
|
||||||
" -F, --format <format> Test format (see list below)\n"
|
|
||||||
"\n"
|
|
||||||
"RGB formats:\n"
|
|
||||||
" - 8 bpp: r8.\n"
|
|
||||||
"\n"
|
|
||||||
" - 16 bpp: r16, gr88, rg88, rgb565, bgr565, xrgb4444, argb4444, xbgr4444,\n"
|
|
||||||
" abgr4444, rgbx4444, rgba4444, bgrx4444, bgra4444, xrgb1555,\n"
|
|
||||||
" argb1555, xbgr1555, abgr1555, rgbx5551, rgba5551, bgrx5551,\n"
|
|
||||||
" bgra5551.\n"
|
|
||||||
"\n"
|
|
||||||
" - 24 bpp: rgb888, bgr888.\n"
|
|
||||||
"\n"
|
|
||||||
" - 32 bpp: gr1616, rg1616, xrgb8888, argb8888, xbgr8888, abgr8888, rgbx8888,\n"
|
|
||||||
" rgba8888, bgrx8888, bgra8888, xrgb2101010, argb2101010, xbgr2101010,\n"
|
|
||||||
" abgr2101010, rgbx1010102, rgba1010102, bgrx1010102, bgra1010102.\n"
|
|
||||||
"\n"
|
|
||||||
" - 64 bpp: xrgb16161616, argb16161616, xbgr16161616, abgr16161616,\n"
|
|
||||||
" xrgb16161616f, argb16161616f, xbgr16161616f, abgr16161616f.\n",
|
|
||||||
program);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct sigaction sigint;
|
struct sigaction sigint;
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct window *window;
|
struct window *window;
|
||||||
const struct format *format = NULL;
|
int ret = 0;
|
||||||
bool paint_format = false;
|
|
||||||
const char *value;
|
|
||||||
int ret = 0, i, j;
|
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
display = create_display();
|
||||||
if (!strcmp(argv[i], "-h") ||
|
window = create_window(display, 250, 250);
|
||||||
!strcmp(argv[i], "--help")) {
|
|
||||||
usage(argv[0]);
|
|
||||||
return 0;
|
|
||||||
} else if (!strcmp(argv[i], "-F") ||
|
|
||||||
!strcmp(argv[i], "--format")) {
|
|
||||||
value = ++i == argc ? "" : argv[i];
|
|
||||||
for (j = 0; j < (int) ARRAY_SIZE(shm_formats); j++) {
|
|
||||||
if (!strcasecmp(shm_formats[j].string, value)) {
|
|
||||||
format = &shm_formats[j];
|
|
||||||
paint_format = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!format) {
|
|
||||||
fprintf(stderr, "Format '%s' not supported by "
|
|
||||||
"client.\n", value);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!format)
|
|
||||||
for (i = 0; i < (int) ARRAY_SIZE(shm_formats); i++)
|
|
||||||
if (shm_formats[i].code == WL_SHM_FORMAT_XRGB8888)
|
|
||||||
format = &shm_formats[i];
|
|
||||||
assert(format);
|
|
||||||
|
|
||||||
display = create_display(format, paint_format);
|
|
||||||
window = create_window(display, 256, 256);
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
display->window = window;
|
|
||||||
sigint.sa_handler = signal_int;
|
sigint.sa_handler = signal_int;
|
||||||
sigemptyset(&sigint.sa_mask);
|
sigemptyset(&sigint.sa_mask);
|
||||||
sigint.sa_flags = SA_RESETHAND;
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
|
@ -970,14 +521,18 @@ main(int argc, char **argv)
|
||||||
wl_surface_damage(window->surface, 0, 0,
|
wl_surface_damage(window->surface, 0, 0,
|
||||||
window->width, window->height);
|
window->width, window->height);
|
||||||
|
|
||||||
if (!window->wait_for_configure)
|
redraw(window, NULL, 0);
|
||||||
redraw(window, NULL, 0);
|
|
||||||
|
|
||||||
while (running && ret != -1)
|
while (running && ret != -1)
|
||||||
ret = wl_display_dispatch(display->display);
|
ret = wl_display_dispatch(display->display);
|
||||||
|
|
||||||
fprintf(stderr, "simple-shm exiting\n");
|
fprintf(stderr, "simple-shm exiting\n");
|
||||||
|
|
||||||
|
if (window->display->ivi_application) {
|
||||||
|
ivi_surface_destroy(window->ivi_surface);
|
||||||
|
ivi_application_destroy(window->display->ivi_application);
|
||||||
|
}
|
||||||
|
|
||||||
destroy_window(window);
|
destroy_window(window);
|
||||||
destroy_display(display);
|
destroy_display(display);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,880 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright © 2011 Benjamin Franzke
|
|
||||||
* Copyright © 2010 Intel Corporation
|
|
||||||
* Copyright © 2025 Collabora, Ltd.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#include "shared/os-compatibility.h"
|
|
||||||
#include "shared/timespec-util.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
|
||||||
|
|
||||||
#include "commit-timing-v1-client-protocol.h"
|
|
||||||
#include "fifo-v1-client-protocol.h"
|
|
||||||
#include "presentation-time-client-protocol.h"
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
|
||||||
|
|
||||||
#define MAX_BUFFER_ALLOC 1000
|
|
||||||
|
|
||||||
struct display {
|
|
||||||
struct wl_display *display;
|
|
||||||
struct wl_registry *registry;
|
|
||||||
struct wl_compositor *compositor;
|
|
||||||
struct xdg_wm_base *wm_base;
|
|
||||||
struct wl_seat *seat;
|
|
||||||
struct wl_keyboard *keyboard;
|
|
||||||
struct wl_shm *shm;
|
|
||||||
struct wp_commit_timing_manager_v1 *commit_timing_manager;
|
|
||||||
struct wp_fifo_manager_v1 *fifo_manager;
|
|
||||||
struct wp_presentation *presentation;
|
|
||||||
bool have_clock_id;
|
|
||||||
clockid_t presentation_clock_id;
|
|
||||||
int64_t first_frame_time;
|
|
||||||
int64_t refresh_nsec;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct buffer {
|
|
||||||
struct window *window;
|
|
||||||
struct wl_buffer *buffer;
|
|
||||||
void *shm_data;
|
|
||||||
int busy;
|
|
||||||
int width, height;
|
|
||||||
size_t size; /* width * 4 * height */
|
|
||||||
struct wl_list buffer_link; /** window::buffer_list */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct window {
|
|
||||||
struct display *display;
|
|
||||||
int width, height;
|
|
||||||
int init_width, init_height;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
struct xdg_surface *xdg_surface;
|
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
|
||||||
struct wl_list buffer_list;
|
|
||||||
struct wp_fifo_v1 *fifo;
|
|
||||||
struct wp_commit_timer_v1 *commit_timer;
|
|
||||||
bool wait_for_configure;
|
|
||||||
bool maximized;
|
|
||||||
bool fullscreen;
|
|
||||||
bool needs_update_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct feedback {
|
|
||||||
struct wp_presentation_feedback *fb;
|
|
||||||
struct window *window;
|
|
||||||
int64_t target_time;
|
|
||||||
bool final;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int running = 1;
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_for_time(void *data, int64_t time, bool wait_fifo);
|
|
||||||
|
|
||||||
static void
|
|
||||||
finish_run(struct window *window);
|
|
||||||
|
|
||||||
static struct buffer *
|
|
||||||
alloc_buffer(struct window *window, int width, int height)
|
|
||||||
{
|
|
||||||
struct buffer *buffer = calloc(1, sizeof(*buffer));
|
|
||||||
|
|
||||||
buffer->width = width;
|
|
||||||
buffer->height = height;
|
|
||||||
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_buffer(struct buffer *buffer)
|
|
||||||
{
|
|
||||||
if (buffer->buffer)
|
|
||||||
wl_buffer_destroy(buffer->buffer);
|
|
||||||
|
|
||||||
munmap(buffer->shm_data, buffer->size);
|
|
||||||
wl_list_remove(&buffer->buffer_link);
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct buffer *
|
|
||||||
pick_free_buffer(struct window *window)
|
|
||||||
{
|
|
||||||
struct buffer *b;
|
|
||||||
struct buffer *buffer = NULL;
|
|
||||||
|
|
||||||
wl_list_for_each(b, &window->buffer_list, buffer_link) {
|
|
||||||
if (!b->busy) {
|
|
||||||
buffer = b;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prune_old_released_buffers(struct window *window)
|
|
||||||
{
|
|
||||||
struct buffer *b, *b_next;
|
|
||||||
|
|
||||||
wl_list_for_each_safe(b, b_next,
|
|
||||||
&window->buffer_list, buffer_link) {
|
|
||||||
if (!b->busy && (b->width != window->width ||
|
|
||||||
b->height != window->height))
|
|
||||||
destroy_buffer(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
buffer_release(void *data, struct wl_buffer *buffer)
|
|
||||||
{
|
|
||||||
struct buffer *mybuf = data;
|
|
||||||
|
|
||||||
mybuf->busy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_buffer_listener buffer_listener = {
|
|
||||||
buffer_release
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
create_shm_buffer(struct window *window, struct buffer *buffer)
|
|
||||||
{
|
|
||||||
struct wl_shm_pool *pool;
|
|
||||||
int fd, size, stride;
|
|
||||||
void *data;
|
|
||||||
int width, height;
|
|
||||||
struct display *display;
|
|
||||||
|
|
||||||
width = window->width;
|
|
||||||
height = window->height;
|
|
||||||
stride = width * 4;
|
|
||||||
size = stride * height;
|
|
||||||
display = window->display;
|
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
|
||||||
size, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
if (data == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pool = wl_shm_create_pool(display->shm, fd, size);
|
|
||||||
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
|
||||||
width, height,
|
|
||||||
stride,
|
|
||||||
WL_SHM_FORMAT_XRGB8888);
|
|
||||||
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
|
||||||
wl_shm_pool_destroy(pool);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
buffer->size = size;
|
|
||||||
buffer->shm_data = data;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t format, int fd, uint32_t size)
|
|
||||||
{
|
|
||||||
/* Just so we don’t leak the keymap fd */
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, struct wl_surface *surface,
|
|
||||||
struct wl_array *keys)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, struct wl_surface *surface)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, uint32_t time, uint32_t key,
|
|
||||||
uint32_t state)
|
|
||||||
{
|
|
||||||
if (key == KEY_ESC && state)
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
|
||||||
uint32_t serial, uint32_t mods_depressed,
|
|
||||||
uint32_t mods_latched, uint32_t mods_locked,
|
|
||||||
uint32_t group)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_keyboard_listener keyboard_listener = {
|
|
||||||
keyboard_handle_keymap,
|
|
||||||
keyboard_handle_enter,
|
|
||||||
keyboard_handle_leave,
|
|
||||||
keyboard_handle_key,
|
|
||||||
keyboard_handle_modifiers,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|
||||||
enum wl_seat_capability caps)
|
|
||||||
{
|
|
||||||
struct display *d = data;
|
|
||||||
|
|
||||||
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
|
|
||||||
d->keyboard = wl_seat_get_keyboard(seat);
|
|
||||||
wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
|
|
||||||
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
|
|
||||||
wl_keyboard_destroy(d->keyboard);
|
|
||||||
d->keyboard = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_seat_listener seat_listener = {
|
|
||||||
seat_handle_capabilities,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
|
|
||||||
uint32_t serial)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
|
|
||||||
xdg_surface_ack_configure(surface, serial);
|
|
||||||
|
|
||||||
if (window->wait_for_configure) {
|
|
||||||
draw_for_time(window, 0, false);
|
|
||||||
window->wait_for_configure = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
|
||||||
handle_xdg_surface_configure,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|
||||||
int32_t width, int32_t height,
|
|
||||||
struct wl_array *states)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
uint32_t *p;
|
|
||||||
|
|
||||||
window->fullscreen = false;
|
|
||||||
window->maximized = false;
|
|
||||||
|
|
||||||
wl_array_for_each(p, states) {
|
|
||||||
uint32_t state = *p;
|
|
||||||
switch (state) {
|
|
||||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
|
||||||
window->fullscreen = true;
|
|
||||||
break;
|
|
||||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
|
||||||
window->maximized = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
if (!window->fullscreen && !window->maximized) {
|
|
||||||
window->init_width = width;
|
|
||||||
window->init_height = height;
|
|
||||||
}
|
|
||||||
window->width = width;
|
|
||||||
window->height = height;
|
|
||||||
} else if (!window->fullscreen && !window->maximized) {
|
|
||||||
window->width = window->init_width;
|
|
||||||
window->height = window->init_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->needs_update_buffer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
|
||||||
{
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
|
||||||
handle_xdg_toplevel_configure,
|
|
||||||
handle_xdg_toplevel_close,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct window *
|
|
||||||
create_window(struct display *display, int width, int height)
|
|
||||||
{
|
|
||||||
struct window *window;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
window = zalloc(sizeof *window);
|
|
||||||
if (!window)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
window->display = display;
|
|
||||||
window->width = width;
|
|
||||||
window->height = height;
|
|
||||||
window->init_width = width;
|
|
||||||
window->init_height = height;
|
|
||||||
window->surface = wl_compositor_create_surface(display->compositor);
|
|
||||||
window->fifo = wp_fifo_manager_v1_get_fifo(display->fifo_manager,
|
|
||||||
window->surface);
|
|
||||||
window->commit_timer = wp_commit_timing_manager_v1_get_timer(display->commit_timing_manager,
|
|
||||||
window->surface);
|
|
||||||
window->needs_update_buffer = false;
|
|
||||||
wl_list_init(&window->buffer_list);
|
|
||||||
|
|
||||||
assert(display->wm_base);
|
|
||||||
|
|
||||||
window->xdg_surface =
|
|
||||||
xdg_wm_base_get_xdg_surface(display->wm_base,
|
|
||||||
window->surface);
|
|
||||||
assert(window->xdg_surface);
|
|
||||||
xdg_surface_add_listener(window->xdg_surface,
|
|
||||||
&xdg_surface_listener, window);
|
|
||||||
|
|
||||||
window->xdg_toplevel =
|
|
||||||
xdg_surface_get_toplevel(window->xdg_surface);
|
|
||||||
assert(window->xdg_toplevel);
|
|
||||||
xdg_toplevel_add_listener(window->xdg_toplevel,
|
|
||||||
&xdg_toplevel_listener, window);
|
|
||||||
|
|
||||||
xdg_toplevel_set_title(window->xdg_toplevel, "simple-timing");
|
|
||||||
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
|
||||||
"org.freedesktop.weston.simple-timing");
|
|
||||||
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
window->wait_for_configure = true;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
|
||||||
alloc_buffer(window, window->width, window->height);
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_window(struct window *window)
|
|
||||||
{
|
|
||||||
struct buffer *buffer, *buffer_next;
|
|
||||||
|
|
||||||
wl_list_for_each_safe(buffer, buffer_next,
|
|
||||||
&window->buffer_list, buffer_link)
|
|
||||||
destroy_buffer(buffer);
|
|
||||||
|
|
||||||
if (window->xdg_toplevel)
|
|
||||||
xdg_toplevel_destroy(window->xdg_toplevel);
|
|
||||||
if (window->xdg_surface)
|
|
||||||
xdg_surface_destroy(window->xdg_surface);
|
|
||||||
wl_surface_destroy(window->surface);
|
|
||||||
|
|
||||||
if (window->fifo)
|
|
||||||
wp_fifo_v1_destroy(window->fifo);
|
|
||||||
|
|
||||||
if (window->commit_timer)
|
|
||||||
wp_commit_timer_v1_destroy(window->commit_timer);
|
|
||||||
|
|
||||||
free(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct buffer *
|
|
||||||
window_next_buffer(struct window *window)
|
|
||||||
{
|
|
||||||
struct buffer *buffer = NULL;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (window->needs_update_buffer) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
|
||||||
alloc_buffer(window, window->width, window->height);
|
|
||||||
|
|
||||||
window->needs_update_buffer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = pick_free_buffer(window);
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!buffer->buffer) {
|
|
||||||
ret = create_shm_buffer(window, buffer);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* paint the padding */
|
|
||||||
memset(buffer->shm_data, 0xff,
|
|
||||||
window->width * window->height * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
paint_pixels(void *image, int width, int height, uint32_t time)
|
|
||||||
{
|
|
||||||
const int halfh = height / 2;
|
|
||||||
const int halfw = width / 2;
|
|
||||||
int ir, or;
|
|
||||||
uint32_t *pixel = image;
|
|
||||||
int y;
|
|
||||||
|
|
||||||
/* squared radii thresholds */
|
|
||||||
or = (halfw < halfh ? halfw : halfh) - 8;
|
|
||||||
ir = or - 32;
|
|
||||||
or *= or;
|
|
||||||
ir *= ir;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++) {
|
|
||||||
int x;
|
|
||||||
int y2 = (y - halfh) * (y - halfh);
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
uint32_t v;
|
|
||||||
|
|
||||||
/* squared distance from center */
|
|
||||||
int r2 = (x - halfw) * (x - halfw) + y2;
|
|
||||||
|
|
||||||
if (r2 < ir)
|
|
||||||
v = (r2 / 32 + time / 64) * 0x0080401;
|
|
||||||
else if (r2 < or)
|
|
||||||
v = (y + time / 32) * 0x0080401;
|
|
||||||
else
|
|
||||||
v = (x + time / 16) * 0x0080401;
|
|
||||||
v &= 0x00ffffff;
|
|
||||||
|
|
||||||
/* cross if compositor uses X from XRGB as alpha */
|
|
||||||
if (abs(x - y) > 6 && abs(x + y - height) > 6)
|
|
||||||
v |= 0xff000000;
|
|
||||||
|
|
||||||
*pixel++ = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
queue_some_frames(struct window *window)
|
|
||||||
{
|
|
||||||
struct display *display = window->display;
|
|
||||||
int64_t target_nsec;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert(display->first_frame_time);
|
|
||||||
|
|
||||||
/* Round off error will cause us problems if we don't
|
|
||||||
* reduce this a bit, because we could end up rounding
|
|
||||||
* to either side of a refresh.
|
|
||||||
*/
|
|
||||||
target_nsec = display->first_frame_time - 100000;
|
|
||||||
|
|
||||||
for (i = 0; i < 60; i++) {
|
|
||||||
target_nsec += display->refresh_nsec * 2;
|
|
||||||
draw_for_time(window, target_nsec, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 30; i++) {
|
|
||||||
target_nsec += display->refresh_nsec * 4;
|
|
||||||
draw_for_time(window, target_nsec, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
|
||||||
target_nsec += display->refresh_nsec * 10;
|
|
||||||
draw_for_time(window, target_nsec, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
|
||||||
target_nsec += display->refresh_nsec * 100;
|
|
||||||
draw_for_time(window, target_nsec, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
finish_run(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
feedback_sync_output(void *data,
|
|
||||||
struct wp_presentation_feedback *presentation_feedback,
|
|
||||||
struct wl_output *output)
|
|
||||||
{
|
|
||||||
/* Just don't care */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
feedback_presented(void *data,
|
|
||||||
struct wp_presentation_feedback *presentation_feedback,
|
|
||||||
uint32_t tv_sec_hi,
|
|
||||||
uint32_t tv_sec_lo,
|
|
||||||
uint32_t tv_nsec,
|
|
||||||
uint32_t refresh_nsec,
|
|
||||||
uint32_t seq_hi,
|
|
||||||
uint32_t seq_lo,
|
|
||||||
uint32_t flags)
|
|
||||||
{
|
|
||||||
struct feedback *feedback = data;
|
|
||||||
struct window *window = feedback->window;
|
|
||||||
struct display *display = window->display;
|
|
||||||
struct timespec pres_ts = {
|
|
||||||
.tv_sec = ((int64_t)tv_sec_hi << 32) + tv_sec_lo,
|
|
||||||
.tv_nsec = tv_nsec,
|
|
||||||
};
|
|
||||||
int64_t ntime = timespec_to_nsec(&pres_ts);
|
|
||||||
double delay;
|
|
||||||
|
|
||||||
if (feedback->final) {
|
|
||||||
running = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!feedback->target_time) {
|
|
||||||
display->first_frame_time = ntime;
|
|
||||||
display->refresh_nsec = refresh_nsec;
|
|
||||||
queue_some_frames(window);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
delay = (ntime - feedback->target_time) / 1000000.0;
|
|
||||||
|
|
||||||
printf("%fms away from intended time\n", delay);
|
|
||||||
if (fabs(delay) > display->refresh_nsec / 1000000)
|
|
||||||
printf("Warning: we missed the intended target display cycle.\n");
|
|
||||||
|
|
||||||
out:
|
|
||||||
wp_presentation_feedback_destroy(feedback->fb);
|
|
||||||
free(feedback);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
feedback_discarded(void *data,
|
|
||||||
struct wp_presentation_feedback *presentation_feedback)
|
|
||||||
{
|
|
||||||
struct feedback *feedback = data;
|
|
||||||
|
|
||||||
printf("Warning: a frame was discarded\n");
|
|
||||||
|
|
||||||
if (feedback->final)
|
|
||||||
running = 0;
|
|
||||||
|
|
||||||
wp_presentation_feedback_destroy(feedback->fb);
|
|
||||||
free(feedback);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wp_presentation_feedback_listener feedback_listener = {
|
|
||||||
feedback_sync_output,
|
|
||||||
feedback_presented,
|
|
||||||
feedback_discarded,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
finish_run(struct window *window)
|
|
||||||
{
|
|
||||||
struct display *display = window->display;
|
|
||||||
struct feedback *feedback;
|
|
||||||
struct buffer *buffer;
|
|
||||||
|
|
||||||
feedback = xzalloc(sizeof *feedback);
|
|
||||||
feedback->window = window;
|
|
||||||
feedback->final = true;
|
|
||||||
feedback->target_time = 0;
|
|
||||||
|
|
||||||
buffer = window_next_buffer(window);
|
|
||||||
assert(buffer);
|
|
||||||
|
|
||||||
paint_pixels(buffer->shm_data, window->width,
|
|
||||||
window->height, 1);
|
|
||||||
|
|
||||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
|
||||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
|
||||||
|
|
||||||
feedback->fb = wp_presentation_feedback(display->presentation,
|
|
||||||
window->surface);
|
|
||||||
wp_presentation_feedback_add_listener(feedback->fb,
|
|
||||||
&feedback_listener, feedback);
|
|
||||||
|
|
||||||
wp_fifo_v1_wait_barrier(window->fifo);
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_for_time(void *data, int64_t time, bool wait_fifo)
|
|
||||||
{
|
|
||||||
struct window *window = data;
|
|
||||||
struct display *display = window->display;
|
|
||||||
struct buffer *buffer;
|
|
||||||
struct feedback *feedback;
|
|
||||||
|
|
||||||
assert(display->have_clock_id);
|
|
||||||
|
|
||||||
prune_old_released_buffers(window);
|
|
||||||
|
|
||||||
buffer = window_next_buffer(window);
|
|
||||||
assert(buffer);
|
|
||||||
|
|
||||||
paint_pixels(buffer->shm_data, window->width,
|
|
||||||
window->height, time / 1000000);
|
|
||||||
|
|
||||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
|
||||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
|
||||||
|
|
||||||
feedback = xzalloc(sizeof *feedback);
|
|
||||||
feedback->window = window;
|
|
||||||
|
|
||||||
feedback->fb = wp_presentation_feedback(display->presentation,
|
|
||||||
window->surface);
|
|
||||||
wp_presentation_feedback_add_listener(feedback->fb,
|
|
||||||
&feedback_listener, feedback);
|
|
||||||
|
|
||||||
feedback->target_time = time;
|
|
||||||
if (time) {
|
|
||||||
struct timespec target;
|
|
||||||
|
|
||||||
timespec_from_nsec(&target, time);
|
|
||||||
wp_commit_timer_v1_set_timestamp(window->commit_timer,
|
|
||||||
(int64_t)target.tv_sec >> 32,
|
|
||||||
target.tv_sec,
|
|
||||||
target.tv_nsec);
|
|
||||||
}
|
|
||||||
wp_fifo_v1_set_barrier(window->fifo);
|
|
||||||
wl_surface_commit(window->surface);
|
|
||||||
buffer->busy = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
|
||||||
{
|
|
||||||
xdg_wm_base_pong(shell, serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
|
||||||
xdg_wm_base_ping,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
presentation_handle_clock_id(void *data,
|
|
||||||
struct wp_presentation *wp_presentation,
|
|
||||||
uint32_t clock_id)
|
|
||||||
{
|
|
||||||
struct display *display = data;
|
|
||||||
|
|
||||||
display->presentation_clock_id = clock_id;
|
|
||||||
display->have_clock_id = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wp_presentation_listener presentation_listener = {
|
|
||||||
presentation_handle_clock_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
registry_handle_global(void *data, struct wl_registry *registry,
|
|
||||||
uint32_t id, const char *interface, uint32_t version)
|
|
||||||
{
|
|
||||||
struct display *d = data;
|
|
||||||
|
|
||||||
if (strcmp(interface, "wl_compositor") == 0) {
|
|
||||||
d->compositor =
|
|
||||||
wl_registry_bind(registry,
|
|
||||||
id, &wl_compositor_interface, 1);
|
|
||||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
|
||||||
d->wm_base = wl_registry_bind(registry,
|
|
||||||
id, &xdg_wm_base_interface, 1);
|
|
||||||
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
|
|
||||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
|
||||||
d->seat = wl_registry_bind(registry, id,
|
|
||||||
&wl_seat_interface, 1);
|
|
||||||
wl_seat_add_listener(d->seat, &seat_listener, d);
|
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
|
||||||
d->shm = wl_registry_bind(registry,
|
|
||||||
id, &wl_shm_interface, 1);
|
|
||||||
} else if (strcmp(interface, wp_commit_timing_manager_v1_interface.name) == 0) {
|
|
||||||
d->commit_timing_manager = wl_registry_bind(registry, id,
|
|
||||||
&wp_commit_timing_manager_v1_interface,
|
|
||||||
1);
|
|
||||||
} else if (strcmp(interface, wp_fifo_manager_v1_interface.name) == 0) {
|
|
||||||
d->fifo_manager = wl_registry_bind(registry, id,
|
|
||||||
&wp_fifo_manager_v1_interface,
|
|
||||||
1);
|
|
||||||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
|
||||||
d->presentation = wl_registry_bind(registry, id,
|
|
||||||
&wp_presentation_interface,
|
|
||||||
2);
|
|
||||||
wp_presentation_add_listener(d->presentation,
|
|
||||||
&presentation_listener, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
registry_handle_global_remove(void *data, struct wl_registry *registry,
|
|
||||||
uint32_t name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
|
||||||
registry_handle_global,
|
|
||||||
registry_handle_global_remove
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct display *
|
|
||||||
create_display(void)
|
|
||||||
{
|
|
||||||
struct display *display;
|
|
||||||
|
|
||||||
display = xzalloc(sizeof *display);
|
|
||||||
|
|
||||||
display->display = wl_display_connect(NULL);
|
|
||||||
assert(display->display);
|
|
||||||
|
|
||||||
display->registry = wl_display_get_registry(display->display);
|
|
||||||
wl_registry_add_listener(display->registry,
|
|
||||||
®istry_listener, display);
|
|
||||||
wl_display_roundtrip(display->display);
|
|
||||||
if (display->shm == NULL) {
|
|
||||||
fprintf(stderr, "No wl_shm global\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_display_roundtrip(display->display);
|
|
||||||
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_display(struct display *display)
|
|
||||||
{
|
|
||||||
if (display->shm)
|
|
||||||
wl_shm_destroy(display->shm);
|
|
||||||
|
|
||||||
if (display->wm_base)
|
|
||||||
xdg_wm_base_destroy(display->wm_base);
|
|
||||||
|
|
||||||
if (display->compositor)
|
|
||||||
wl_compositor_destroy(display->compositor);
|
|
||||||
|
|
||||||
if (display->presentation)
|
|
||||||
wp_presentation_destroy(display->presentation);
|
|
||||||
|
|
||||||
if (display->fifo_manager)
|
|
||||||
wp_fifo_manager_v1_destroy(display->fifo_manager);
|
|
||||||
|
|
||||||
if (display->commit_timing_manager)
|
|
||||||
wp_commit_timing_manager_v1_destroy(display->commit_timing_manager);
|
|
||||||
|
|
||||||
if (display->keyboard)
|
|
||||||
wl_keyboard_destroy(display->keyboard);
|
|
||||||
|
|
||||||
if (display->seat)
|
|
||||||
wl_seat_destroy(display->seat);
|
|
||||||
|
|
||||||
wl_registry_destroy(display->registry);
|
|
||||||
wl_display_flush(display->display);
|
|
||||||
wl_display_disconnect(display->display);
|
|
||||||
free(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
signal_int(int signum)
|
|
||||||
{
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(const char *program)
|
|
||||||
{
|
|
||||||
fprintf(stdout,
|
|
||||||
"Usage: %s [OPTIONS]\n"
|
|
||||||
"\n"
|
|
||||||
"Schedule frames in the future with commit-timing\n"
|
|
||||||
"\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -h, --help Show this help\n"
|
|
||||||
"\n",
|
|
||||||
program);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct sigaction sigint;
|
|
||||||
struct display *display;
|
|
||||||
struct window *window;
|
|
||||||
int ret = 0, i;
|
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
if (!strcmp(argv[i], "-h") ||
|
|
||||||
!strcmp(argv[i], "--help")) {
|
|
||||||
usage(argv[0]);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display = create_display();
|
|
||||||
window = create_window(display, 256, 256);
|
|
||||||
if (!window)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
sigint.sa_handler = signal_int;
|
|
||||||
sigemptyset(&sigint.sa_mask);
|
|
||||||
sigint.sa_flags = SA_RESETHAND;
|
|
||||||
sigaction(SIGINT, &sigint, NULL);
|
|
||||||
|
|
||||||
while (running && ret != -1)
|
|
||||||
ret = wl_display_dispatch(display->display);
|
|
||||||
|
|
||||||
fprintf(stderr, "simple-timing exiting\n");
|
|
||||||
|
|
||||||
destroy_window(window);
|
|
||||||
destroy_display(display);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +1,40 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2011 Benjamin Franzke
|
* Copyright © 2011 Benjamin Franzke
|
||||||
* Copyright © 2011 Intel Corporation
|
* Copyright © 2011 Intel Corporation
|
||||||
* Copyright © 2021 Collabora, Ltd.
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "shared/helpers.h"
|
#include "../shared/os-compatibility.h"
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "shared/os-compatibility.h"
|
|
||||||
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
|
||||||
struct seat {
|
struct seat {
|
||||||
struct touch *touch;
|
struct touch *touch;
|
||||||
|
|
@ -48,92 +42,54 @@ struct seat {
|
||||||
struct wl_touch *wl_touch;
|
struct wl_touch *wl_touch;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buffer {
|
|
||||||
struct wl_buffer *buffer;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct touch {
|
struct touch {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct xdg_wm_base *wm_base;
|
struct wl_shell *shell;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
|
struct wl_pointer *pointer;
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct xdg_surface *xdg_surface;
|
struct wl_shell_surface *shell_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct wl_buffer *buffer;
|
||||||
struct buffer *buffer;
|
int has_argb;
|
||||||
int width, height;
|
int width, height;
|
||||||
int init_width, init_height;
|
void *data;
|
||||||
bool running;
|
|
||||||
bool wait_for_configure;
|
|
||||||
bool needs_buffer_update;
|
|
||||||
bool has_argb;
|
|
||||||
bool maximized;
|
|
||||||
bool fullscreen;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct buffer *
|
static void
|
||||||
create_shm_buffer(struct touch *touch)
|
create_shm_buffer(struct touch *touch)
|
||||||
{
|
{
|
||||||
struct wl_shm_pool *pool;
|
struct wl_shm_pool *pool;
|
||||||
int fd, size, stride;
|
int fd, size, stride;
|
||||||
void *data;
|
|
||||||
struct buffer *buffer;
|
|
||||||
|
|
||||||
buffer = xzalloc(sizeof(*buffer));
|
|
||||||
|
|
||||||
stride = touch->width * 4;
|
stride = touch->width * 4;
|
||||||
size = stride * touch->height;
|
size = stride * touch->height;
|
||||||
|
|
||||||
fd = os_create_anonymous_file(size);
|
fd = os_create_anonymous_file(size);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
|
||||||
size, strerror(errno));
|
size);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
touch->data =
|
||||||
if (data == MAP_FAILED) {
|
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
if (touch->data == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "mmap failed: %m\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = wl_shm_create_pool(touch->shm, fd, size);
|
pool = wl_shm_create_pool(touch->shm, fd, size);
|
||||||
buffer->buffer =
|
touch->buffer =
|
||||||
wl_shm_pool_create_buffer(pool, 0,
|
wl_shm_pool_create_buffer(pool, 0,
|
||||||
touch->width, touch->height, stride,
|
touch->width, touch->height, stride,
|
||||||
WL_SHM_FORMAT_ARGB8888);
|
WL_SHM_FORMAT_ARGB8888);
|
||||||
|
|
||||||
wl_shm_pool_destroy(pool);
|
wl_shm_pool_destroy(pool);
|
||||||
|
|
||||||
buffer->data = data;
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
redraw(void *data)
|
|
||||||
{
|
|
||||||
struct touch *touch = data;
|
|
||||||
struct buffer *buffer = NULL;
|
|
||||||
|
|
||||||
buffer = create_shm_buffer(touch);
|
|
||||||
assert(buffer);
|
|
||||||
|
|
||||||
if (touch->buffer)
|
|
||||||
free(touch->buffer);
|
|
||||||
|
|
||||||
touch->buffer = buffer;
|
|
||||||
|
|
||||||
/* paint the "work-area" */
|
|
||||||
memset(buffer->data, 64, touch->width * touch->height * 4);
|
|
||||||
|
|
||||||
wl_surface_attach(touch->surface, buffer->buffer, 0, 0);
|
|
||||||
wl_surface_damage(touch->surface, 0, 0, touch->width, touch->height);
|
|
||||||
wl_surface_commit(touch->surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -142,7 +98,7 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
||||||
struct touch *touch = data;
|
struct touch *touch = data;
|
||||||
|
|
||||||
if (format == WL_SHM_FORMAT_ARGB8888)
|
if (format == WL_SHM_FORMAT_ARGB8888)
|
||||||
touch->has_argb = true;
|
touch->has_argb = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_shm_listener shm_listener = {
|
struct wl_shm_listener shm_listener = {
|
||||||
|
|
@ -172,7 +128,7 @@ touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id)
|
||||||
y < 2 || y >= touch->height - 2)
|
y < 2 || y >= touch->height - 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = ((uint32_t *) touch->buffer->data) + (x - 2) + (y - 2) * touch->width;
|
p = (uint32_t *) touch->data + (x - 2) + (y - 2) * touch->width;
|
||||||
p[2] = c;
|
p[2] = c;
|
||||||
p += touch->width;
|
p += touch->width;
|
||||||
p[1] = c;
|
p[1] = c;
|
||||||
|
|
@ -191,7 +147,7 @@ touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id)
|
||||||
p += touch->width;
|
p += touch->width;
|
||||||
p[2] = c;
|
p[2] = c;
|
||||||
|
|
||||||
wl_surface_attach(touch->surface, touch->buffer->buffer, 0, 0);
|
wl_surface_attach(touch->surface, touch->buffer, 0, 0);
|
||||||
wl_surface_damage(touch->surface, x - 2, y - 2, 5, 5);
|
wl_surface_damage(touch->surface, x - 2, y - 2, 5, 5);
|
||||||
/* todo: We could queue up more damage before committing, if there
|
/* todo: We could queue up more damage before committing, if there
|
||||||
* are more input events to handle.
|
* are more input events to handle.
|
||||||
|
|
@ -283,32 +239,27 @@ add_seat(struct touch *touch, uint32_t name, uint32_t version)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
|
handle_ping(void *data, struct wl_shell_surface *shell_surface,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
struct touch *touch = data;
|
wl_shell_surface_pong(shell_surface, serial);
|
||||||
|
|
||||||
xdg_surface_ack_configure(surface, serial);
|
|
||||||
|
|
||||||
if (touch->wait_for_configure || touch->needs_buffer_update) {
|
|
||||||
redraw(touch);
|
|
||||||
touch->wait_for_configure = false;
|
|
||||||
touch->needs_buffer_update = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
|
||||||
handle_xdg_surface_configure,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
handle_configure(void *data, struct wl_shell_surface *shell_surface,
|
||||||
|
uint32_t edges, int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
xdg_wm_base_pong(shell, serial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_wm_base_listener wm_base_listener = {
|
static void
|
||||||
xdg_wm_base_ping,
|
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_shell_surface_listener shell_surface_listener = {
|
||||||
|
handle_ping,
|
||||||
|
handle_configure,
|
||||||
|
handle_popup_done
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -321,12 +272,10 @@ handle_global(void *data, struct wl_registry *registry,
|
||||||
touch->compositor =
|
touch->compositor =
|
||||||
wl_registry_bind(registry, name,
|
wl_registry_bind(registry, name,
|
||||||
&wl_compositor_interface, 1);
|
&wl_compositor_interface, 1);
|
||||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
} else if (strcmp(interface, "wl_shell") == 0) {
|
||||||
touch->wm_base =
|
touch->shell =
|
||||||
wl_registry_bind(registry, name,
|
wl_registry_bind(registry, name,
|
||||||
&xdg_wm_base_interface, 1);
|
&wl_shell_interface, 1);
|
||||||
xdg_wm_base_add_listener(touch->wm_base,
|
|
||||||
&wm_base_listener, touch);
|
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
touch->shm = wl_registry_bind(registry, name,
|
touch->shm = wl_registry_bind(registry, name,
|
||||||
&wl_shm_interface, 1);
|
&wl_shm_interface, 1);
|
||||||
|
|
@ -346,56 +295,6 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
handle_global_remove
|
handle_global_remove
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
handle_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|
||||||
int32_t width, int32_t height, struct wl_array *states)
|
|
||||||
{
|
|
||||||
struct touch *touch = data;
|
|
||||||
uint32_t *p;
|
|
||||||
|
|
||||||
touch->fullscreen = false;
|
|
||||||
touch->maximized = false;
|
|
||||||
|
|
||||||
wl_array_for_each(p, states) {
|
|
||||||
uint32_t state = *p;
|
|
||||||
switch (state) {
|
|
||||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
|
||||||
touch->fullscreen = true;
|
|
||||||
break;
|
|
||||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
|
||||||
touch->maximized = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
if (!touch->fullscreen && !touch->maximized) {
|
|
||||||
touch->init_width = width;
|
|
||||||
touch->init_width = height;
|
|
||||||
}
|
|
||||||
touch->width = width;
|
|
||||||
touch->height = height;
|
|
||||||
} else if (!touch->fullscreen && !touch->maximized) {
|
|
||||||
touch->width = touch->init_width;
|
|
||||||
touch->height = touch->init_height;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
touch->needs_buffer_update = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
|
||||||
{
|
|
||||||
struct touch *touch = data;
|
|
||||||
touch->running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
|
||||||
handle_toplevel_configure,
|
|
||||||
handle_toplevel_close,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct touch *
|
static struct touch *
|
||||||
touch_create(int width, int height)
|
touch_create(int width, int height)
|
||||||
{
|
{
|
||||||
|
|
@ -409,8 +308,7 @@ touch_create(int width, int height)
|
||||||
touch->display = wl_display_connect(NULL);
|
touch->display = wl_display_connect(NULL);
|
||||||
assert(touch->display);
|
assert(touch->display);
|
||||||
|
|
||||||
touch->has_argb = false;
|
touch->has_argb = 0;
|
||||||
touch->buffer = NULL;
|
|
||||||
touch->registry = wl_display_get_registry(touch->display);
|
touch->registry = wl_display_get_registry(touch->display);
|
||||||
wl_registry_add_listener(touch->registry, ®istry_listener, touch);
|
wl_registry_add_listener(touch->registry, ®istry_listener, touch);
|
||||||
wl_display_dispatch(touch->display);
|
wl_display_dispatch(touch->display);
|
||||||
|
|
@ -421,59 +319,30 @@ touch_create(int width, int height)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!touch->wm_base) {
|
touch->width = width;
|
||||||
fprintf(stderr, "xdg-shell required!\n");
|
touch->height = height;
|
||||||
exit(1);
|
touch->surface = wl_compositor_create_surface(touch->compositor);
|
||||||
|
touch->shell_surface = wl_shell_get_shell_surface(touch->shell,
|
||||||
|
touch->surface);
|
||||||
|
create_shm_buffer(touch);
|
||||||
|
|
||||||
|
if (touch->shell_surface) {
|
||||||
|
wl_shell_surface_add_listener(touch->shell_surface,
|
||||||
|
&shell_surface_listener, touch);
|
||||||
|
wl_shell_surface_set_toplevel(touch->shell_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
touch->init_width = width;
|
wl_surface_set_user_data(touch->surface, touch);
|
||||||
touch->init_height = height;
|
wl_shell_surface_set_title(touch->shell_surface, "simple-touch");
|
||||||
touch->surface = wl_compositor_create_surface(touch->compositor);
|
|
||||||
|
|
||||||
touch->xdg_surface =
|
memset(touch->data, 64, width * height * 4);
|
||||||
xdg_wm_base_get_xdg_surface(touch->wm_base, touch->surface);
|
wl_surface_attach(touch->surface, touch->buffer, 0, 0);
|
||||||
assert(touch->xdg_surface);
|
wl_surface_damage(touch->surface, 0, 0, width, height);
|
||||||
|
|
||||||
xdg_surface_add_listener(touch->xdg_surface, &xdg_surface_listener, touch);
|
|
||||||
|
|
||||||
touch->xdg_toplevel = xdg_surface_get_toplevel(touch->xdg_surface);
|
|
||||||
assert(touch->xdg_toplevel);
|
|
||||||
xdg_toplevel_add_listener(touch->xdg_toplevel,
|
|
||||||
&xdg_toplevel_listener, touch);
|
|
||||||
xdg_toplevel_set_title(touch->xdg_toplevel, "simple-touch");
|
|
||||||
xdg_toplevel_set_app_id(touch->xdg_toplevel, "simple-touch");
|
|
||||||
touch->wait_for_configure = true;
|
|
||||||
touch->needs_buffer_update = false;
|
|
||||||
wl_surface_commit(touch->surface);
|
wl_surface_commit(touch->surface);
|
||||||
|
|
||||||
touch->running = true;
|
|
||||||
|
|
||||||
return touch;
|
return touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_touch(struct touch *touch)
|
|
||||||
{
|
|
||||||
if (touch->buffer->buffer)
|
|
||||||
wl_buffer_destroy(touch->buffer->buffer);
|
|
||||||
|
|
||||||
if (touch->xdg_toplevel)
|
|
||||||
xdg_toplevel_destroy(touch->xdg_toplevel);
|
|
||||||
if (touch->xdg_surface)
|
|
||||||
xdg_surface_destroy(touch->xdg_surface);
|
|
||||||
if (touch->wm_base)
|
|
||||||
xdg_wm_base_destroy(touch->wm_base);
|
|
||||||
if (touch->shm)
|
|
||||||
wl_shm_destroy(touch->shm);
|
|
||||||
if (touch->compositor)
|
|
||||||
wl_compositor_destroy(touch->compositor);
|
|
||||||
|
|
||||||
|
|
||||||
wl_surface_destroy(touch->surface);
|
|
||||||
free(touch->buffer);
|
|
||||||
free(touch);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
@ -482,9 +351,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
touch = touch_create(600, 500);
|
touch = touch_create(600, 500);
|
||||||
|
|
||||||
while (ret != -1 && touch->running)
|
while (ret != -1)
|
||||||
ret = wl_display_dispatch(touch->display);
|
ret = wl_display_dispatch(touch->display);
|
||||||
|
|
||||||
destroy_touch(touch);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(location = 0) in vec4 v_color;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
f_color = v_color;
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(std140, set = 0, binding = 0) uniform block {
|
|
||||||
uniform mat4 reflection;
|
|
||||||
uniform float offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(location = 0) in vec4 pos;
|
|
||||||
layout(location = 1) in vec4 color;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 v_color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_Position = reflection * (pos + vec4(offset, offset, 0.0, 0.0));
|
|
||||||
v_color = color;
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(location = 0) in vec4 vVaryingColor;
|
|
||||||
layout(location = 0) out vec4 f_color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
f_color = vVaryingColor;
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(std140, set = 0, binding = 0) uniform block {
|
|
||||||
uniform mat4 rotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(location = 0) in vec4 in_position;
|
|
||||||
layout(location = 1) in vec4 in_color;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 vVaryingColor;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_Position = rotation * in_position;
|
|
||||||
vVaryingColor = vec4(in_color.rgba);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2010 Kristian Høgsberg
|
* Copyright © 2010 Kristian Høgsberg
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -29,7 +28,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
@ -202,6 +200,8 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
|
|
||||||
render(smoke, surface);
|
render(smoke, surface);
|
||||||
|
|
||||||
|
window_damage(smoke->window, 0, 0, smoke->width, smoke->height);
|
||||||
|
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
|
|
||||||
widget_schedule_redraw(smoke->widget);
|
widget_schedule_redraw(smoke->widget);
|
||||||
|
|
@ -261,7 +261,7 @@ resize_handler(struct widget *widget,
|
||||||
{
|
{
|
||||||
struct smoke *smoke = data;
|
struct smoke *smoke = data;
|
||||||
|
|
||||||
/* Don't resize me */
|
/* Dont resize me */
|
||||||
widget_set_size(smoke->widget, smoke->width, smoke->height);
|
widget_set_size(smoke->widget, smoke->width, smoke->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,8 +274,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +284,6 @@ int main(int argc, char *argv[])
|
||||||
smoke.window = window_create(d);
|
smoke.window = window_create(d);
|
||||||
smoke.widget = window_add_widget(smoke.window, &smoke);
|
smoke.widget = window_add_widget(smoke.window, &smoke);
|
||||||
window_set_title(smoke.window, "smoke");
|
window_set_title(smoke.window, "smoke");
|
||||||
window_set_appid(smoke.window, "org.freedesktop.weston.smoke");
|
|
||||||
|
|
||||||
window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM);
|
window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM);
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,43 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Collabora Ltd.
|
* Copyright © 2013 Collabora Ltd.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
* to deal in the Software without restriction, including without limitation
|
* that the above copyright notice appear in all copies and that both that
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* copyright notice and this permission notice appear in supporting
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* Software.
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
*
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <wayland-util.h>
|
|
||||||
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
struct stacking_window {
|
|
||||||
struct stacking *stacking;
|
|
||||||
struct window *window;
|
|
||||||
struct widget *widget;
|
|
||||||
struct wl_list link;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stacking {
|
struct stacking {
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct wl_list windows;
|
struct window *root_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
close_handler(void *data);
|
|
||||||
static void
|
static void
|
||||||
button_handler(struct widget *widget,
|
button_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
|
|
@ -73,54 +58,29 @@ redraw_handler(struct widget *widget, void *data);
|
||||||
|
|
||||||
/* Iff parent_window is set, the new window will be transient. */
|
/* Iff parent_window is set, the new window will be transient. */
|
||||||
static struct window *
|
static struct window *
|
||||||
create_window(struct stacking *stacking, struct window *parent_window)
|
new_window(struct stacking *stacking, struct window *parent_window)
|
||||||
{
|
{
|
||||||
struct stacking_window *new_stacking_window;
|
|
||||||
struct window *new_window;
|
struct window *new_window;
|
||||||
struct widget *new_widget;
|
struct widget *new_widget;
|
||||||
|
|
||||||
new_stacking_window = xzalloc(sizeof *new_stacking_window);
|
|
||||||
new_stacking_window->stacking = stacking;
|
|
||||||
new_window = window_create(stacking->display);
|
new_window = window_create(stacking->display);
|
||||||
new_stacking_window->window = new_window;
|
|
||||||
window_set_parent(new_window, parent_window);
|
window_set_parent(new_window, parent_window);
|
||||||
|
|
||||||
new_widget = window_frame_create(new_window, new_window);
|
new_widget = window_frame_create(new_window, new_window);
|
||||||
new_stacking_window->widget = new_widget;
|
|
||||||
|
|
||||||
wl_list_insert(stacking->windows.prev, &new_stacking_window->link);
|
|
||||||
|
|
||||||
window_set_title(new_window, "Stacking Test");
|
window_set_title(new_window, "Stacking Test");
|
||||||
window_set_appid(new_window, "org.freedesktop.weston.stacking-test");
|
|
||||||
window_set_key_handler(new_window, key_handler);
|
window_set_key_handler(new_window, key_handler);
|
||||||
window_set_keyboard_focus_handler(new_window, keyboard_focus_handler);
|
window_set_keyboard_focus_handler(new_window, keyboard_focus_handler);
|
||||||
window_set_fullscreen_handler(new_window, fullscreen_handler);
|
window_set_fullscreen_handler(new_window, fullscreen_handler);
|
||||||
window_set_close_handler(new_window, close_handler);
|
|
||||||
widget_set_button_handler(new_widget, button_handler);
|
widget_set_button_handler(new_widget, button_handler);
|
||||||
widget_set_redraw_handler(new_widget, redraw_handler);
|
widget_set_redraw_handler(new_widget, redraw_handler);
|
||||||
window_set_user_data(new_window, new_stacking_window);
|
window_set_user_data(new_window, stacking);
|
||||||
|
|
||||||
window_schedule_resize(new_window, 300, 300);
|
window_schedule_resize(new_window, 300, 300);
|
||||||
|
|
||||||
return new_window;
|
return new_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_window(struct stacking_window *stacking_window)
|
|
||||||
{
|
|
||||||
struct stacking *stacking = stacking_window->stacking;
|
|
||||||
|
|
||||||
widget_destroy(stacking_window->widget);
|
|
||||||
window_destroy(stacking_window->window);
|
|
||||||
|
|
||||||
wl_list_remove(&stacking_window->link);
|
|
||||||
free(stacking_window);
|
|
||||||
|
|
||||||
if (wl_list_empty(&stacking->windows))
|
|
||||||
display_exit(stacking->display);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
show_popup_cb(void *data, struct input *input, int index)
|
show_popup_cb(void *data, struct input *input, int index)
|
||||||
{
|
{
|
||||||
|
|
@ -142,27 +102,18 @@ show_popup(struct stacking *stacking, struct input *input, uint32_t time,
|
||||||
show_popup_cb, entries, ARRAY_LENGTH(entries));
|
show_popup_cb, entries, ARRAY_LENGTH(entries));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
close_handler(void *data)
|
|
||||||
{
|
|
||||||
struct stacking_window *stacking_window = data;
|
|
||||||
|
|
||||||
destroy_window(stacking_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
button_handler(struct widget *widget,
|
button_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
uint32_t button,
|
uint32_t button,
|
||||||
enum wl_pointer_button_state state, void *data)
|
enum wl_pointer_button_state state, void *data)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct stacking *stacking = data;
|
||||||
struct stacking_window *stacking_window = window_get_user_data(window);
|
|
||||||
|
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case BTN_RIGHT:
|
case BTN_RIGHT:
|
||||||
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||||
show_popup(stacking_window->stacking, input, time,
|
show_popup(stacking, input, time,
|
||||||
widget_get_user_data(widget));
|
widget_get_user_data(widget));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -178,8 +129,7 @@ key_handler(struct window *window,
|
||||||
uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
|
uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct stacking_window *stacking_window = data;
|
struct stacking *stacking = data;
|
||||||
struct stacking *stacking = stacking_window->stacking;
|
|
||||||
|
|
||||||
if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
return;
|
return;
|
||||||
|
|
@ -195,24 +145,20 @@ key_handler(struct window *window,
|
||||||
|
|
||||||
case XKB_KEY_n:
|
case XKB_KEY_n:
|
||||||
/* New top-level window. */
|
/* New top-level window. */
|
||||||
create_window(stacking, NULL);
|
new_window(stacking, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XKB_KEY_p:
|
case XKB_KEY_p:
|
||||||
show_popup(stacking, input, time, window);
|
show_popup(stacking, input, time, window);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XKB_KEY_c:
|
|
||||||
destroy_window(stacking_window);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XKB_KEY_q:
|
case XKB_KEY_q:
|
||||||
display_exit(stacking->display);
|
exit (0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XKB_KEY_t:
|
case XKB_KEY_t:
|
||||||
/* New transient window. */
|
/* New transient window. */
|
||||||
create_window(stacking, window);
|
new_window(stacking, window);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -235,7 +181,7 @@ fullscreen_handler(struct window *window, void *data)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_string(cairo_t *cr,
|
draw_string(cairo_t *cr,
|
||||||
const char *fmt, ...) WL_PRINTF(2, 3);
|
const char *fmt, ...) __attribute__((format (gnu_printf, 2, 3)));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_string(cairo_t *cr,
|
draw_string(cairo_t *cr,
|
||||||
|
|
@ -249,7 +195,7 @@ draw_string(cairo_t *cr,
|
||||||
|
|
||||||
cairo_save(cr);
|
cairo_save(cr);
|
||||||
|
|
||||||
cairo_select_font_face(cr, "sans-serif",
|
cairo_select_font_face(cr, "sans",
|
||||||
CAIRO_FONT_SLANT_NORMAL,
|
CAIRO_FONT_SLANT_NORMAL,
|
||||||
CAIRO_FONT_WEIGHT_NORMAL);
|
CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
cairo_set_font_size(cr, 14);
|
cairo_set_font_size(cr, 14);
|
||||||
|
|
@ -297,21 +243,26 @@ set_window_background_colour(cairo_t *cr, struct window *window)
|
||||||
static void
|
static void
|
||||||
redraw_handler(struct widget *widget, void *data)
|
redraw_handler(struct widget *widget, void *data)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct window *window;
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
widget_get_allocation(widget, &allocation);
|
||||||
|
window = widget_get_user_data(widget);
|
||||||
|
|
||||||
cr = widget_cairo_create(widget);
|
cr = widget_cairo_create(widget);
|
||||||
cairo_translate(cr, allocation.x, allocation.y);
|
cairo_translate(cr, allocation.x, allocation.y);
|
||||||
|
|
||||||
/* Draw background. */
|
/* Draw background. */
|
||||||
|
cairo_push_group(cr);
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||||
set_window_background_colour(cr, window);
|
set_window_background_colour(cr, window);
|
||||||
cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
|
cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
|
||||||
cairo_fill(cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
|
cairo_pop_group_to_source(cr);
|
||||||
|
cairo_paint(cr);
|
||||||
|
|
||||||
/* Print the instructions. */
|
/* Print the instructions. */
|
||||||
cairo_move_to(cr, 5, 15);
|
cairo_move_to(cr, 5, 15);
|
||||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||||
|
|
@ -323,8 +274,7 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
"Transient? %u\n"
|
"Transient? %u\n"
|
||||||
"Keys: (f)ullscreen, (m)aximize,\n"
|
"Keys: (f)ullscreen, (m)aximize,\n"
|
||||||
" (n)ew window, (p)opup,\n"
|
" (n)ew window, (p)opup,\n"
|
||||||
" (c)lose, (q)uit,\n"
|
" (q)uit, (t)ransient window\n",
|
||||||
" (t)ransient window\n",
|
|
||||||
window, window_is_fullscreen(window),
|
window, window_is_fullscreen(window),
|
||||||
window_is_maximized(window), window_get_parent(window) ? 1 : 0);
|
window_is_maximized(window), window_get_parent(window) ? 1 : 0);
|
||||||
|
|
||||||
|
|
@ -335,27 +285,26 @@ int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct stacking stacking;
|
struct stacking stacking;
|
||||||
struct stacking_window *stacking_window, *tmp;
|
|
||||||
|
|
||||||
memset(&stacking, 0, sizeof stacking);
|
memset(&stacking, 0, sizeof stacking);
|
||||||
wl_list_init(&stacking.windows);
|
|
||||||
|
#ifdef HAVE_PANGO
|
||||||
|
g_type_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
stacking.display = display_create(&argc, argv);
|
stacking.display = display_create(&argc, argv);
|
||||||
if (stacking.display == NULL) {
|
if (stacking.display == NULL) {
|
||||||
fprintf(stderr, "Failed to create display: %s\n",
|
fprintf(stderr, "Failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
display_set_user_data(stacking.display, &stacking);
|
display_set_user_data(stacking.display, &stacking);
|
||||||
|
|
||||||
create_window(&stacking, NULL);
|
stacking.root_window = new_window(&stacking, NULL);
|
||||||
|
|
||||||
display_run(stacking.display);
|
display_run(stacking.display);
|
||||||
|
|
||||||
wl_list_for_each_safe(stacking_window, tmp, &stacking.windows, link)
|
window_destroy(stacking.root_window);
|
||||||
destroy_window(stacking_window);
|
|
||||||
|
|
||||||
display_destroy(stacking.display);
|
display_destroy(stacking.display);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,23 @@
|
||||||
* Copyright © 2011 Benjamin Franzke
|
* Copyright © 2011 Benjamin Franzke
|
||||||
* Copyright © 2012-2013 Collabora, Ltd.
|
* Copyright © 2012-2013 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -32,7 +31,6 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
@ -42,9 +40,6 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -56,8 +51,8 @@
|
||||||
|
|
||||||
static int32_t option_red_mode;
|
static int32_t option_red_mode;
|
||||||
static int32_t option_triangle_mode;
|
static int32_t option_triangle_mode;
|
||||||
static bool option_no_triangle;
|
static int32_t option_no_triangle;
|
||||||
static bool option_help;
|
static int32_t option_help;
|
||||||
|
|
||||||
static const struct weston_option options[] = {
|
static const struct weston_option options[] = {
|
||||||
{ WESTON_OPTION_INTEGER, "red-mode", 'r', &option_red_mode },
|
{ WESTON_OPTION_INTEGER, "red-mode", 'r', &option_red_mode },
|
||||||
|
|
@ -218,7 +213,7 @@ egl_state_create(struct wl_display *display)
|
||||||
EGLint major, minor, n;
|
EGLint major, minor, n;
|
||||||
EGLBoolean ret;
|
EGLBoolean ret;
|
||||||
|
|
||||||
egl = zalloc(sizeof *egl);
|
egl = calloc(1, sizeof *egl);
|
||||||
assert(egl);
|
assert(egl);
|
||||||
|
|
||||||
egl->dpy =
|
egl->dpy =
|
||||||
|
|
@ -296,7 +291,7 @@ create_shader(const char *source, GLenum shader_type)
|
||||||
char log[1000];
|
char log[1000];
|
||||||
GLsizei len;
|
GLsizei len;
|
||||||
glGetShaderInfoLog(shader, 1000, &len, log);
|
glGetShaderInfoLog(shader, 1000, &len, log);
|
||||||
fprintf(stderr, "Error: compiling %s: %.*s\n",
|
fprintf(stderr, "Error: compiling %s: %*s\n",
|
||||||
shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
||||||
len, log);
|
len, log);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -325,7 +320,7 @@ triangle_init_gl(struct triangle_gl_state *trigl)
|
||||||
char log[1000];
|
char log[1000];
|
||||||
GLsizei len;
|
GLsizei len;
|
||||||
glGetProgramInfoLog(program, 1000, &len, log);
|
glGetProgramInfoLog(program, 1000, &len, log);
|
||||||
fprintf(stderr, "Error: linking:\n%.*s\n", len, log);
|
fprintf(stderr, "Error: linking:\n%*s\n", len, log);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,7 +496,8 @@ triangle_create(struct window *window, struct egl_state *egl)
|
||||||
{
|
{
|
||||||
struct triangle *tri;
|
struct triangle *tri;
|
||||||
|
|
||||||
tri = xzalloc(sizeof *tri);
|
tri = xmalloc(sizeof *tri);
|
||||||
|
memset(tri, 0, sizeof *tri);
|
||||||
|
|
||||||
tri->egl = egl;
|
tri->egl = egl;
|
||||||
tri->widget = window_add_subsurface(window, tri,
|
tri->widget = window_add_subsurface(window, tri,
|
||||||
|
|
@ -519,8 +515,7 @@ static void
|
||||||
triangle_destroy(struct triangle *tri)
|
triangle_destroy(struct triangle *tri)
|
||||||
{
|
{
|
||||||
if (tri->egl_surface)
|
if (tri->egl_surface)
|
||||||
weston_platform_destroy_egl_surface(tri->egl->dpy,
|
eglDestroySurface(tri->egl->dpy, tri->egl_surface);
|
||||||
tri->egl_surface);
|
|
||||||
|
|
||||||
if (tri->egl_window)
|
if (tri->egl_window)
|
||||||
wl_egl_window_destroy(tri->egl_window);
|
wl_egl_window_destroy(tri->egl_window);
|
||||||
|
|
@ -723,7 +718,8 @@ demoapp_create(struct display *display)
|
||||||
{
|
{
|
||||||
struct demoapp *app;
|
struct demoapp *app;
|
||||||
|
|
||||||
app = xzalloc(sizeof *app);
|
app = xmalloc(sizeof *app);
|
||||||
|
memset(app, 0, sizeof *app);
|
||||||
|
|
||||||
app->egl = egl_state_create(display_get_display(display));
|
app->egl = egl_state_create(display_get_display(display));
|
||||||
|
|
||||||
|
|
@ -733,8 +729,6 @@ demoapp_create(struct display *display)
|
||||||
app->window = window_create(app->display);
|
app->window = window_create(app->display);
|
||||||
app->widget = window_frame_create(app->window, app);
|
app->widget = window_frame_create(app->window, app);
|
||||||
window_set_title(app->window, "Wayland Sub-surface Demo");
|
window_set_title(app->window, "Wayland Sub-surface Demo");
|
||||||
window_set_appid(app->window,
|
|
||||||
"org.freedesktop.weston.wayland-sub-surface-demo");
|
|
||||||
|
|
||||||
window_set_key_handler(app->window, key_handler);
|
window_set_key_handler(app->window, key_handler);
|
||||||
window_set_user_data(app->window, app);
|
window_set_user_data(app->window, app);
|
||||||
|
|
@ -791,8 +785,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
display = display_create(&argc, argv);
|
display = display_create(&argc, argv);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
254
clients/tablet.c
|
|
@ -1,254 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright © 2014 Lyude
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and
|
|
||||||
* its documentation for any purpose is hereby granted without fee, provided
|
|
||||||
* that the above copyright notice appear in all copies and that both that
|
|
||||||
* copyright notice and this permission notice appear in supporting
|
|
||||||
* documentation, and that the name of the copyright holders not be used in
|
|
||||||
* advertising or publicity pertaining to distribution of the software
|
|
||||||
* without specific, written prior permission. The copyright holders make
|
|
||||||
* no representations about the suitability of this software for any
|
|
||||||
* purpose. It is provided "as is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
||||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
||||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
|
||||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <cairo.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
|
||||||
#include <wayland-client.h>
|
|
||||||
|
|
||||||
#include "window.h"
|
|
||||||
#include "tablet-unstable-v2-client-protocol.h"
|
|
||||||
|
|
||||||
struct display *display;
|
|
||||||
struct window *window;
|
|
||||||
struct widget *widget;
|
|
||||||
|
|
||||||
cairo_surface_t *draw_buffer;
|
|
||||||
|
|
||||||
int old_x, old_y;
|
|
||||||
int current_x, current_y;
|
|
||||||
enum zwp_tablet_tool_v2_type tool_type;
|
|
||||||
|
|
||||||
bool tablet_is_down;
|
|
||||||
|
|
||||||
double current_pressure;
|
|
||||||
|
|
||||||
#define WL_TABLET_AXIS_MAX 65535
|
|
||||||
|
|
||||||
static void
|
|
||||||
redraw_handler(struct widget *widget, void *data)
|
|
||||||
{
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *window_cr, *drawing_cr;
|
|
||||||
struct rectangle allocation;
|
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
|
||||||
|
|
||||||
surface = window_get_surface(window);
|
|
||||||
|
|
||||||
/* Setup the background */
|
|
||||||
window_cr = cairo_create(surface);
|
|
||||||
cairo_set_operator(window_cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_rectangle(window_cr,
|
|
||||||
allocation.x,
|
|
||||||
allocation.y,
|
|
||||||
allocation.width,
|
|
||||||
allocation.height);
|
|
||||||
cairo_set_source_rgba(window_cr, 0, 0, 0, 0.8);
|
|
||||||
cairo_fill(window_cr);
|
|
||||||
|
|
||||||
/* Update the drawing buffer */
|
|
||||||
if (tablet_is_down) {
|
|
||||||
if (old_x != -1 && old_y != -1) {
|
|
||||||
drawing_cr = cairo_create(draw_buffer);
|
|
||||||
if (tool_type == ZWP_TABLET_TOOL_V2_TYPE_PEN) {
|
|
||||||
cairo_set_source_rgb(drawing_cr, 1, 1, 1);
|
|
||||||
cairo_set_line_width(drawing_cr,
|
|
||||||
current_pressure /
|
|
||||||
WL_TABLET_AXIS_MAX * 7 + 1);
|
|
||||||
} else if (tool_type == ZWP_TABLET_TOOL_V2_TYPE_ERASER) {
|
|
||||||
cairo_set_operator(drawing_cr, CAIRO_OPERATOR_CLEAR);
|
|
||||||
cairo_set_source_rgb(drawing_cr, 0, 0, 0);
|
|
||||||
cairo_set_line_width(drawing_cr,
|
|
||||||
current_pressure /
|
|
||||||
WL_TABLET_AXIS_MAX * 30 + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_set_line_cap(drawing_cr, CAIRO_LINE_CAP_ROUND);
|
|
||||||
|
|
||||||
cairo_translate(drawing_cr,
|
|
||||||
-allocation.x,
|
|
||||||
-allocation.y);
|
|
||||||
cairo_move_to(drawing_cr, old_x, old_y);
|
|
||||||
cairo_line_to(drawing_cr, current_x, current_y);
|
|
||||||
cairo_stroke(drawing_cr);
|
|
||||||
|
|
||||||
cairo_destroy(drawing_cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
old_x = current_x;
|
|
||||||
old_y = current_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Squash the drawing buffer onto the window's buffer */
|
|
||||||
cairo_set_source_surface(window_cr,
|
|
||||||
draw_buffer,
|
|
||||||
allocation.x,
|
|
||||||
allocation.y);
|
|
||||||
cairo_set_operator(window_cr, CAIRO_OPERATOR_ADD);
|
|
||||||
cairo_rectangle(window_cr,
|
|
||||||
allocation.x,
|
|
||||||
allocation.y,
|
|
||||||
allocation.width,
|
|
||||||
allocation.height);
|
|
||||||
cairo_clip(window_cr);
|
|
||||||
cairo_paint(window_cr);
|
|
||||||
|
|
||||||
cairo_destroy(window_cr);
|
|
||||||
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
resize_handler(struct widget *widget,
|
|
||||||
int32_t width, int32_t height,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
cairo_surface_t *tmp_buffer;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
tmp_buffer = draw_buffer;
|
|
||||||
draw_buffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
|
|
||||||
width, height);
|
|
||||||
cr = cairo_create(draw_buffer);
|
|
||||||
cairo_set_source_rgba(cr, 0, 0, 0, 0);
|
|
||||||
cairo_rectangle(cr, 0, 0, width, height);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
if (tmp_buffer) {
|
|
||||||
cairo_set_source_surface(cr, tmp_buffer, 0, 0);
|
|
||||||
cairo_rectangle(cr, 0, 0, width, height);
|
|
||||||
cairo_clip(cr);
|
|
||||||
cairo_paint(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_destroy(cr);
|
|
||||||
|
|
||||||
cairo_surface_destroy(tmp_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
proximity_in_handler(struct widget *widget, struct tablet_tool *tool,
|
|
||||||
struct tablet *tablet, void *data)
|
|
||||||
{
|
|
||||||
tool_type = tablet_tool_get_type(tool);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
pressure_handler(struct widget *widget, struct tablet_tool *tool,
|
|
||||||
uint32_t pressure, void *data)
|
|
||||||
{
|
|
||||||
current_pressure = pressure;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
tablet_motion_handler(struct widget *widget, struct tablet_tool *tool,
|
|
||||||
float x, float y, void *data)
|
|
||||||
{
|
|
||||||
int cursor;
|
|
||||||
|
|
||||||
current_x = x;
|
|
||||||
current_y = y;
|
|
||||||
|
|
||||||
if (tablet_is_down) {
|
|
||||||
widget_schedule_redraw(widget);
|
|
||||||
cursor = CURSOR_HAND1;
|
|
||||||
} else {
|
|
||||||
cursor = CURSOR_LEFT_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tablet_down_handler(struct widget *widget, struct tablet_tool *tool, void *data)
|
|
||||||
{
|
|
||||||
tablet_is_down = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tablet_up_handler(struct widget *widget, struct tablet_tool *tool, void *data)
|
|
||||||
{
|
|
||||||
tablet_is_down = false;
|
|
||||||
old_x = -1;
|
|
||||||
old_y = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_globals(void)
|
|
||||||
{
|
|
||||||
window = window_create(display);
|
|
||||||
widget = window_frame_create(window, NULL);
|
|
||||||
window_set_title(window, "Wayland Tablet Demo");
|
|
||||||
old_x = -1;
|
|
||||||
old_y = -1;
|
|
||||||
|
|
||||||
widget_set_tablet_tool_axis_handlers(widget,
|
|
||||||
tablet_motion_handler,
|
|
||||||
pressure_handler,
|
|
||||||
NULL, NULL,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
widget_set_tablet_tool_down_handler(widget, tablet_down_handler);
|
|
||||||
widget_set_tablet_tool_up_handler(widget, tablet_up_handler);
|
|
||||||
widget_set_tablet_tool_proximity_handlers(widget,
|
|
||||||
proximity_in_handler,
|
|
||||||
NULL);
|
|
||||||
widget_set_redraw_handler(widget, redraw_handler);
|
|
||||||
widget_set_resize_handler(widget, resize_handler);
|
|
||||||
|
|
||||||
widget_schedule_resize(widget, 1000, 800);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cleanup(void)
|
|
||||||
{
|
|
||||||
widget_destroy(widget);
|
|
||||||
window_destroy(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
display = display_create(&argc, argv);
|
|
||||||
if (display == NULL) {
|
|
||||||
fprintf(stderr, "failed to create display: %m\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_globals();
|
|
||||||
|
|
||||||
display_run(display);
|
|
||||||
|
|
||||||
cleanup();
|
|
||||||
|
|
||||||
display_destroy(display);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +1,27 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -39,26 +37,21 @@
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
#include <libweston/config-parser.h>
|
#include "../shared/config-parser.h"
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
static bool option_fullscreen;
|
static int option_fullscreen;
|
||||||
static bool option_maximize;
|
|
||||||
static char *option_font;
|
static char *option_font;
|
||||||
static int option_font_size;
|
static int option_font_size;
|
||||||
static char *option_term;
|
static char *option_term;
|
||||||
static char *option_shell;
|
static char *option_shell;
|
||||||
|
|
||||||
static struct wl_list terminal_list;
|
static struct wl_list terminal_list;
|
||||||
struct sigaction oldact;
|
|
||||||
|
|
||||||
static struct terminal *
|
static struct terminal *
|
||||||
terminal_create(struct display *display);
|
terminal_create(struct display *display);
|
||||||
|
|
@ -128,7 +121,6 @@ init_state_machine(struct utf8_state_machine *machine)
|
||||||
machine->state = utf8state_start;
|
machine->state = utf8state_start;
|
||||||
machine->len = 0;
|
machine->len = 0;
|
||||||
machine->s.ch = 0;
|
machine->s.ch = 0;
|
||||||
machine->unicode = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum utf8_state
|
static enum utf8_state
|
||||||
|
|
@ -140,28 +132,28 @@ utf8_next_char(struct utf8_state_machine *machine, unsigned char c)
|
||||||
case utf8state_reject:
|
case utf8state_reject:
|
||||||
machine->s.ch = 0;
|
machine->s.ch = 0;
|
||||||
machine->len = 0;
|
machine->len = 0;
|
||||||
if (c == 0xC0 || c == 0xC1) {
|
if(c == 0xC0 || c == 0xC1) {
|
||||||
/* overlong encoding, reject */
|
/* overlong encoding, reject */
|
||||||
machine->state = utf8state_reject;
|
machine->state = utf8state_reject;
|
||||||
} else if ((c & 0x80) == 0) {
|
} else if((c & 0x80) == 0) {
|
||||||
/* single byte, accept */
|
/* single byte, accept */
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->state = utf8state_accept;
|
machine->state = utf8state_accept;
|
||||||
machine->unicode = c;
|
machine->unicode = c;
|
||||||
} else if ((c & 0xC0) == 0x80) {
|
} else if((c & 0xC0) == 0x80) {
|
||||||
/* parser out of sync, ignore byte */
|
/* parser out of sync, ignore byte */
|
||||||
machine->state = utf8state_start;
|
machine->state = utf8state_start;
|
||||||
} else if ((c & 0xE0) == 0xC0) {
|
} else if((c & 0xE0) == 0xC0) {
|
||||||
/* start of two byte sequence */
|
/* start of two byte sequence */
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->state = utf8state_expect1;
|
machine->state = utf8state_expect1;
|
||||||
machine->unicode = c & 0x1f;
|
machine->unicode = c & 0x1f;
|
||||||
} else if ((c & 0xF0) == 0xE0) {
|
} else if((c & 0xF0) == 0xE0) {
|
||||||
/* start of three byte sequence */
|
/* start of three byte sequence */
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->state = utf8state_expect2;
|
machine->state = utf8state_expect2;
|
||||||
machine->unicode = c & 0x0f;
|
machine->unicode = c & 0x0f;
|
||||||
} else if ((c & 0xF8) == 0xF0) {
|
} else if((c & 0xF8) == 0xF0) {
|
||||||
/* start of four byte sequence */
|
/* start of four byte sequence */
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->state = utf8state_expect3;
|
machine->state = utf8state_expect3;
|
||||||
|
|
@ -174,7 +166,7 @@ utf8_next_char(struct utf8_state_machine *machine, unsigned char c)
|
||||||
case utf8state_expect3:
|
case utf8state_expect3:
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->unicode = (machine->unicode << 6) | (c & 0x3f);
|
machine->unicode = (machine->unicode << 6) | (c & 0x3f);
|
||||||
if ((c & 0xC0) == 0x80) {
|
if((c & 0xC0) == 0x80) {
|
||||||
/* all good, continue */
|
/* all good, continue */
|
||||||
machine->state = utf8state_expect2;
|
machine->state = utf8state_expect2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -185,7 +177,7 @@ utf8_next_char(struct utf8_state_machine *machine, unsigned char c)
|
||||||
case utf8state_expect2:
|
case utf8state_expect2:
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->unicode = (machine->unicode << 6) | (c & 0x3f);
|
machine->unicode = (machine->unicode << 6) | (c & 0x3f);
|
||||||
if ((c & 0xC0) == 0x80) {
|
if((c & 0xC0) == 0x80) {
|
||||||
/* all good, continue */
|
/* all good, continue */
|
||||||
machine->state = utf8state_expect1;
|
machine->state = utf8state_expect1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -196,7 +188,7 @@ utf8_next_char(struct utf8_state_machine *machine, unsigned char c)
|
||||||
case utf8state_expect1:
|
case utf8state_expect1:
|
||||||
machine->s.byte[machine->len++] = c;
|
machine->s.byte[machine->len++] = c;
|
||||||
machine->unicode = (machine->unicode << 6) | (c & 0x3f);
|
machine->unicode = (machine->unicode << 6) | (c & 0x3f);
|
||||||
if ((c & 0xC0) == 0x80) {
|
if((c & 0xC0) == 0x80) {
|
||||||
/* all good, accept */
|
/* all good, accept */
|
||||||
machine->state = utf8state_accept;
|
machine->state = utf8state_accept;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -484,7 +476,6 @@ struct terminal {
|
||||||
int selection_start_row, selection_start_col;
|
int selection_start_row, selection_start_col;
|
||||||
int selection_end_row, selection_end_col;
|
int selection_end_row, selection_end_col;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
int pace_pipe;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create default tab stops, every 8 characters */
|
/* Create default tab stops, every 8 characters */
|
||||||
|
|
@ -667,7 +658,7 @@ terminal_scroll_window(struct terminal *terminal, int d)
|
||||||
// scrolling range is inclusive
|
// scrolling range is inclusive
|
||||||
window_height = terminal->margin_bottom - terminal->margin_top + 1;
|
window_height = terminal->margin_bottom - terminal->margin_top + 1;
|
||||||
d = d % (window_height + 1);
|
d = d % (window_height + 1);
|
||||||
if (d < 0) {
|
if(d < 0) {
|
||||||
d = 0 - d;
|
d = 0 - d;
|
||||||
to_row = terminal->margin_bottom;
|
to_row = terminal->margin_bottom;
|
||||||
from_row = terminal->margin_bottom - d;
|
from_row = terminal->margin_bottom - d;
|
||||||
|
|
@ -708,7 +699,7 @@ terminal_scroll_window(struct terminal *terminal, int d)
|
||||||
static void
|
static void
|
||||||
terminal_scroll(struct terminal *terminal, int d)
|
terminal_scroll(struct terminal *terminal, int d)
|
||||||
{
|
{
|
||||||
if (terminal->margin_top == 0 && terminal->margin_bottom == terminal->height - 1)
|
if(terminal->margin_top == 0 && terminal->margin_bottom == terminal->height - 1)
|
||||||
terminal_scroll_buffer(terminal, d);
|
terminal_scroll_buffer(terminal, d);
|
||||||
else
|
else
|
||||||
terminal_scroll_window(terminal, d);
|
terminal_scroll_window(terminal, d);
|
||||||
|
|
@ -864,13 +855,9 @@ resize_handler(struct widget *widget,
|
||||||
struct terminal *terminal = data;
|
struct terminal *terminal = data;
|
||||||
int32_t columns, rows, m;
|
int32_t columns, rows, m;
|
||||||
|
|
||||||
if (terminal->pace_pipe >= 0) {
|
|
||||||
close(terminal->pace_pipe);
|
|
||||||
terminal->pace_pipe = -1;
|
|
||||||
}
|
|
||||||
m = 2 * terminal->margin;
|
m = 2 * terminal->margin;
|
||||||
columns = (int32_t) round((width - m) / terminal->average_width);
|
columns = (width - m) / (int32_t) terminal->average_width;
|
||||||
rows = (int32_t) round((height - m) / terminal->extents.height);
|
rows = (height - m) / (int32_t) terminal->extents.height;
|
||||||
|
|
||||||
if (!window_is_fullscreen(terminal->window) &&
|
if (!window_is_fullscreen(terminal->window) &&
|
||||||
!window_is_maximized(terminal->window)) {
|
!window_is_maximized(terminal->window)) {
|
||||||
|
|
@ -953,7 +940,7 @@ terminal_send_selection(struct terminal *terminal, int fd)
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (row = terminal->selection_start_row; row < terminal->height; row++) {
|
for (row = 0; row < terminal->height; row++) {
|
||||||
p_row = terminal_get_row(terminal, row);
|
p_row = terminal_get_row(terminal, row);
|
||||||
for (col = 0; col < terminal->width; col++) {
|
for (col = 0; col < terminal->width; col++) {
|
||||||
if (p_row[col].ch == 0x200B) /* space glyph */
|
if (p_row[col].ch == 0x200B) /* space glyph */
|
||||||
|
|
@ -1125,9 +1112,9 @@ redraw_handler(struct widget *widget, void *data)
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip space glyph (RLE) we use as a placeholder of
|
/* skip space glyph (RLE) we use as a placeholder of
|
||||||
the right half of a double-width character,
|
the right half of a double-width character,
|
||||||
because RLE is not available in every font. */
|
because RLE is not available in every font. */
|
||||||
if (p_row[col].ch == 0x200B)
|
if (p_row[col].ch == 0x200B)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -1307,8 +1294,6 @@ handle_osc(struct terminal *terminal)
|
||||||
break;
|
break;
|
||||||
case 7: /* shell cwd as uri */
|
case 7: /* shell cwd as uri */
|
||||||
break;
|
break;
|
||||||
case 777: /* Desktop notifications */
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown OSC escape code %d, text %s\n",
|
fprintf(stderr, "Unknown OSC escape code %d, text %s\n",
|
||||||
code, p);
|
code, p);
|
||||||
|
|
@ -1345,12 +1330,12 @@ handle_escape(struct terminal *terminal)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case '@': /* ICH - Insert <count> blank characters */
|
case '@': /* ICH */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
terminal_shift_line(terminal, count);
|
terminal_shift_line(terminal, count);
|
||||||
break;
|
break;
|
||||||
case 'A': /* CUU - Move cursor up <count> rows */
|
case 'A': /* CUU */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (terminal->row - count >= terminal->margin_top)
|
if (terminal->row - count >= terminal->margin_top)
|
||||||
|
|
@ -1358,7 +1343,7 @@ handle_escape(struct terminal *terminal)
|
||||||
else
|
else
|
||||||
terminal->row = terminal->margin_top;
|
terminal->row = terminal->margin_top;
|
||||||
break;
|
break;
|
||||||
case 'B': /* CUD - Move cursor down <count> rows */
|
case 'B': /* CUD */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (terminal->row + count <= terminal->margin_bottom)
|
if (terminal->row + count <= terminal->margin_bottom)
|
||||||
|
|
@ -1366,7 +1351,7 @@ handle_escape(struct terminal *terminal)
|
||||||
else
|
else
|
||||||
terminal->row = terminal->margin_bottom;
|
terminal->row = terminal->margin_bottom;
|
||||||
break;
|
break;
|
||||||
case 'C': /* CUF - Move cursor right by <count> columns */
|
case 'C': /* CUF */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if ((terminal->column + count) < terminal->width)
|
if ((terminal->column + count) < terminal->width)
|
||||||
|
|
@ -1374,7 +1359,7 @@ handle_escape(struct terminal *terminal)
|
||||||
else
|
else
|
||||||
terminal->column = terminal->width - 1;
|
terminal->column = terminal->width - 1;
|
||||||
break;
|
break;
|
||||||
case 'D': /* CUB - Move cursor left <count> columns */
|
case 'D': /* CUB */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if ((terminal->column - count) >= 0)
|
if ((terminal->column - count) >= 0)
|
||||||
|
|
@ -1382,7 +1367,7 @@ handle_escape(struct terminal *terminal)
|
||||||
else
|
else
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
break;
|
break;
|
||||||
case 'E': /* CNL - Move cursor down <count> rows, to column 1 */
|
case 'E': /* CNL */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (terminal->row + count <= terminal->margin_bottom)
|
if (terminal->row + count <= terminal->margin_bottom)
|
||||||
terminal->row += count;
|
terminal->row += count;
|
||||||
|
|
@ -1390,7 +1375,7 @@ handle_escape(struct terminal *terminal)
|
||||||
terminal->row = terminal->margin_bottom;
|
terminal->row = terminal->margin_bottom;
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
break;
|
break;
|
||||||
case 'F': /* CPL - Move cursour up <count> rows, to column 1 */
|
case 'F': /* CPL */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (terminal->row - count >= terminal->margin_top)
|
if (terminal->row - count >= terminal->margin_top)
|
||||||
terminal->row -= count;
|
terminal->row -= count;
|
||||||
|
|
@ -1398,14 +1383,14 @@ handle_escape(struct terminal *terminal)
|
||||||
terminal->row = terminal->margin_top;
|
terminal->row = terminal->margin_top;
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
break;
|
break;
|
||||||
case 'G': /* CHA - Move cursor to column <y> in current row */
|
case 'G': /* CHA */
|
||||||
y = set[0] ? args[0] : 1;
|
y = set[0] ? args[0] : 1;
|
||||||
y = y <= 0 ? 1 : y > terminal->width ? terminal->width : y;
|
y = y <= 0 ? 1 : y > terminal->width ? terminal->width : y;
|
||||||
|
|
||||||
terminal->column = y - 1;
|
terminal->column = y - 1;
|
||||||
break;
|
break;
|
||||||
case 'f': /* HVP - Move cursor to <x, y> */
|
case 'f': /* HVP */
|
||||||
case 'H': /* CUP - Move cursor to <x, y> (origin at 1,1) */
|
case 'H': /* CUP */
|
||||||
x = (set[1] ? args[1] : 1) - 1;
|
x = (set[1] ? args[1] : 1) - 1;
|
||||||
x = x < 0 ? 0 :
|
x = x < 0 ? 0 :
|
||||||
(x >= terminal->width ? terminal->width - 1 : x);
|
(x >= terminal->width ? terminal->width - 1 : x);
|
||||||
|
|
@ -1432,7 +1417,7 @@ handle_escape(struct terminal *terminal)
|
||||||
}
|
}
|
||||||
terminal->column--;
|
terminal->column--;
|
||||||
break;
|
break;
|
||||||
case 'J': /* ED - Erase display */
|
case 'J': /* ED */
|
||||||
row = terminal_get_row(terminal, terminal->row);
|
row = terminal_get_row(terminal, terminal->row);
|
||||||
attr_row = terminal_get_attr_row(terminal, terminal->row);
|
attr_row = terminal_get_attr_row(terminal, terminal->row);
|
||||||
if (!set[0] || args[0] == 0 || args[0] > 2) {
|
if (!set[0] || args[0] == 0 || args[0] > 2) {
|
||||||
|
|
@ -1461,7 +1446,7 @@ handle_escape(struct terminal *terminal)
|
||||||
terminal->end - terminal->start);
|
terminal->end - terminal->start);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'K': /* EL - Erase line */
|
case 'K': /* EL */
|
||||||
row = terminal_get_row(terminal, terminal->row);
|
row = terminal_get_row(terminal, terminal->row);
|
||||||
attr_row = terminal_get_attr_row(terminal, terminal->row);
|
attr_row = terminal_get_attr_row(terminal, terminal->row);
|
||||||
if (!set[0] || args[0] == 0 || args[0] > 2) {
|
if (!set[0] || args[0] == 0 || args[0] > 2) {
|
||||||
|
|
@ -1477,7 +1462,7 @@ handle_escape(struct terminal *terminal)
|
||||||
attr_init(attr_row, terminal->curr_attr, terminal->width);
|
attr_init(attr_row, terminal->curr_attr, terminal->width);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'L': /* IL - Insert <count> blank lines */
|
case 'L': /* IL */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (terminal->row >= terminal->margin_top &&
|
if (terminal->row >= terminal->margin_top &&
|
||||||
|
|
@ -1494,7 +1479,7 @@ handle_escape(struct terminal *terminal)
|
||||||
terminal->curr_attr, terminal->width);
|
terminal->curr_attr, terminal->width);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'M': /* DL - Delete <count> lines */
|
case 'M': /* DL */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if (terminal->row >= terminal->margin_top &&
|
if (terminal->row >= terminal->margin_top &&
|
||||||
|
|
@ -1509,7 +1494,7 @@ handle_escape(struct terminal *terminal)
|
||||||
0, terminal->data_pitch);
|
0, terminal->data_pitch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'P': /* DCH - Delete <count> characters on current line */
|
case 'P': /* DCH */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
terminal_shift_line(terminal, 0 - count);
|
terminal_shift_line(terminal, 0 - count);
|
||||||
|
|
@ -1520,7 +1505,7 @@ handle_escape(struct terminal *terminal)
|
||||||
case 'T': /* SD */
|
case 'T': /* SD */
|
||||||
terminal_scroll(terminal, 0 - (set[0] ? args[0] : 1));
|
terminal_scroll(terminal, 0 - (set[0] ? args[0] : 1));
|
||||||
break;
|
break;
|
||||||
case 'X': /* ECH - Erase <count> characters on current line */
|
case 'X': /* ECH */
|
||||||
count = set[0] ? args[0] : 1;
|
count = set[0] ? args[0] : 1;
|
||||||
if (count == 0) count = 1;
|
if (count == 0) count = 1;
|
||||||
if ((terminal->column + count) > terminal->width)
|
if ((terminal->column + count) > terminal->width)
|
||||||
|
|
@ -1539,7 +1524,7 @@ handle_escape(struct terminal *terminal)
|
||||||
}
|
}
|
||||||
terminal->column++;
|
terminal->column++;
|
||||||
break;
|
break;
|
||||||
case '`': /* HPA - Move cursor to <y> column in current row */
|
case '`': /* HPA */
|
||||||
y = set[0] ? args[0] : 1;
|
y = set[0] ? args[0] : 1;
|
||||||
y = y <= 0 ? 1 : y > terminal->width ? terminal->width : y;
|
y = y <= 0 ? 1 : y > terminal->width ? terminal->width : y;
|
||||||
|
|
||||||
|
|
@ -1553,34 +1538,34 @@ handle_escape(struct terminal *terminal)
|
||||||
handle_char(terminal, terminal->last_char);
|
handle_char(terminal, terminal->last_char);
|
||||||
terminal->last_char.byte[0] = 0;
|
terminal->last_char.byte[0] = 0;
|
||||||
break;
|
break;
|
||||||
case 'c': /* Primary DA - Answer "I am a VT102" */
|
case 'c': /* Primary DA */
|
||||||
terminal_write(terminal, "\e[?6c", 5);
|
terminal_write(terminal, "\e[?6c", 5);
|
||||||
break;
|
break;
|
||||||
case 'd': /* VPA - Move cursor to <x> row, current column */
|
case 'd': /* VPA */
|
||||||
x = set[0] ? args[0] : 1;
|
x = set[0] ? args[0] : 1;
|
||||||
x = x <= 0 ? 1 : x > terminal->height ? terminal->height : x;
|
x = x <= 0 ? 1 : x > terminal->height ? terminal->height : x;
|
||||||
|
|
||||||
terminal->row = x - 1;
|
terminal->row = x - 1;
|
||||||
break;
|
break;
|
||||||
case 'g': /* TBC - Clear tab stop(s) */
|
case 'g': /* TBC */
|
||||||
if (!set[0] || args[0] == 0) {
|
if (!set[0] || args[0] == 0) {
|
||||||
terminal->tab_ruler[terminal->column] = 0;
|
terminal->tab_ruler[terminal->column] = 0;
|
||||||
} else if (args[0] == 3) {
|
} else if (args[0] == 3) {
|
||||||
memset(terminal->tab_ruler, 0, terminal->width);
|
memset(terminal->tab_ruler, 0, terminal->width);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'h': /* SM - Set mode */
|
case 'h': /* SM */
|
||||||
for (i = 0; i < 10 && set[i]; i++) {
|
for(i = 0; i < 10 && set[i]; i++) {
|
||||||
handle_term_parameter(terminal, args[i], 1);
|
handle_term_parameter(terminal, args[i], 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'l': /* RM - Reset mode */
|
case 'l': /* RM */
|
||||||
for (i = 0; i < 10 && set[i]; i++) {
|
for(i = 0; i < 10 && set[i]; i++) {
|
||||||
handle_term_parameter(terminal, args[i], 0);
|
handle_term_parameter(terminal, args[i], 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'm': /* SGR - Set attributes */
|
case 'm': /* SGR */
|
||||||
for (i = 0; i < 10; i++) {
|
for(i = 0; i < 10; i++) {
|
||||||
if (i <= 7 && set[i] && set[i + 1] &&
|
if (i <= 7 && set[i] && set[i + 1] &&
|
||||||
set[i + 2] && args[i + 1] == 5)
|
set[i + 2] && args[i + 1] == 5)
|
||||||
{
|
{
|
||||||
|
|
@ -1592,9 +1577,9 @@ handle_escape(struct terminal *terminal)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (set[i]) {
|
if(set[i]) {
|
||||||
handle_sgr(terminal, args[i]);
|
handle_sgr(terminal, args[i]);
|
||||||
} else if (i == 0) {
|
} else if(i == 0) {
|
||||||
handle_sgr(terminal, 0);
|
handle_sgr(terminal, 0);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1602,7 +1587,7 @@ handle_escape(struct terminal *terminal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'n': /* DSR - Status report */
|
case 'n': /* DSR */
|
||||||
i = set[0] ? args[0] : 0;
|
i = set[0] ? args[0] : 0;
|
||||||
if (i == 0 || i == 5) {
|
if (i == 0 || i == 5) {
|
||||||
terminal_write(terminal, "\e[0n", 4);
|
terminal_write(terminal, "\e[0n", 4);
|
||||||
|
|
@ -1614,8 +1599,8 @@ handle_escape(struct terminal *terminal)
|
||||||
terminal_write(terminal, response, strlen(response));
|
terminal_write(terminal, response, strlen(response));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'r': /* DECSTBM - Set scrolling region */
|
case 'r':
|
||||||
if (!set[0]) {
|
if(!set[0]) {
|
||||||
terminal->margin_top = 0;
|
terminal->margin_top = 0;
|
||||||
terminal->margin_bottom = terminal->height-1;
|
terminal->margin_bottom = terminal->height-1;
|
||||||
terminal->row = 0;
|
terminal->row = 0;
|
||||||
|
|
@ -1627,21 +1612,21 @@ handle_escape(struct terminal *terminal)
|
||||||
bottom = (set[1] ? args[1] : 1) - 1;
|
bottom = (set[1] ? args[1] : 1) - 1;
|
||||||
bottom = bottom < 0 ? 0 :
|
bottom = bottom < 0 ? 0 :
|
||||||
(bottom >= terminal->height ? terminal->height - 1 : bottom);
|
(bottom >= terminal->height ? terminal->height - 1 : bottom);
|
||||||
if (bottom > top) {
|
if(bottom > top) {
|
||||||
terminal->margin_top = top;
|
terminal->margin_top = top;
|
||||||
terminal->margin_bottom = bottom;
|
terminal->margin_bottom = bottom;
|
||||||
} else {
|
} else {
|
||||||
terminal->margin_top = 0;
|
terminal->margin_top = 0;
|
||||||
terminal->margin_bottom = terminal->height-1;
|
terminal->margin_bottom = terminal->height-1;
|
||||||
}
|
}
|
||||||
if (terminal->origin_mode)
|
if(terminal->origin_mode)
|
||||||
terminal->row = terminal->margin_top;
|
terminal->row = terminal->margin_top;
|
||||||
else
|
else
|
||||||
terminal->row = 0;
|
terminal->row = 0;
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's': /* Save cursor location */
|
case 's':
|
||||||
terminal->saved_row = terminal->row;
|
terminal->saved_row = terminal->row;
|
||||||
terminal->saved_column = terminal->column;
|
terminal->saved_column = terminal->column;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1688,8 +1673,7 @@ handle_escape(struct terminal *terminal)
|
||||||
fprintf(stderr, "Unimplemented windowOp %d\n", args[0]);
|
fprintf(stderr, "Unimplemented windowOp %d\n", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
case 'u':
|
||||||
case 'u': /* Restore cursor location */
|
|
||||||
terminal->row = terminal->saved_row;
|
terminal->row = terminal->saved_row;
|
||||||
terminal->column = terminal->saved_column;
|
terminal->column = terminal->saved_column;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1703,30 +1687,30 @@ static void
|
||||||
handle_non_csi_escape(struct terminal *terminal, char code)
|
handle_non_csi_escape(struct terminal *terminal, char code)
|
||||||
{
|
{
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case 'M': /* RI - Reverse linefeed */
|
case 'M': /* RI */
|
||||||
terminal->row -= 1;
|
terminal->row -= 1;
|
||||||
if (terminal->row < terminal->margin_top) {
|
if(terminal->row < terminal->margin_top) {
|
||||||
terminal->row = terminal->margin_top;
|
terminal->row = terminal->margin_top;
|
||||||
terminal_scroll(terminal, -1);
|
terminal_scroll(terminal, -1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'E': /* NEL - Newline */
|
case 'E': /* NEL */
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
FALLTHROUGH;
|
// fallthrough
|
||||||
case 'D': /* IND - Linefeed */
|
case 'D': /* IND */
|
||||||
terminal->row += 1;
|
terminal->row += 1;
|
||||||
if (terminal->row > terminal->margin_bottom) {
|
if(terminal->row > terminal->margin_bottom) {
|
||||||
terminal->row = terminal->margin_bottom;
|
terminal->row = terminal->margin_bottom;
|
||||||
terminal_scroll(terminal, +1);
|
terminal_scroll(terminal, +1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'c': /* RIS - Reset*/
|
case 'c': /* RIS */
|
||||||
terminal_init(terminal);
|
terminal_init(terminal);
|
||||||
break;
|
break;
|
||||||
case 'H': /* HTS - Set tab stop at current column */
|
case 'H': /* HTS */
|
||||||
terminal->tab_ruler[terminal->column] = 1;
|
terminal->tab_ruler[terminal->column] = 1;
|
||||||
break;
|
break;
|
||||||
case '7': /* DECSC - Save current state */
|
case '7': /* DECSC */
|
||||||
terminal->saved_row = terminal->row;
|
terminal->saved_row = terminal->row;
|
||||||
terminal->saved_column = terminal->column;
|
terminal->saved_column = terminal->column;
|
||||||
terminal->saved_attr = terminal->curr_attr;
|
terminal->saved_attr = terminal->curr_attr;
|
||||||
|
|
@ -1735,7 +1719,7 @@ handle_non_csi_escape(struct terminal *terminal, char code)
|
||||||
terminal->saved_g0 = terminal->g0;
|
terminal->saved_g0 = terminal->g0;
|
||||||
terminal->saved_g1 = terminal->g1;
|
terminal->saved_g1 = terminal->g1;
|
||||||
break;
|
break;
|
||||||
case '8': /* DECRC - Restore state most recently saved by ESC 7 */
|
case '8': /* DECRC */
|
||||||
terminal->row = terminal->saved_row;
|
terminal->row = terminal->saved_row;
|
||||||
terminal->column = terminal->saved_column;
|
terminal->column = terminal->saved_column;
|
||||||
terminal->curr_attr = terminal->saved_attr;
|
terminal->curr_attr = terminal->saved_attr;
|
||||||
|
|
@ -1744,10 +1728,10 @@ handle_non_csi_escape(struct terminal *terminal, char code)
|
||||||
terminal->g0 = terminal->saved_g0;
|
terminal->g0 = terminal->saved_g0;
|
||||||
terminal->g1 = terminal->saved_g1;
|
terminal->g1 = terminal->saved_g1;
|
||||||
break;
|
break;
|
||||||
case '=': /* DECPAM - Set application keypad mode */
|
case '=': /* DECPAM */
|
||||||
terminal->key_mode = KM_APPLICATION;
|
terminal->key_mode = KM_APPLICATION;
|
||||||
break;
|
break;
|
||||||
case '>': /* DECPNM - Set numeric keypad mode */
|
case '>': /* DECPNM */
|
||||||
terminal->key_mode = KM_NORMAL;
|
terminal->key_mode = KM_NORMAL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1767,7 +1751,7 @@ handle_special_escape(struct terminal *terminal, char special, char code)
|
||||||
/* fill with 'E', no cheap way to do this */
|
/* fill with 'E', no cheap way to do this */
|
||||||
memset(terminal->data, 0, terminal->data_pitch * terminal->height);
|
memset(terminal->data, 0, terminal->data_pitch * terminal->height);
|
||||||
numChars = terminal->width * terminal->height;
|
numChars = terminal->width * terminal->height;
|
||||||
for (i = 0; i < numChars; i++) {
|
for(i = 0; i < numChars; i++) {
|
||||||
terminal->data[i].byte[0] = 'E';
|
terminal->data[i].byte[0] = 'E';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1855,19 +1839,19 @@ handle_sgr(struct terminal *terminal, int code)
|
||||||
terminal->curr_attr.bg = terminal->color_scheme->default_attr.bg;
|
terminal->curr_attr.bg = terminal->color_scheme->default_attr.bg;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (code >= 30 && code <= 37) {
|
if(code >= 30 && code <= 37) {
|
||||||
terminal->curr_attr.fg = code - 30;
|
terminal->curr_attr.fg = code - 30;
|
||||||
if (terminal->curr_attr.a & ATTRMASK_BOLD)
|
if (terminal->curr_attr.a & ATTRMASK_BOLD)
|
||||||
terminal->curr_attr.fg += 8;
|
terminal->curr_attr.fg += 8;
|
||||||
} else if (code >= 40 && code <= 47) {
|
} else if(code >= 40 && code <= 47) {
|
||||||
terminal->curr_attr.bg = code - 40;
|
terminal->curr_attr.bg = code - 40;
|
||||||
} else if (code >= 90 && code <= 97) {
|
} else if (code >= 90 && code <= 97) {
|
||||||
terminal->curr_attr.fg = code - 90 + 8;
|
terminal->curr_attr.fg = code - 90 + 8;
|
||||||
} else if (code >= 100 && code <= 107) {
|
} else if (code >= 100 && code <= 107) {
|
||||||
terminal->curr_attr.bg = code - 100 + 8;
|
terminal->curr_attr.bg = code - 100 + 8;
|
||||||
} else if (code >= 256 && code < 512) {
|
} else if(code >= 256 && code < 512) {
|
||||||
terminal->curr_attr.fg = code - 256;
|
terminal->curr_attr.fg = code - 256;
|
||||||
} else if (code >= 512 && code < 768) {
|
} else if(code >= 512 && code < 768) {
|
||||||
terminal->curr_attr.bg = code - 512;
|
terminal->curr_attr.bg = code - 512;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown SGR code: %d\n", code);
|
fprintf(stderr, "Unknown SGR code: %d\n", code);
|
||||||
|
|
@ -1894,7 +1878,7 @@ handle_special_char(struct terminal *terminal, char c)
|
||||||
if (terminal->mode & MODE_LF_NEWLINE) {
|
if (terminal->mode & MODE_LF_NEWLINE) {
|
||||||
terminal->column = 0;
|
terminal->column = 0;
|
||||||
}
|
}
|
||||||
FALLTHROUGH;
|
/* fallthrough */
|
||||||
case '\v':
|
case '\v':
|
||||||
case '\f':
|
case '\f':
|
||||||
terminal->row++;
|
terminal->row++;
|
||||||
|
|
@ -2209,29 +2193,10 @@ data_source_cancelled(void *data, struct wl_data_source *source)
|
||||||
wl_data_source_destroy(source);
|
wl_data_source_destroy(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_dnd_drop_performed(void *data, struct wl_data_source *source)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_dnd_finished(void *data, struct wl_data_source *source)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
data_source_action(void *data,
|
|
||||||
struct wl_data_source *source, uint32_t dnd_action)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_data_source_listener data_source_listener = {
|
static const struct wl_data_source_listener data_source_listener = {
|
||||||
data_source_target,
|
data_source_target,
|
||||||
data_source_send,
|
data_source_send,
|
||||||
data_source_cancelled,
|
data_source_cancelled
|
||||||
data_source_dnd_drop_performed,
|
|
||||||
data_source_dnd_finished,
|
|
||||||
data_source_action
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char text_mime_type[] = "text/plain;charset=utf-8";
|
static const char text_mime_type[] = "text/plain;charset=utf-8";
|
||||||
|
|
@ -2286,9 +2251,6 @@ terminal_copy(struct terminal *terminal, struct input *input)
|
||||||
{
|
{
|
||||||
terminal->selection =
|
terminal->selection =
|
||||||
display_create_data_source(terminal->display);
|
display_create_data_source(terminal->display);
|
||||||
if (!terminal->selection)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wl_data_source_offer(terminal->selection,
|
wl_data_source_offer(terminal->selection,
|
||||||
"text/plain;charset=utf-8");
|
"text/plain;charset=utf-8");
|
||||||
wl_data_source_add_listener(terminal->selection,
|
wl_data_source_add_listener(terminal->selection,
|
||||||
|
|
@ -2615,7 +2577,7 @@ static int wordsep(int ch)
|
||||||
{
|
{
|
||||||
const char extra[] = "-,./?%&#:_=+@~";
|
const char extra[] = "-,./?%&#:_=+@~";
|
||||||
|
|
||||||
if (ch > 127 || ch < 0)
|
if (ch > 127)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return ch == 0 || !(isalpha(ch) || isdigit(ch) || strchr(extra, ch));
|
return ch == 0 || !(isalpha(ch) || isdigit(ch) || strchr(extra, ch));
|
||||||
|
|
@ -2631,7 +2593,7 @@ recompute_selection(struct terminal *terminal)
|
||||||
int side_margin, top_margin;
|
int side_margin, top_margin;
|
||||||
int start_x, end_x;
|
int start_x, end_x;
|
||||||
int cw, ch;
|
int cw, ch;
|
||||||
union utf8_char *data = NULL;
|
union utf8_char *data;
|
||||||
|
|
||||||
cw = terminal->average_width;
|
cw = terminal->average_width;
|
||||||
ch = terminal->extents.height;
|
ch = terminal->extents.height;
|
||||||
|
|
@ -2950,8 +2912,6 @@ terminal_create(struct display *display)
|
||||||
terminal->widget = window_frame_create(terminal->window, terminal);
|
terminal->widget = window_frame_create(terminal->window, terminal);
|
||||||
terminal->title = xstrdup("Wayland Terminal");
|
terminal->title = xstrdup("Wayland Terminal");
|
||||||
window_set_title(terminal->window, terminal->title);
|
window_set_title(terminal->window, terminal->title);
|
||||||
window_set_appid(terminal->window,
|
|
||||||
"org.freedesktop.weston.wayland-terminal");
|
|
||||||
widget_set_transparent(terminal->widget, 0);
|
widget_set_transparent(terminal->widget, 0);
|
||||||
|
|
||||||
init_state_machine(&terminal->state_machine);
|
init_state_machine(&terminal->state_machine);
|
||||||
|
|
@ -3024,22 +2984,13 @@ static void
|
||||||
terminal_destroy(struct terminal *terminal)
|
terminal_destroy(struct terminal *terminal)
|
||||||
{
|
{
|
||||||
display_unwatch_fd(terminal->display, terminal->master);
|
display_unwatch_fd(terminal->display, terminal->master);
|
||||||
close(terminal->master);
|
|
||||||
|
|
||||||
cairo_scaled_font_destroy(terminal->font_bold);
|
|
||||||
cairo_scaled_font_destroy(terminal->font_normal);
|
|
||||||
|
|
||||||
widget_destroy(terminal->widget);
|
|
||||||
window_destroy(terminal->window);
|
window_destroy(terminal->window);
|
||||||
|
close(terminal->master);
|
||||||
wl_list_remove(&terminal->link);
|
wl_list_remove(&terminal->link);
|
||||||
|
|
||||||
if (wl_list_empty(&terminal_list))
|
if (wl_list_empty(&terminal_list))
|
||||||
display_exit(terminal->display);
|
display_exit(terminal->display);
|
||||||
|
|
||||||
free(terminal->data);
|
|
||||||
free(terminal->data_attr);
|
|
||||||
free(terminal->tab_ruler);
|
|
||||||
free(terminal->title);
|
free(terminal->title);
|
||||||
free(terminal);
|
free(terminal);
|
||||||
}
|
}
|
||||||
|
|
@ -3058,12 +3009,10 @@ io_handler(struct task *task, uint32_t events)
|
||||||
}
|
}
|
||||||
|
|
||||||
len = read(terminal->master, buffer, sizeof buffer);
|
len = read(terminal->master, buffer, sizeof buffer);
|
||||||
if (len < 0) {
|
if (len < 0)
|
||||||
terminal_destroy(terminal);
|
terminal_destroy(terminal);
|
||||||
return;
|
else
|
||||||
}
|
terminal_data(terminal, buffer, len);
|
||||||
|
|
||||||
terminal_data(terminal, buffer, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -3071,52 +3020,21 @@ terminal_run(struct terminal *terminal, const char *path)
|
||||||
{
|
{
|
||||||
int master;
|
int master;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int pipes[2];
|
|
||||||
|
|
||||||
/* Awkwardness: There's a sticky race condition here. If
|
|
||||||
* anything prints after the forkpty() but before the window has
|
|
||||||
* a size then we'll segfault. So we make a pipe and wait on
|
|
||||||
* it before actually exec()ing the terminal. The resize
|
|
||||||
* handler closes it in the parent process and the child continues
|
|
||||||
* on to launch a shell.
|
|
||||||
*
|
|
||||||
* The reason we don't just do terminal_run() after the window
|
|
||||||
* has a size is that we'd prefer to perform the fork() before
|
|
||||||
* the process opens a wayland connection.
|
|
||||||
*/
|
|
||||||
if (pipe(pipes) == -1) {
|
|
||||||
fprintf(stderr, "Can't create pipe for pacing.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = forkpty(&master, NULL, NULL, NULL);
|
pid = forkpty(&master, NULL, NULL, NULL);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
int ret;
|
|
||||||
|
|
||||||
close(pipes[1]);
|
|
||||||
do {
|
|
||||||
char tmp;
|
|
||||||
ret = read(pipes[0], &tmp, 1);
|
|
||||||
} while (ret == -1 && errno == EINTR);
|
|
||||||
close(pipes[0]);
|
|
||||||
setenv("TERM", option_term, 1);
|
setenv("TERM", option_term, 1);
|
||||||
setenv("COLORTERM", option_term, 1);
|
setenv("COLORTERM", option_term, 1);
|
||||||
|
|
||||||
sigaction(SIGPIPE, &oldact, NULL);
|
|
||||||
|
|
||||||
if (execl(path, path, NULL)) {
|
if (execl(path, path, NULL)) {
|
||||||
printf("exec failed: %s\n", strerror(errno));
|
printf("exec failed: %m\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (pid < 0) {
|
} else if (pid < 0) {
|
||||||
fprintf(stderr, "failed to fork and create pty (%s).\n",
|
fprintf(stderr, "failed to fork and create pty (%m).\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipes[0]);
|
|
||||||
terminal->master = master;
|
terminal->master = master;
|
||||||
terminal->pace_pipe = pipes[1];
|
|
||||||
fcntl(master, F_SETFL, O_NONBLOCK);
|
fcntl(master, F_SETFL, O_NONBLOCK);
|
||||||
terminal->io_task.run = io_handler;
|
terminal->io_task.run = io_handler;
|
||||||
display_watch_fd(terminal->display, terminal->master,
|
display_watch_fd(terminal->display, terminal->master,
|
||||||
|
|
@ -3124,8 +3042,6 @@ terminal_run(struct terminal *terminal, const char *path)
|
||||||
|
|
||||||
if (option_fullscreen)
|
if (option_fullscreen)
|
||||||
window_set_fullscreen(terminal->window, 1);
|
window_set_fullscreen(terminal->window, 1);
|
||||||
else if (option_maximize)
|
|
||||||
window_set_maximized(terminal->window, 1);
|
|
||||||
else
|
else
|
||||||
terminal_resize(terminal, 80, 24);
|
terminal_resize(terminal, 80, 24);
|
||||||
|
|
||||||
|
|
@ -3134,7 +3050,6 @@ terminal_run(struct terminal *terminal, const char *path)
|
||||||
|
|
||||||
static const struct weston_option terminal_options[] = {
|
static const struct weston_option terminal_options[] = {
|
||||||
{ WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &option_fullscreen },
|
{ WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &option_fullscreen },
|
||||||
{ WESTON_OPTION_BOOLEAN, "maximized", 'm', &option_maximize },
|
|
||||||
{ WESTON_OPTION_STRING, "font", 0, &option_font },
|
{ WESTON_OPTION_STRING, "font", 0, &option_font },
|
||||||
{ WESTON_OPTION_INTEGER, "font-size", 0, &option_font_size },
|
{ WESTON_OPTION_INTEGER, "font-size", 0, &option_font_size },
|
||||||
{ WESTON_OPTION_STRING, "shell", 0, &option_shell },
|
{ WESTON_OPTION_STRING, "shell", 0, &option_shell },
|
||||||
|
|
@ -3143,9 +3058,8 @@ static const struct weston_option terminal_options[] = {
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct display *d;
|
struct display *d;
|
||||||
struct terminal *terminal, *tmp;
|
struct terminal *terminal;
|
||||||
const char *config_file;
|
const char *config_file;
|
||||||
struct sigaction sigpipe;
|
|
||||||
struct weston_config *config;
|
struct weston_config *config;
|
||||||
struct weston_config_section *s;
|
struct weston_config_section *s;
|
||||||
|
|
||||||
|
|
@ -3155,12 +3069,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
option_shell = getenv("SHELL");
|
option_shell = getenv("SHELL");
|
||||||
if (!option_shell)
|
if (!option_shell)
|
||||||
option_shell = "/bin/sh";
|
option_shell = "/bin/bash";
|
||||||
|
|
||||||
config_file = weston_config_get_name_from_env();
|
config_file = weston_config_get_name_from_env();
|
||||||
config = weston_config_parse(config_file);
|
config = weston_config_parse(config_file);
|
||||||
s = weston_config_get_section(config, "terminal", NULL, NULL);
|
s = weston_config_get_section(config, "terminal", NULL, NULL);
|
||||||
weston_config_section_get_string(s, "font", &option_font, "monospace");
|
weston_config_section_get_string(s, "font", &option_font, "mono");
|
||||||
weston_config_section_get_int(s, "font-size", &option_font_size, 14);
|
weston_config_section_get_int(s, "font-size", &option_font_size, 14);
|
||||||
weston_config_section_get_string(s, "term", &option_term, "xterm");
|
weston_config_section_get_string(s, "term", &option_term, "xterm");
|
||||||
weston_config_destroy(config);
|
weston_config_destroy(config);
|
||||||
|
|
@ -3169,27 +3083,15 @@ int main(int argc, char *argv[])
|
||||||
ARRAY_LENGTH(terminal_options), &argc, argv) > 1) {
|
ARRAY_LENGTH(terminal_options), &argc, argv) > 1) {
|
||||||
printf("Usage: %s [OPTIONS]\n"
|
printf("Usage: %s [OPTIONS]\n"
|
||||||
" --fullscreen or -f\n"
|
" --fullscreen or -f\n"
|
||||||
" --maximized or -m\n"
|
|
||||||
" --font=NAME\n"
|
" --font=NAME\n"
|
||||||
" --font-size=SIZE\n"
|
" --font-size=SIZE\n"
|
||||||
" --shell=NAME\n", argv[0]);
|
" --shell=NAME\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable SIGPIPE so that paste operations do not crash the program
|
|
||||||
* when the file descriptor provided to receive data is a pipe or
|
|
||||||
* socket whose reading end has been closed */
|
|
||||||
sigpipe.sa_handler = SIG_IGN;
|
|
||||||
sigemptyset(&sigpipe.sa_mask);
|
|
||||||
sigemptyset(&oldact.sa_mask);
|
|
||||||
|
|
||||||
sigpipe.sa_flags = 0;
|
|
||||||
sigaction(SIGPIPE, &sigpipe, &oldact);
|
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3200,9 +3102,5 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
display_run(d);
|
display_run(d);
|
||||||
|
|
||||||
wl_list_for_each_safe(terminal, tmp, &terminal_list, link)
|
|
||||||
terminal_destroy(terminal);
|
|
||||||
display_destroy(d);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,972 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012 Intel Corporation
|
|
||||||
* Copyright 2017-2018 Collabora, Ltd.
|
|
||||||
* Copyright 2017-2018 General Electric Company
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <cairo.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
|
||||||
|
|
||||||
#include "clients/window.h"
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include <libweston/matrix.h>
|
|
||||||
|
|
||||||
#include "weston-touch-calibration-client-protocol.h"
|
|
||||||
|
|
||||||
enum exit_code {
|
|
||||||
CAL_EXIT_SUCCESS = 0,
|
|
||||||
CAL_EXIT_ERROR = 1,
|
|
||||||
CAL_EXIT_CANCELLED = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int debug_;
|
|
||||||
static int verbose_;
|
|
||||||
|
|
||||||
#define pr_ver(...) do { \
|
|
||||||
if (verbose_) \
|
|
||||||
printf(__VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define pr_dbg(...) do { \
|
|
||||||
if (debug_) \
|
|
||||||
fprintf(stderr, __VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static void
|
|
||||||
pr_err(const char *fmt, ...) WL_PRINTF(1, 2);
|
|
||||||
|
|
||||||
/* Our points for the calibration must be not be on a line */
|
|
||||||
static const struct {
|
|
||||||
float x_ratio, y_ratio;
|
|
||||||
} test_ratios[] = {
|
|
||||||
{ 0.15, 0.10 }, /* three points for calibration */
|
|
||||||
{ 0.85, 0.13 },
|
|
||||||
{ 0.20, 0.80 },
|
|
||||||
{ 0.70, 0.75 } /* and one for verification */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NR_SAMPLES ((int)ARRAY_LENGTH(test_ratios))
|
|
||||||
|
|
||||||
struct point {
|
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sample {
|
|
||||||
int ind;
|
|
||||||
struct point drawn; /**< drawn point, pixels */
|
|
||||||
struct weston_touch_coordinate *pending;
|
|
||||||
struct point drawn_cal; /**< drawn point, converted */
|
|
||||||
bool conv_done;
|
|
||||||
struct point touched; /**< touch point, normalized */
|
|
||||||
bool touch_done;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct poly {
|
|
||||||
struct color {
|
|
||||||
double r, g, b, a;
|
|
||||||
} color;
|
|
||||||
int n_verts;
|
|
||||||
const struct point *verts;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Touch event handling state machine
|
|
||||||
*
|
|
||||||
* Only a complete down->up->frame sequence should be accepted with user
|
|
||||||
* feedback "right", and anything that deviates from that (invalid_touch,
|
|
||||||
* cancel, multiple touch-downs) needs to undo the current sample and
|
|
||||||
* possibly show user feedback "wrong".
|
|
||||||
*
|
|
||||||
* \<STATE\>
|
|
||||||
* - \<triggers\>: \<actions\>
|
|
||||||
*
|
|
||||||
* IDLE
|
|
||||||
* - touch down: sample, -> DOWN
|
|
||||||
* - touch up: no-op
|
|
||||||
* - frame: no-op
|
|
||||||
* - invalid_touch: (undo), wrong, -> WAIT
|
|
||||||
* - cancel: no-op
|
|
||||||
* DOWN (first touch down)
|
|
||||||
* - touch down: undo, wrong, -> WAIT
|
|
||||||
* - touch up: -> UP
|
|
||||||
* - frame: no-op
|
|
||||||
* - invalid_touch: undo, wrong, -> WAIT
|
|
||||||
* - cancel: undo, -> IDLE
|
|
||||||
* UP (first touch was down and up)
|
|
||||||
* - touch down: undo, wrong, -> WAIT
|
|
||||||
* - touch up: no-op
|
|
||||||
* - frame: right, touch finish, -> WAIT
|
|
||||||
* - invalid_touch: undo, wrong, -> WAIT
|
|
||||||
* - cancel: undo, -> IDLE
|
|
||||||
* WAIT (show user feedback)
|
|
||||||
* - touch down: no-op
|
|
||||||
* - touch up: no-op
|
|
||||||
* - frame, cancel, timer: if num_tp == 0 && timer_done -> IDLE
|
|
||||||
* - invalid_touch: no-op
|
|
||||||
*/
|
|
||||||
enum touch_state {
|
|
||||||
STATE_IDLE,
|
|
||||||
STATE_DOWN,
|
|
||||||
STATE_UP,
|
|
||||||
STATE_WAIT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct calibrator {
|
|
||||||
struct sample samples[NR_SAMPLES];
|
|
||||||
int current_sample;
|
|
||||||
|
|
||||||
struct display *display;
|
|
||||||
struct weston_touch_calibration *calibration;
|
|
||||||
struct weston_touch_calibrator *calibrator;
|
|
||||||
struct window *window;
|
|
||||||
struct widget *widget;
|
|
||||||
|
|
||||||
int n_devices_listed;
|
|
||||||
char *match_name;
|
|
||||||
char *device_name;
|
|
||||||
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
|
|
||||||
bool cancelled;
|
|
||||||
|
|
||||||
const struct poly *current_poly;
|
|
||||||
bool exiting;
|
|
||||||
|
|
||||||
struct toytimer wait_timer;
|
|
||||||
bool timer_pending;
|
|
||||||
enum touch_state state;
|
|
||||||
|
|
||||||
int num_tp; /* touch points down count */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct sample *
|
|
||||||
current_sample(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
return &cal->samples[cal->current_sample];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sample_start(struct calibrator *cal, int i)
|
|
||||||
{
|
|
||||||
struct sample *s = &cal->samples[i];
|
|
||||||
|
|
||||||
assert(i >= 0 && i < NR_SAMPLES);
|
|
||||||
|
|
||||||
s->ind = i;
|
|
||||||
s->drawn.x = round(test_ratios[i].x_ratio * cal->width);
|
|
||||||
s->drawn.y = round(test_ratios[i].y_ratio * cal->height);
|
|
||||||
s->pending = NULL;
|
|
||||||
s->conv_done = false;
|
|
||||||
s->touch_done = false;
|
|
||||||
|
|
||||||
cal->current_sample = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct point
|
|
||||||
wire_to_point(uint32_t xu, uint32_t yu)
|
|
||||||
{
|
|
||||||
struct point p = {
|
|
||||||
.x = (double)xu / 0xffffffff,
|
|
||||||
.y = (double)yu / 0xffffffff
|
|
||||||
};
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sample_touch_down(struct calibrator *cal, uint32_t xu, uint32_t yu)
|
|
||||||
{
|
|
||||||
struct sample *s = current_sample(cal);
|
|
||||||
|
|
||||||
s->touched = wire_to_point(xu, yu);
|
|
||||||
s->touch_done = true;
|
|
||||||
|
|
||||||
pr_dbg("Down[%d] (%f, %f)\n", s->ind, s->touched.x, s->touched.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
coordinate_result_handler(void *data, struct weston_touch_coordinate *interface,
|
|
||||||
uint32_t xu, uint32_t yu)
|
|
||||||
{
|
|
||||||
struct sample *s = data;
|
|
||||||
|
|
||||||
weston_touch_coordinate_destroy(s->pending);
|
|
||||||
s->pending = NULL;
|
|
||||||
|
|
||||||
s->drawn_cal = wire_to_point(xu, yu);
|
|
||||||
s->conv_done = true;
|
|
||||||
|
|
||||||
pr_dbg("Conv[%d] (%f, %f)\n", s->ind, s->drawn_cal.x, s->drawn_cal.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct weston_touch_coordinate_listener coordinate_listener = {
|
|
||||||
coordinate_result_handler
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
sample_undo(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
struct sample *s = current_sample(cal);
|
|
||||||
|
|
||||||
pr_dbg("Undo[%d]\n", s->ind);
|
|
||||||
|
|
||||||
s->touch_done = false;
|
|
||||||
s->conv_done = false;
|
|
||||||
if (s->pending) {
|
|
||||||
weston_touch_coordinate_destroy(s->pending);
|
|
||||||
s->pending = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sample_finish(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
struct sample *s = current_sample(cal);
|
|
||||||
|
|
||||||
pr_dbg("Finish[%d]\n", s->ind);
|
|
||||||
|
|
||||||
assert(!s->pending && !s->conv_done);
|
|
||||||
|
|
||||||
s->pending = weston_touch_calibrator_convert(cal->calibrator,
|
|
||||||
(int32_t)s->drawn.x,
|
|
||||||
(int32_t)s->drawn.y);
|
|
||||||
weston_touch_coordinate_add_listener(s->pending,
|
|
||||||
&coordinate_listener, s);
|
|
||||||
|
|
||||||
if (cal->current_sample + 1 < NR_SAMPLES) {
|
|
||||||
sample_start(cal, cal->current_sample + 1);
|
|
||||||
} else {
|
|
||||||
pr_dbg("got all touches\n");
|
|
||||||
cal->exiting = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calibration algorithm:
|
|
||||||
*
|
|
||||||
* The equation we want to apply at event time where x' and y' are the
|
|
||||||
* calibrated co-ordinates.
|
|
||||||
*
|
|
||||||
* x' = Ax + By + C
|
|
||||||
* y' = Dx + Ey + F
|
|
||||||
*
|
|
||||||
* For example "zero calibration" would be A=1.0 B=0.0 C=0.0, D=0.0, E=1.0,
|
|
||||||
* and F=0.0.
|
|
||||||
*
|
|
||||||
* With 6 unknowns we need 6 equations to find the constants:
|
|
||||||
*
|
|
||||||
* x1' = Ax1 + By1 + C
|
|
||||||
* y1' = Dx1 + Ey1 + F
|
|
||||||
* ...
|
|
||||||
* x3' = Ax3 + By3 + C
|
|
||||||
* y3' = Dx3 + Ey3 + F
|
|
||||||
*
|
|
||||||
* In matrix form:
|
|
||||||
*
|
|
||||||
* x1' x1 y1 1 A
|
|
||||||
* x2' = x2 y2 1 x B
|
|
||||||
* x3' x3 y3 1 C
|
|
||||||
*
|
|
||||||
* So making the matrix M we can find the constants with:
|
|
||||||
*
|
|
||||||
* A x1'
|
|
||||||
* B = M^-1 x x2'
|
|
||||||
* C x3'
|
|
||||||
*
|
|
||||||
* (and similarly for D, E and F)
|
|
||||||
*
|
|
||||||
* For the calibration the desired values x, y are the same values at which
|
|
||||||
* we've drawn at.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
compute_calibration(struct calibrator *cal, float *result)
|
|
||||||
{
|
|
||||||
struct weston_matrix m;
|
|
||||||
struct weston_matrix inverse;
|
|
||||||
struct weston_vector x_calib;
|
|
||||||
struct weston_vector y_calib;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert(NR_SAMPLES >= 3);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* x1 y1 1 0
|
|
||||||
* x2 y2 1 0
|
|
||||||
* x3 y3 1 0
|
|
||||||
* 0 0 0 1
|
|
||||||
*/
|
|
||||||
weston_matrix_init(&m);
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
m.M.col[0].el[i] = cal->samples[i].touched.x;
|
|
||||||
m.M.col[1].el[i] = cal->samples[i].touched.y;
|
|
||||||
m.M.col[2].el[i] = 1.0f;
|
|
||||||
}
|
|
||||||
m.type = WESTON_MATRIX_TRANSFORM_OTHER;
|
|
||||||
|
|
||||||
if (weston_matrix_invert(&inverse, &m) < 0) {
|
|
||||||
pr_err("non-invertible matrix during computation\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
x_calib.v.el[i] = cal->samples[i].drawn_cal.x;
|
|
||||||
y_calib.v.el[i] = cal->samples[i].drawn_cal.y;
|
|
||||||
}
|
|
||||||
x_calib.v.el[3] = 0.0f;
|
|
||||||
y_calib.v.el[3] = 0.0f;
|
|
||||||
|
|
||||||
/* Multiples into the vector */
|
|
||||||
weston_matrix_transform(&inverse, &x_calib);
|
|
||||||
weston_matrix_transform(&inverse, &y_calib);
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
result[i] = x_calib.v.el[i];
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
result[i + 3] = y_calib.v.el[i];
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
verify_calibration(struct calibrator *cal, const float *r)
|
|
||||||
{
|
|
||||||
double thr = 0.1; /* accepted error radius */
|
|
||||||
struct point e; /* expected value; error */
|
|
||||||
const struct sample *s = &cal->samples[3];
|
|
||||||
|
|
||||||
/* transform raw touches through the matrix */
|
|
||||||
e.x = r[0] * s->touched.x + r[1] * s->touched.y + r[2];
|
|
||||||
e.y = r[3] * s->touched.x + r[4] * s->touched.y + r[5];
|
|
||||||
|
|
||||||
/* compute error */
|
|
||||||
e.x -= s->drawn_cal.x;
|
|
||||||
e.y -= s->drawn_cal.y;
|
|
||||||
|
|
||||||
pr_dbg("calibration test error: %f, %f\n", e.x, e.y);
|
|
||||||
|
|
||||||
if (e.x * e.x + e.y * e.y < thr * thr)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
pr_err("Calibration verification failed, too large error.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_calibration(struct calibrator *cal, float *values)
|
|
||||||
{
|
|
||||||
struct wl_array matrix;
|
|
||||||
float *f;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
wl_array_init(&matrix);
|
|
||||||
for (i = 0; i < 6; i++) {
|
|
||||||
f = wl_array_add(&matrix, sizeof *f);
|
|
||||||
*f = values[i];
|
|
||||||
}
|
|
||||||
weston_touch_calibration_save(cal->calibration,
|
|
||||||
cal->device_name, &matrix);
|
|
||||||
wl_array_release(&matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct point cross_verts[] = {
|
|
||||||
{ 0.1, 0.2 },
|
|
||||||
{ 0.2, 0.1 },
|
|
||||||
{ 0.5, 0.4 },
|
|
||||||
{ 0.8, 0.1 },
|
|
||||||
{ 0.9, 0.2 },
|
|
||||||
{ 0.6, 0.5 },
|
|
||||||
{ 0.9, 0.8 },
|
|
||||||
{ 0.8, 0.9 },
|
|
||||||
{ 0.5, 0.6 },
|
|
||||||
{ 0.2, 0.9 },
|
|
||||||
{ 0.1, 0.8 },
|
|
||||||
{ 0.4, 0.5 },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* a red cross, for "wrong" */
|
|
||||||
static const struct poly cross = {
|
|
||||||
.color = { 0.7, 0.0, 0.0, 1.0 },
|
|
||||||
.n_verts = ARRAY_LENGTH(cross_verts),
|
|
||||||
.verts = cross_verts
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct point check_verts[] = {
|
|
||||||
{ 0.5, 0.7 },
|
|
||||||
{ 0.8, 0.1 },
|
|
||||||
{ 0.9, 0.1 },
|
|
||||||
{ 0.55, 0.8 },
|
|
||||||
{ 0.45, 0.8 },
|
|
||||||
{ 0.3, 0.5 },
|
|
||||||
{ 0.4, 0.5 }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* a green check mark, for "right" */
|
|
||||||
static const struct poly check = {
|
|
||||||
.color = { 0.0, 0.7, 0.0, 1.0 },
|
|
||||||
.n_verts = ARRAY_LENGTH(check_verts),
|
|
||||||
.verts = check_verts
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_poly(cairo_t *cr, const struct poly *poly)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, poly->color.r, poly->color.g,
|
|
||||||
poly->color.b, poly->color.a);
|
|
||||||
cairo_move_to(cr, poly->verts[0].x, poly->verts[0].y);
|
|
||||||
for (i = 1; i < poly->n_verts; i++)
|
|
||||||
cairo_line_to(cr, poly->verts[i].x, poly->verts[i].y);
|
|
||||||
cairo_close_path(cr);
|
|
||||||
cairo_fill(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
feedback_show(struct calibrator *cal, const struct poly *what)
|
|
||||||
{
|
|
||||||
cal->current_poly = what;
|
|
||||||
widget_schedule_redraw(cal->widget);
|
|
||||||
|
|
||||||
toytimer_arm_once_usec(&cal->wait_timer, 1000 * 1000);
|
|
||||||
cal->timer_pending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
feedback_hide(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
cal->current_poly = NULL;
|
|
||||||
widget_schedule_redraw(cal->widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
try_enter_state_idle(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
if (cal->num_tp != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (cal->timer_pending)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cal->state = STATE_IDLE;
|
|
||||||
|
|
||||||
feedback_hide(cal);
|
|
||||||
|
|
||||||
if (cal->exiting)
|
|
||||||
display_exit(cal->display);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
enter_state_wait(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
assert(cal->timer_pending);
|
|
||||||
cal->state = STATE_WAIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wait_timer_done(struct toytimer *tt)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = container_of(tt, struct calibrator, wait_timer);
|
|
||||||
|
|
||||||
assert(cal->state == STATE_WAIT);
|
|
||||||
cal->timer_pending = false;
|
|
||||||
try_enter_state_idle(cal);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
redraw_handler(struct widget *widget, void *data)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
struct sample *s = current_sample(cal);
|
|
||||||
struct rectangle allocation;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
widget_get_allocation(cal->widget, &allocation);
|
|
||||||
assert(allocation.width == cal->width);
|
|
||||||
assert(allocation.height == cal->height);
|
|
||||||
|
|
||||||
surface = window_get_surface(cal->window);
|
|
||||||
cr = cairo_create(surface);
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
|
|
||||||
cairo_paint(cr);
|
|
||||||
|
|
||||||
if (!cal->current_poly) {
|
|
||||||
cairo_translate(cr, s->drawn.x, s->drawn.y);
|
|
||||||
cairo_set_line_width(cr, 2.0);
|
|
||||||
cairo_set_source_rgb(cr, 0.7, 0.0, 0.0);
|
|
||||||
cairo_move_to(cr, 0, -10.0);
|
|
||||||
cairo_line_to(cr, 0, 10.0);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
cairo_move_to(cr, -10.0, 0);
|
|
||||||
cairo_line_to(cr, 10.0, 0.0);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
} else {
|
|
||||||
cairo_scale(cr, allocation.width, allocation.height);
|
|
||||||
draw_poly(cr, cal->current_poly);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_destroy(cr);
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct calibrator *
|
|
||||||
calibrator_create(struct display *display, const char *match_name)
|
|
||||||
{
|
|
||||||
struct calibrator *cal;
|
|
||||||
|
|
||||||
cal = zalloc(sizeof *cal);
|
|
||||||
if (!cal)
|
|
||||||
abort();
|
|
||||||
|
|
||||||
cal->match_name = match_name ? strdup(match_name) : NULL;
|
|
||||||
cal->window = window_create_custom(display);
|
|
||||||
cal->widget = window_add_widget(cal->window, cal);
|
|
||||||
window_inhibit_redraw(cal->window);
|
|
||||||
window_set_title(cal->window, "Touchscreen calibrator");
|
|
||||||
window_set_appid(cal->window,
|
|
||||||
"org.freedesktop.weston.touchscreen-calibrator");
|
|
||||||
cal->display = display;
|
|
||||||
|
|
||||||
widget_set_redraw_handler(cal->widget, redraw_handler);
|
|
||||||
|
|
||||||
toytimer_init(&cal->wait_timer, CLOCK_MONOTONIC,
|
|
||||||
display, wait_timer_done);
|
|
||||||
|
|
||||||
cal->state = STATE_IDLE;
|
|
||||||
cal->num_tp = 0;
|
|
||||||
|
|
||||||
return cal;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
configure_handler(void *data, struct weston_touch_calibrator *interface,
|
|
||||||
int32_t width, int32_t height)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
pr_dbg("Configure calibrator window to size %ix%i\n", width, height);
|
|
||||||
cal->width = width;
|
|
||||||
cal->height = height;
|
|
||||||
window_schedule_resize(cal->window, width, height);
|
|
||||||
window_uninhibit_redraw(cal->window);
|
|
||||||
|
|
||||||
sample_start(cal, 0);
|
|
||||||
widget_schedule_redraw(cal->widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cancel_calibration_handler(void *data, struct weston_touch_calibrator *interface)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
pr_dbg("calibration cancelled by the display server, quitting.\n");
|
|
||||||
cal->cancelled = true;
|
|
||||||
display_exit(cal->display);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
invalid_touch_handler(void *data, struct weston_touch_calibrator *interface)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
pr_dbg("invalid touch\n");
|
|
||||||
|
|
||||||
switch (cal->state) {
|
|
||||||
case STATE_IDLE:
|
|
||||||
case STATE_DOWN:
|
|
||||||
case STATE_UP:
|
|
||||||
sample_undo(cal);
|
|
||||||
feedback_show(cal, &cross);
|
|
||||||
enter_state_wait(cal);
|
|
||||||
break;
|
|
||||||
case STATE_WAIT:
|
|
||||||
/* no-op */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
down_handler(void *data, struct weston_touch_calibrator *interface,
|
|
||||||
uint32_t time, int32_t id, uint32_t xu, uint32_t yu)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
cal->num_tp++;
|
|
||||||
|
|
||||||
switch (cal->state) {
|
|
||||||
case STATE_IDLE:
|
|
||||||
sample_touch_down(cal, xu, yu);
|
|
||||||
cal->state = STATE_DOWN;
|
|
||||||
break;
|
|
||||||
case STATE_DOWN:
|
|
||||||
case STATE_UP:
|
|
||||||
sample_undo(cal);
|
|
||||||
feedback_show(cal, &cross);
|
|
||||||
enter_state_wait(cal);
|
|
||||||
break;
|
|
||||||
case STATE_WAIT:
|
|
||||||
/* no-op */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cal->current_poly)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
up_handler(void *data, struct weston_touch_calibrator *interface,
|
|
||||||
uint32_t time, int32_t id)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
cal->num_tp--;
|
|
||||||
if (cal->num_tp < 0) {
|
|
||||||
pr_dbg("Unmatched touch up.\n");
|
|
||||||
cal->num_tp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cal->state) {
|
|
||||||
case STATE_DOWN:
|
|
||||||
cal->state = STATE_UP;
|
|
||||||
break;
|
|
||||||
case STATE_IDLE:
|
|
||||||
case STATE_UP:
|
|
||||||
case STATE_WAIT:
|
|
||||||
/* no-op */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
motion_handler(void *data, struct weston_touch_calibrator *interface,
|
|
||||||
uint32_t time, int32_t id, uint32_t xu, uint32_t yu)
|
|
||||||
{
|
|
||||||
/* motion is ignored */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
frame_handler(void *data, struct weston_touch_calibrator *interface)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
switch (cal->state) {
|
|
||||||
case STATE_IDLE:
|
|
||||||
case STATE_DOWN:
|
|
||||||
/* no-op */
|
|
||||||
break;
|
|
||||||
case STATE_UP:
|
|
||||||
feedback_show(cal, &check);
|
|
||||||
sample_finish(cal);
|
|
||||||
enter_state_wait(cal);
|
|
||||||
break;
|
|
||||||
case STATE_WAIT:
|
|
||||||
try_enter_state_idle(cal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cancel_handler(void *data, struct weston_touch_calibrator *interface)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
cal->num_tp = 0;
|
|
||||||
|
|
||||||
switch (cal->state) {
|
|
||||||
case STATE_IDLE:
|
|
||||||
/* no-op */
|
|
||||||
break;
|
|
||||||
case STATE_DOWN:
|
|
||||||
case STATE_UP:
|
|
||||||
sample_undo(cal);
|
|
||||||
try_enter_state_idle(cal);
|
|
||||||
break;
|
|
||||||
case STATE_WAIT:
|
|
||||||
try_enter_state_idle(cal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct weston_touch_calibrator_listener calibrator_listener = {
|
|
||||||
configure_handler,
|
|
||||||
cancel_calibration_handler,
|
|
||||||
invalid_touch_handler,
|
|
||||||
down_handler,
|
|
||||||
up_handler,
|
|
||||||
motion_handler,
|
|
||||||
frame_handler,
|
|
||||||
cancel_handler
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
calibrator_show(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
struct wl_surface *surface = window_get_wl_surface(cal->window);
|
|
||||||
|
|
||||||
cal->calibrator =
|
|
||||||
weston_touch_calibration_create_calibrator(cal->calibration,
|
|
||||||
surface,
|
|
||||||
cal->device_name);
|
|
||||||
weston_touch_calibrator_add_listener(cal->calibrator,
|
|
||||||
&calibrator_listener, cal);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
calibrator_destroy(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
toytimer_fini(&cal->wait_timer);
|
|
||||||
if (cal->calibrator)
|
|
||||||
weston_touch_calibrator_destroy(cal->calibrator);
|
|
||||||
if (cal->calibration)
|
|
||||||
weston_touch_calibration_destroy(cal->calibration);
|
|
||||||
if (cal->widget)
|
|
||||||
widget_destroy(cal->widget);
|
|
||||||
if (cal->window)
|
|
||||||
window_destroy(cal->window);
|
|
||||||
free(cal->match_name);
|
|
||||||
free(cal->device_name);
|
|
||||||
free(cal);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
touch_device_handler(void *data, struct weston_touch_calibration *c,
|
|
||||||
const char *device, const char *head)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
cal->n_devices_listed++;
|
|
||||||
|
|
||||||
if (!cal->match_name) {
|
|
||||||
printf("device \"%s\" - head \"%s\"\n", device, head);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cal->device_name)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (strcmp(cal->match_name, device) == 0 ||
|
|
||||||
strcmp(cal->match_name, head) == 0)
|
|
||||||
cal->device_name = strdup(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct weston_touch_calibration_listener touch_calibration_listener = {
|
|
||||||
touch_device_handler
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
global_handler(struct display *display, uint32_t name,
|
|
||||||
const char *interface, uint32_t version, void *data)
|
|
||||||
{
|
|
||||||
struct calibrator *cal = data;
|
|
||||||
|
|
||||||
if (strcmp(interface, "weston_touch_calibration") == 0) {
|
|
||||||
cal->calibration = display_bind(display, name,
|
|
||||||
&weston_touch_calibration_interface, 1);
|
|
||||||
weston_touch_calibration_add_listener(cal->calibration,
|
|
||||||
&touch_calibration_listener,
|
|
||||||
cal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
calibrator_run(struct calibrator *cal)
|
|
||||||
{
|
|
||||||
struct wl_display *dpy;
|
|
||||||
struct sample *s;
|
|
||||||
bool wait;
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
float result[6];
|
|
||||||
|
|
||||||
calibrator_show(cal);
|
|
||||||
display_run(cal->display);
|
|
||||||
|
|
||||||
if (cal->cancelled)
|
|
||||||
return CAL_EXIT_CANCELLED;
|
|
||||||
|
|
||||||
/* remove the window, no more input events */
|
|
||||||
widget_destroy(cal->widget);
|
|
||||||
cal->widget = NULL;
|
|
||||||
window_destroy(cal->window);
|
|
||||||
cal->window = NULL;
|
|
||||||
|
|
||||||
/* wait for all conversions to return */
|
|
||||||
dpy = display_get_display(cal->display);
|
|
||||||
do {
|
|
||||||
wait = false;
|
|
||||||
|
|
||||||
for (i = 0; i < NR_SAMPLES; i++)
|
|
||||||
if (cal->samples[i].pending)
|
|
||||||
wait = true;
|
|
||||||
|
|
||||||
if (wait) {
|
|
||||||
ret = wl_display_roundtrip(dpy);
|
|
||||||
if (ret < 0)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
}
|
|
||||||
} while (wait);
|
|
||||||
|
|
||||||
for (i = 0; i < NR_SAMPLES; i++) {
|
|
||||||
s = &cal->samples[i];
|
|
||||||
if (!s->conv_done || !s->touch_done)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compute_calibration(cal, result) < 0)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
|
|
||||||
if (verify_calibration(cal, result) < 0)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
|
|
||||||
pr_ver("Calibration values:");
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
pr_ver(" %f", result[i]);
|
|
||||||
pr_ver("\n");
|
|
||||||
|
|
||||||
send_calibration(cal, result);
|
|
||||||
ret = wl_display_roundtrip(dpy);
|
|
||||||
if (ret < 0)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
|
|
||||||
return CAL_EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
pr_err(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list argp;
|
|
||||||
|
|
||||||
va_start(argp, fmt);
|
|
||||||
fprintf(stderr, "%s error: ", program_invocation_short_name);
|
|
||||||
vfprintf(stderr, fmt, argp);
|
|
||||||
va_end(argp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
help(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Compute a touchscreen calibration matrix for "
|
|
||||||
"a Wayland compositor by\n"
|
|
||||||
"having the user touch points on the screen.\n\n");
|
|
||||||
fprintf(stderr, "Usage: %s [options...] name\n\n",
|
|
||||||
program_invocation_short_name);
|
|
||||||
fprintf(stderr,
|
|
||||||
"Where 'name' can be a touch device sys path or a head name.\n"
|
|
||||||
"If 'name' is not given, all devices available for "
|
|
||||||
"calibration will be listed.\n"
|
|
||||||
"If 'name' is given, it must be exactly as listed.\n"
|
|
||||||
"Options:\n"
|
|
||||||
" --debug Print messages to help debugging.\n"
|
|
||||||
" -h, --help Display this help message\n"
|
|
||||||
" -v, --verbose Print list header and calibration result.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct display *display;
|
|
||||||
struct calibrator *cal;
|
|
||||||
int c;
|
|
||||||
char *match_name = NULL;
|
|
||||||
int exit_code = CAL_EXIT_SUCCESS;
|
|
||||||
static const struct option opts[] = {
|
|
||||||
{ "help", no_argument, NULL, 'h' },
|
|
||||||
{ "debug", no_argument, &debug_, 1 },
|
|
||||||
{ "verbose", no_argument, &verbose_, 1 },
|
|
||||||
{ 0, 0, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "hv", opts, NULL)) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 'h':
|
|
||||||
help();
|
|
||||||
return CAL_EXIT_SUCCESS;
|
|
||||||
case 'v':
|
|
||||||
verbose_ = 1;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc)
|
|
||||||
match_name = argv[optind++];
|
|
||||||
|
|
||||||
if (optind < argc) {
|
|
||||||
pr_err("extra arguments given.\n\n");
|
|
||||||
help();
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
display = display_create(&argc, argv);
|
|
||||||
if (!display)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
|
|
||||||
cal = calibrator_create(display, match_name);
|
|
||||||
if (!cal)
|
|
||||||
return CAL_EXIT_ERROR;
|
|
||||||
|
|
||||||
display_set_user_data(display, cal);
|
|
||||||
display_set_global_handler(display, global_handler);
|
|
||||||
|
|
||||||
if (!match_name)
|
|
||||||
pr_ver("Available touch devices:\n");
|
|
||||||
|
|
||||||
/* Roundtrip to get list of available touch devices,
|
|
||||||
* first globals, then touch_device events */
|
|
||||||
wl_display_roundtrip(display_get_display(display));
|
|
||||||
wl_display_roundtrip(display_get_display(display));
|
|
||||||
|
|
||||||
if (!cal->calibration) {
|
|
||||||
exit_code = CAL_EXIT_ERROR;
|
|
||||||
pr_err("the Wayland server does not expose the calibration interface.\n");
|
|
||||||
} else if (cal->device_name) {
|
|
||||||
exit_code = calibrator_run(cal);
|
|
||||||
} else if (match_name) {
|
|
||||||
exit_code = CAL_EXIT_ERROR;
|
|
||||||
pr_err("\"%s\" was not found.\n", match_name);
|
|
||||||
} else if (cal->n_devices_listed == 0) {
|
|
||||||
fprintf(stderr, "No devices listed.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
calibrator_destroy(cal);
|
|
||||||
display_destroy(display);
|
|
||||||
|
|
||||||
return exit_code;
|
|
||||||
}
|
|
||||||
|
|
@ -2,24 +2,23 @@
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
* Copyright © 2012 Intel Corporation
|
* Copyright © 2012 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -29,7 +28,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
@ -227,13 +225,11 @@ static void
|
||||||
usage(int error_code)
|
usage(int error_code)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: transformed [OPTIONS]\n\n"
|
fprintf(stderr, "Usage: transformed [OPTIONS]\n\n"
|
||||||
|
" -d\t\tUse \"driver\" fullscreen method\n"
|
||||||
" -w <width>\tSet window width to <width>\n"
|
" -w <width>\tSet window width to <width>\n"
|
||||||
" -h <height>\tSet window height to <height>\n"
|
" -h <height>\tSet window height to <height>\n"
|
||||||
" --help\tShow this help text\n\n");
|
" --help\tShow this help text\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "This version has been fixed for "
|
|
||||||
"https://gitlab.freedesktop.org/wayland/weston/issues/99 .\n");
|
|
||||||
|
|
||||||
exit(error_code);
|
exit(error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,8 +262,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,8 +272,6 @@ int main(int argc, char *argv[])
|
||||||
window_add_widget(transformed.window, &transformed);
|
window_add_widget(transformed.window, &transformed);
|
||||||
|
|
||||||
window_set_title(transformed.window, "Transformed");
|
window_set_title(transformed.window, "Transformed");
|
||||||
window_set_appid(transformed.window,
|
|
||||||
"org.freedesktop.weston.transformed");
|
|
||||||
|
|
||||||
widget_set_transparent(transformed.widget, 0);
|
widget_set_transparent(transformed.widget, 0);
|
||||||
widget_set_default_cursor(transformed.widget, CURSOR_BLANK);
|
widget_set_default_cursor(transformed.widget, CURSOR_BLANK);
|
||||||
|
|
|
||||||
|
|
@ -1,502 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright © 2017 Pekka Paalanen <pq@iki.fi>
|
|
||||||
* Copyright © 2018 Zodiac Inflight Innovations
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the
|
|
||||||
* next paragraph) shall be included in all copies or substantial
|
|
||||||
* portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
|
||||||
|
|
||||||
#include "shared/helpers.h"
|
|
||||||
#include <libweston/zalloc.h>
|
|
||||||
#include "weston-debug-client-protocol.h"
|
|
||||||
|
|
||||||
struct debug_app {
|
|
||||||
struct {
|
|
||||||
bool help;
|
|
||||||
bool list;
|
|
||||||
bool bind_all;
|
|
||||||
char *output;
|
|
||||||
char *outfd;
|
|
||||||
} opt;
|
|
||||||
|
|
||||||
int out_fd;
|
|
||||||
struct wl_display *dpy;
|
|
||||||
struct wl_registry *registry;
|
|
||||||
struct weston_debug_v1 *debug_iface;
|
|
||||||
struct wl_list stream_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct debug_stream {
|
|
||||||
struct wl_list link;
|
|
||||||
bool should_bind;
|
|
||||||
char *name;
|
|
||||||
char *desc;
|
|
||||||
struct weston_debug_stream_v1 *obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called either through stream_find in response to an advertisement
|
|
||||||
* event (see comment on stream_find) when we have all the information,
|
|
||||||
* or directly from option parsing to make a placeholder entry when the
|
|
||||||
* stream was explicitly named on the command line to bind to.
|
|
||||||
*/
|
|
||||||
static struct debug_stream *
|
|
||||||
stream_alloc(struct debug_app *app, const char *name, const char *desc)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream;
|
|
||||||
|
|
||||||
stream = zalloc(sizeof *stream);
|
|
||||||
if (!stream)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
stream->name = strdup(name);
|
|
||||||
if (!stream->name) {
|
|
||||||
free(stream);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desc) {
|
|
||||||
stream->desc = strdup(desc);
|
|
||||||
if (!stream->desc) {
|
|
||||||
free(stream->name);
|
|
||||||
free(stream);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->should_bind = app->opt.bind_all;
|
|
||||||
wl_list_insert(app->stream_list.prev, &stream->link);
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called in response to a stream advertisement event. If our stream was
|
|
||||||
* manually specified on the command line, then it will already have a
|
|
||||||
* dummy entry in stream_list: we fill in its description and return.
|
|
||||||
* If there's no entry in the list, we make a new one and return that.
|
|
||||||
*/
|
|
||||||
static struct debug_stream *
|
|
||||||
stream_find(struct debug_app *app, const char *name, const char *desc)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream;
|
|
||||||
|
|
||||||
wl_list_for_each(stream, &app->stream_list, link) {
|
|
||||||
if (strcmp(stream->name, name) == 0) {
|
|
||||||
assert(stream->desc == NULL);
|
|
||||||
if (desc)
|
|
||||||
stream->desc = strdup(desc);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream_alloc(app, name, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
stream_destroy(struct debug_stream *stream)
|
|
||||||
{
|
|
||||||
if (stream->obj)
|
|
||||||
weston_debug_stream_v1_destroy(stream->obj);
|
|
||||||
|
|
||||||
wl_list_remove(&stream->link);
|
|
||||||
free(stream->desc);
|
|
||||||
free(stream->name);
|
|
||||||
free(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_streams(struct debug_app *app)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream;
|
|
||||||
struct debug_stream *tmp;
|
|
||||||
|
|
||||||
wl_list_for_each_safe(stream, tmp, &app->stream_list, link)
|
|
||||||
stream_destroy(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
debug_advertise(void *data, struct weston_debug_v1 *debug, const char *name,
|
|
||||||
const char *desc)
|
|
||||||
{
|
|
||||||
struct debug_app *app = data;
|
|
||||||
(void) stream_find(app, name, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct weston_debug_v1_listener debug_listener = {
|
|
||||||
debug_advertise,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
global_handler(void *data, struct wl_registry *registry, uint32_t id,
|
|
||||||
const char *interface, uint32_t version)
|
|
||||||
{
|
|
||||||
struct debug_app *app = data;
|
|
||||||
uint32_t myver;
|
|
||||||
|
|
||||||
assert(app->registry == registry);
|
|
||||||
|
|
||||||
if (!strcmp(interface, weston_debug_v1_interface.name)) {
|
|
||||||
if (app->debug_iface)
|
|
||||||
return;
|
|
||||||
|
|
||||||
myver = MIN(1, version);
|
|
||||||
app->debug_iface =
|
|
||||||
wl_registry_bind(registry, id,
|
|
||||||
&weston_debug_v1_interface, myver);
|
|
||||||
weston_debug_v1_add_listener(app->debug_iface, &debug_listener,
|
|
||||||
app);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
|
||||||
global_handler,
|
|
||||||
global_remove_handler
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_stream_complete(void *data, struct weston_debug_stream_v1 *obj)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream = data;
|
|
||||||
|
|
||||||
assert(stream->obj == obj);
|
|
||||||
|
|
||||||
stream_destroy(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_stream_failure(void *data, struct weston_debug_stream_v1 *obj,
|
|
||||||
const char *msg)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream = data;
|
|
||||||
|
|
||||||
assert(stream->obj == obj);
|
|
||||||
|
|
||||||
fprintf(stderr, "Debug stream '%s' aborted: %s\n", stream->name, msg);
|
|
||||||
|
|
||||||
stream_destroy(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct weston_debug_stream_v1_listener stream_listener = {
|
|
||||||
handle_stream_complete,
|
|
||||||
handle_stream_failure
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_streams(struct debug_app *app)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream;
|
|
||||||
|
|
||||||
wl_list_for_each(stream, &app->stream_list, link) {
|
|
||||||
if (!stream->should_bind)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
stream->obj = weston_debug_v1_subscribe(app->debug_iface,
|
|
||||||
stream->name,
|
|
||||||
app->out_fd);
|
|
||||||
weston_debug_stream_v1_add_listener(stream->obj,
|
|
||||||
&stream_listener, stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
list_streams(struct debug_app *app)
|
|
||||||
{
|
|
||||||
struct debug_stream *stream;
|
|
||||||
|
|
||||||
fprintf(stderr, "Available debug streams:\n");
|
|
||||||
|
|
||||||
wl_list_for_each(stream, &app->stream_list, link) {
|
|
||||||
if (stream->should_bind && stream->desc) {
|
|
||||||
fprintf(stderr, " %s [will bind]\n", stream->name);
|
|
||||||
fprintf(stderr, " %s\n", stream->desc);
|
|
||||||
} else if (stream->should_bind) {
|
|
||||||
fprintf(stderr, " %s [wanted but not found]\n",
|
|
||||||
stream->name);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, " %s [will not bind]\n",
|
|
||||||
stream->name);
|
|
||||||
fprintf(stderr, " %s\n", stream->desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
setup_out_fd(const char *output, const char *outfd)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
assert(!(output && outfd));
|
|
||||||
|
|
||||||
if (output) {
|
|
||||||
if (strcmp(output, "-") == 0) {
|
|
||||||
fd = STDOUT_FILENO;
|
|
||||||
} else {
|
|
||||||
fd = open(output,
|
|
||||||
O_WRONLY | O_APPEND | O_CREAT, 0644);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error: opening file '%s' failed: %s\n",
|
|
||||||
output, strerror(errno));
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
} else if (outfd) {
|
|
||||||
fd = atoi(outfd);
|
|
||||||
} else {
|
|
||||||
fd = STDOUT_FILENO;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = fcntl(fd, F_GETFL);
|
|
||||||
if (flags == -1) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error: cannot use file descriptor %d: %s\n", fd,
|
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & O_ACCMODE) != O_WRONLY &&
|
|
||||||
(flags & O_ACCMODE) != O_RDWR) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error: file descriptor %d is not writable.\n", fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_help(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage: weston-debug [options] [names]\n"
|
|
||||||
"Where options may be:\n"
|
|
||||||
" -h, --help\n"
|
|
||||||
" This help text, and exit with success.\n"
|
|
||||||
" -l, --list\n"
|
|
||||||
" Print a list of available debug streams to stderr.\n"
|
|
||||||
" -a, --all-streams\n"
|
|
||||||
" Bind to all available streams.\n"
|
|
||||||
" -o FILE, --output FILE\n"
|
|
||||||
" Direct output to file named FILE. Use - for stdout.\n"
|
|
||||||
" Stdout is the default. Mutually exclusive with -f.\n"
|
|
||||||
" -f FD, --outfd FD\n"
|
|
||||||
" Direct output to the file descriptor FD.\n"
|
|
||||||
" Stdout (1) is the default. Mutually exclusive with -o.\n"
|
|
||||||
"Names are whatever debug stream names the compositor supports.\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
parse_cmdline(struct debug_app *app, int argc, char **argv)
|
|
||||||
{
|
|
||||||
static const struct option opts[] = {
|
|
||||||
{ "help", no_argument, NULL, 'h' },
|
|
||||||
{ "list", no_argument, NULL, 'l' },
|
|
||||||
{ "all-streams", no_argument, NULL, 'a' },
|
|
||||||
{ "output", required_argument, NULL, 'o' },
|
|
||||||
{ "outfd", required_argument, NULL, 'f' },
|
|
||||||
{ 0 }
|
|
||||||
};
|
|
||||||
static const char optstr[] = "hlao:f:";
|
|
||||||
int c;
|
|
||||||
bool failed = false;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
c = getopt_long(argc, argv, optstr, opts, NULL);
|
|
||||||
if (c == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case 'h':
|
|
||||||
app->opt.help = true;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
app->opt.list = true;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
app->opt.bind_all = true;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
free(app->opt.output);
|
|
||||||
app->opt.output = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
free(app->opt.outfd);
|
|
||||||
app->opt.outfd = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "huh? getopt => %c (%d)\n", c, c);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failed)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
while (optind < argc) {
|
|
||||||
struct debug_stream *stream =
|
|
||||||
stream_alloc(app, argv[optind++], NULL);
|
|
||||||
stream->should_bind = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct debug_app app = {};
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
wl_list_init(&app.stream_list);
|
|
||||||
app.out_fd = -1;
|
|
||||||
|
|
||||||
if (parse_cmdline(&app, argc, argv) < 0) {
|
|
||||||
ret = 1;
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app.opt.help) {
|
|
||||||
print_help();
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!app.opt.list && !app.opt.bind_all &&
|
|
||||||
wl_list_empty(&app.stream_list)) {
|
|
||||||
fprintf(stderr, "Error: no options given.\n\n");
|
|
||||||
ret = 1;
|
|
||||||
print_help();
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app.opt.bind_all && !wl_list_empty(&app.stream_list)) {
|
|
||||||
fprintf(stderr, "Error: --all and specific stream names cannot be used simultaneously.\n");
|
|
||||||
ret = 1;
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app.opt.output && app.opt.outfd) {
|
|
||||||
fprintf(stderr, "Error: options --output and --outfd cannot be used simultaneously.\n");
|
|
||||||
ret = 1;
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.out_fd = setup_out_fd(app.opt.output, app.opt.outfd);
|
|
||||||
if (app.out_fd < 0) {
|
|
||||||
ret = 1;
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.dpy = wl_display_connect(NULL);
|
|
||||||
if (!app.dpy) {
|
|
||||||
fprintf(stderr, "Error: Could not connect to Wayland display: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
ret = 1;
|
|
||||||
goto out_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.registry = wl_display_get_registry(app.dpy);
|
|
||||||
wl_registry_add_listener(app.registry, ®istry_listener, &app);
|
|
||||||
wl_display_roundtrip(app.dpy);
|
|
||||||
|
|
||||||
if (!app.debug_iface) {
|
|
||||||
ret = 1;
|
|
||||||
fprintf(stderr,
|
|
||||||
"The Wayland server does not support %s interface.\n",
|
|
||||||
weston_debug_v1_interface.name);
|
|
||||||
goto out_conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_display_roundtrip(app.dpy); /* for weston_debug_v1::advertise */
|
|
||||||
|
|
||||||
if (app.opt.list)
|
|
||||||
list_streams(&app);
|
|
||||||
|
|
||||||
start_streams(&app);
|
|
||||||
|
|
||||||
weston_debug_v1_destroy(app.debug_iface);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
struct debug_stream *stream;
|
|
||||||
bool empty = true;
|
|
||||||
|
|
||||||
wl_list_for_each(stream, &app.stream_list, link) {
|
|
||||||
if (stream->obj) {
|
|
||||||
empty = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (wl_display_dispatch(app.dpy) < 0) {
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out_conn:
|
|
||||||
destroy_streams(&app);
|
|
||||||
|
|
||||||
/* Wait for server to close all files */
|
|
||||||
wl_display_roundtrip(app.dpy);
|
|
||||||
|
|
||||||
wl_registry_destroy(app.registry);
|
|
||||||
wl_display_disconnect(app.dpy);
|
|
||||||
|
|
||||||
out_parse:
|
|
||||||
if (app.out_fd != -1)
|
|
||||||
close(app.out_fd);
|
|
||||||
|
|
||||||
destroy_streams(&app);
|
|
||||||
free(app.opt.output);
|
|
||||||
free(app.opt.outfd);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
735
clients/weston-info.c
Normal file
|
|
@ -0,0 +1,735 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2012 Philipp Brüschweiler
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
|
* that the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "../shared/os-compatibility.h"
|
||||||
|
#include "presentation_timing-client-protocol.h"
|
||||||
|
|
||||||
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
|
||||||
|
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||||
|
|
||||||
|
typedef void (*print_info_t)(void *info);
|
||||||
|
typedef void (*destroy_info_t)(void *info);
|
||||||
|
|
||||||
|
struct global_info {
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t version;
|
||||||
|
char *interface;
|
||||||
|
|
||||||
|
print_info_t print;
|
||||||
|
destroy_info_t destroy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct output_mode {
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
uint32_t flags;
|
||||||
|
int32_t width, height;
|
||||||
|
int32_t refresh;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct output_info {
|
||||||
|
struct global_info global;
|
||||||
|
|
||||||
|
struct wl_output *output;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int32_t x, y;
|
||||||
|
int32_t physical_width, physical_height;
|
||||||
|
enum wl_output_subpixel subpixel;
|
||||||
|
enum wl_output_transform output_transform;
|
||||||
|
char *make;
|
||||||
|
char *model;
|
||||||
|
} geometry;
|
||||||
|
|
||||||
|
struct wl_list modes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shm_format {
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
uint32_t format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shm_info {
|
||||||
|
struct global_info global;
|
||||||
|
struct wl_shm *shm;
|
||||||
|
|
||||||
|
struct wl_list formats;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct seat_info {
|
||||||
|
struct global_info global;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct weston_info *info;
|
||||||
|
|
||||||
|
uint32_t capabilities;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int32_t repeat_rate;
|
||||||
|
int32_t repeat_delay;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct presentation_info {
|
||||||
|
struct global_info global;
|
||||||
|
struct presentation *presentation;
|
||||||
|
|
||||||
|
clockid_t clk_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_info {
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
|
||||||
|
struct wl_list infos;
|
||||||
|
bool roundtrip_needed;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
fail_on_null(void *p)
|
||||||
|
{
|
||||||
|
if (p == NULL) {
|
||||||
|
fprintf(stderr, "%s: out of memory\n", program_invocation_short_name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
xmalloc(size_t s)
|
||||||
|
{
|
||||||
|
return fail_on_null(malloc(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
xzalloc(size_t s)
|
||||||
|
{
|
||||||
|
return fail_on_null(calloc(1, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
xstrdup(const char *s)
|
||||||
|
{
|
||||||
|
return fail_on_null(strdup(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_global_info(void *data)
|
||||||
|
{
|
||||||
|
struct global_info *global = data;
|
||||||
|
|
||||||
|
printf("interface: '%s', version: %u, name: %u\n",
|
||||||
|
global->interface, global->version, global->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_global_info(struct weston_info *info,
|
||||||
|
struct global_info *global, uint32_t id,
|
||||||
|
const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
global->id = id;
|
||||||
|
global->version = version;
|
||||||
|
global->interface = xstrdup(interface);
|
||||||
|
|
||||||
|
wl_list_insert(info->infos.prev, &global->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_output_info(void *data)
|
||||||
|
{
|
||||||
|
struct output_info *output = data;
|
||||||
|
struct output_mode *mode;
|
||||||
|
const char *subpixel_orientation;
|
||||||
|
const char *transform;
|
||||||
|
|
||||||
|
print_global_info(data);
|
||||||
|
|
||||||
|
switch (output->geometry.subpixel) {
|
||||||
|
case WL_OUTPUT_SUBPIXEL_UNKNOWN:
|
||||||
|
subpixel_orientation = "unknown";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_SUBPIXEL_NONE:
|
||||||
|
subpixel_orientation = "none";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
|
||||||
|
subpixel_orientation = "horizontal rgb";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
|
||||||
|
subpixel_orientation = "horizontal bgr";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
|
||||||
|
subpixel_orientation = "vertical rgb";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
|
||||||
|
subpixel_orientation = "vertical bgr";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown subpixel orientation %u\n",
|
||||||
|
output->geometry.subpixel);
|
||||||
|
subpixel_orientation = "unexpected value";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (output->geometry.output_transform) {
|
||||||
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||||
|
transform = "normal";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_90:
|
||||||
|
transform = "90°";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_180:
|
||||||
|
transform = "180°";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_270:
|
||||||
|
transform = "270°";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||||
|
transform = "flipped";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||||
|
transform = "flipped 90°";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||||
|
transform = "flipped 180°";
|
||||||
|
break;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||||
|
transform = "flipped 270°";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown output transform %u\n",
|
||||||
|
output->geometry.output_transform);
|
||||||
|
transform = "unexpected value";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\tx: %d, y: %d,\n",
|
||||||
|
output->geometry.x, output->geometry.y);
|
||||||
|
printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
|
||||||
|
output->geometry.physical_width,
|
||||||
|
output->geometry.physical_height);
|
||||||
|
printf("\tmake: '%s', model: '%s',\n",
|
||||||
|
output->geometry.make, output->geometry.model);
|
||||||
|
printf("\tsubpixel_orientation: %s, output_transform: %s,\n",
|
||||||
|
subpixel_orientation, transform);
|
||||||
|
|
||||||
|
wl_list_for_each(mode, &output->modes, link) {
|
||||||
|
printf("\tmode:\n");
|
||||||
|
|
||||||
|
printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
|
||||||
|
mode->width, mode->height,
|
||||||
|
(float) mode->refresh / 1000);
|
||||||
|
|
||||||
|
printf("\t\tflags:");
|
||||||
|
if (mode->flags & WL_OUTPUT_MODE_CURRENT)
|
||||||
|
printf(" current");
|
||||||
|
if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
|
||||||
|
printf(" preferred");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_shm_info(void *data)
|
||||||
|
{
|
||||||
|
struct shm_info *shm = data;
|
||||||
|
struct shm_format *format;
|
||||||
|
|
||||||
|
print_global_info(data);
|
||||||
|
|
||||||
|
printf("\tformats:");
|
||||||
|
|
||||||
|
wl_list_for_each(format, &shm->formats, link)
|
||||||
|
switch (format->format) {
|
||||||
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
|
printf(" ARGB8888");
|
||||||
|
break;
|
||||||
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
|
printf(" XRGB8888");
|
||||||
|
break;
|
||||||
|
case WL_SHM_FORMAT_RGB565:
|
||||||
|
printf(" RGB565");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf(" unknown(%08x)", format->format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_seat_info(void *data)
|
||||||
|
{
|
||||||
|
struct seat_info *seat = data;
|
||||||
|
|
||||||
|
print_global_info(data);
|
||||||
|
|
||||||
|
printf("\tname: %s\n", seat->name);
|
||||||
|
printf("\tcapabilities:");
|
||||||
|
|
||||||
|
if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
|
||||||
|
printf(" pointer");
|
||||||
|
if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
|
||||||
|
printf(" keyboard");
|
||||||
|
if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
|
||||||
|
printf(" touch");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (seat->repeat_rate > 0)
|
||||||
|
printf("\tkeyboard repeat rate: %d\n", seat->repeat_rate);
|
||||||
|
if (seat->repeat_delay > 0)
|
||||||
|
printf("\tkeyboard repeat delay: %d\n", seat->repeat_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t format, int fd, uint32_t size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, struct wl_surface *surface,
|
||||||
|
struct wl_array *keys)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, uint32_t time, uint32_t key,
|
||||||
|
uint32_t state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, uint32_t mods_depressed,
|
||||||
|
uint32_t mods_latched, uint32_t mods_locked,
|
||||||
|
uint32_t group)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
|
||||||
|
int32_t rate, int32_t delay)
|
||||||
|
{
|
||||||
|
struct seat_info *seat = data;
|
||||||
|
|
||||||
|
seat->repeat_rate = rate;
|
||||||
|
seat->repeat_delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_keyboard_listener keyboard_listener = {
|
||||||
|
keyboard_handle_keymap,
|
||||||
|
keyboard_handle_enter,
|
||||||
|
keyboard_handle_leave,
|
||||||
|
keyboard_handle_key,
|
||||||
|
keyboard_handle_modifiers,
|
||||||
|
keyboard_handle_repeat_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
||||||
|
enum wl_seat_capability caps)
|
||||||
|
{
|
||||||
|
struct seat_info *seat = data;
|
||||||
|
|
||||||
|
seat->capabilities = caps;
|
||||||
|
|
||||||
|
/* we want listen for repeat_info from wl_keyboard, but only
|
||||||
|
* do so if the seat info is >= 4 and if we actually have a
|
||||||
|
* keyboard */
|
||||||
|
if (seat->global.version < 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
|
|
||||||
|
keyboard = wl_seat_get_keyboard(seat->seat);
|
||||||
|
wl_keyboard_add_listener(keyboard, &keyboard_listener,
|
||||||
|
seat);
|
||||||
|
|
||||||
|
seat->info->roundtrip_needed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_handle_name(void *data, struct wl_seat *wl_seat,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct seat_info *seat = data;
|
||||||
|
seat->name = xstrdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_seat_listener seat_listener = {
|
||||||
|
seat_handle_capabilities,
|
||||||
|
seat_handle_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_seat_info(void *data)
|
||||||
|
{
|
||||||
|
struct seat_info *seat = data;
|
||||||
|
|
||||||
|
wl_seat_destroy(seat->seat);
|
||||||
|
|
||||||
|
if (seat->name != NULL)
|
||||||
|
free(seat->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
|
||||||
|
{
|
||||||
|
struct seat_info *seat = xzalloc(sizeof *seat);
|
||||||
|
|
||||||
|
/* required to set roundtrip_needed to true in capabilities
|
||||||
|
* handler */
|
||||||
|
seat->info = info;
|
||||||
|
|
||||||
|
init_global_info(info, &seat->global, id, "wl_seat", version);
|
||||||
|
seat->global.print = print_seat_info;
|
||||||
|
seat->global.destroy = destroy_seat_info;
|
||||||
|
|
||||||
|
seat->seat = wl_registry_bind(info->registry,
|
||||||
|
id, &wl_seat_interface, MIN(version, 4));
|
||||||
|
wl_seat_add_listener(seat->seat, &seat_listener, seat);
|
||||||
|
|
||||||
|
seat->repeat_rate = seat->repeat_delay = -1;
|
||||||
|
|
||||||
|
info->roundtrip_needed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
||||||
|
{
|
||||||
|
struct shm_info *shm = data;
|
||||||
|
struct shm_format *shm_format = xzalloc(sizeof *shm_format);
|
||||||
|
|
||||||
|
wl_list_insert(&shm->formats, &shm_format->link);
|
||||||
|
shm_format->format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_shm_listener shm_listener = {
|
||||||
|
shm_handle_format,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_shm_info(void *data)
|
||||||
|
{
|
||||||
|
struct shm_info *shm = data;
|
||||||
|
struct shm_format *format, *tmp;
|
||||||
|
|
||||||
|
wl_list_for_each_safe(format, tmp, &shm->formats, link) {
|
||||||
|
wl_list_remove(&format->link);
|
||||||
|
free(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_shm_destroy(shm->shm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
|
||||||
|
{
|
||||||
|
struct shm_info *shm = xzalloc(sizeof *shm);
|
||||||
|
|
||||||
|
init_global_info(info, &shm->global, id, "wl_shm", version);
|
||||||
|
shm->global.print = print_shm_info;
|
||||||
|
shm->global.destroy = destroy_shm_info;
|
||||||
|
|
||||||
|
wl_list_init(&shm->formats);
|
||||||
|
|
||||||
|
shm->shm = wl_registry_bind(info->registry,
|
||||||
|
id, &wl_shm_interface, 1);
|
||||||
|
wl_shm_add_listener(shm->shm, &shm_listener, shm);
|
||||||
|
|
||||||
|
info->roundtrip_needed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_handle_geometry(void *data, struct wl_output *wl_output,
|
||||||
|
int32_t x, int32_t y,
|
||||||
|
int32_t physical_width, int32_t physical_height,
|
||||||
|
int32_t subpixel,
|
||||||
|
const char *make, const char *model,
|
||||||
|
int32_t output_transform)
|
||||||
|
{
|
||||||
|
struct output_info *output = data;
|
||||||
|
|
||||||
|
output->geometry.x = x;
|
||||||
|
output->geometry.y = y;
|
||||||
|
output->geometry.physical_width = physical_width;
|
||||||
|
output->geometry.physical_height = physical_height;
|
||||||
|
output->geometry.subpixel = subpixel;
|
||||||
|
output->geometry.make = xstrdup(make);
|
||||||
|
output->geometry.model = xstrdup(model);
|
||||||
|
output->geometry.output_transform = output_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_handle_mode(void *data, struct wl_output *wl_output,
|
||||||
|
uint32_t flags, int32_t width, int32_t height,
|
||||||
|
int32_t refresh)
|
||||||
|
{
|
||||||
|
struct output_info *output = data;
|
||||||
|
struct output_mode *mode = xmalloc(sizeof *mode);
|
||||||
|
|
||||||
|
mode->flags = flags;
|
||||||
|
mode->width = width;
|
||||||
|
mode->height = height;
|
||||||
|
mode->refresh = refresh;
|
||||||
|
|
||||||
|
wl_list_insert(output->modes.prev, &mode->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_output_listener output_listener = {
|
||||||
|
output_handle_geometry,
|
||||||
|
output_handle_mode,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_output_info(void *data)
|
||||||
|
{
|
||||||
|
struct output_info *output = data;
|
||||||
|
struct output_mode *mode, *tmp;
|
||||||
|
|
||||||
|
wl_output_destroy(output->output);
|
||||||
|
|
||||||
|
if (output->geometry.make != NULL)
|
||||||
|
free(output->geometry.make);
|
||||||
|
if (output->geometry.model != NULL)
|
||||||
|
free(output->geometry.model);
|
||||||
|
|
||||||
|
wl_list_for_each_safe(mode, tmp, &output->modes, link) {
|
||||||
|
wl_list_remove(&mode->link);
|
||||||
|
free(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
|
||||||
|
{
|
||||||
|
struct output_info *output = xzalloc(sizeof *output);
|
||||||
|
|
||||||
|
init_global_info(info, &output->global, id, "wl_output", version);
|
||||||
|
output->global.print = print_output_info;
|
||||||
|
output->global.destroy = destroy_output_info;
|
||||||
|
|
||||||
|
wl_list_init(&output->modes);
|
||||||
|
|
||||||
|
output->output = wl_registry_bind(info->registry, id,
|
||||||
|
&wl_output_interface, 1);
|
||||||
|
wl_output_add_listener(output->output, &output_listener,
|
||||||
|
output);
|
||||||
|
|
||||||
|
info->roundtrip_needed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_presentation_info(void *info)
|
||||||
|
{
|
||||||
|
struct presentation_info *prinfo = info;
|
||||||
|
|
||||||
|
presentation_destroy(prinfo->presentation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
clock_name(clockid_t clk_id)
|
||||||
|
{
|
||||||
|
static const char *names[] = {
|
||||||
|
[CLOCK_REALTIME] = "CLOCK_REALTIME",
|
||||||
|
[CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
|
||||||
|
[CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
|
||||||
|
[CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
|
||||||
|
[CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
|
||||||
|
[CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
|
||||||
|
return "unknown";
|
||||||
|
|
||||||
|
return names[clk_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_presentation_info(void *info)
|
||||||
|
{
|
||||||
|
struct presentation_info *prinfo = info;
|
||||||
|
|
||||||
|
print_global_info(info);
|
||||||
|
|
||||||
|
printf("\tpresentation clock id: %d (%s)\n",
|
||||||
|
prinfo->clk_id, clock_name(prinfo->clk_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
presentation_handle_clock_id(void *data, struct presentation *presentation,
|
||||||
|
uint32_t clk_id)
|
||||||
|
{
|
||||||
|
struct presentation_info *prinfo = data;
|
||||||
|
|
||||||
|
prinfo->clk_id = clk_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct presentation_listener presentation_listener = {
|
||||||
|
presentation_handle_clock_id
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_presentation_info(struct weston_info *info, uint32_t id, uint32_t version)
|
||||||
|
{
|
||||||
|
struct presentation_info *prinfo = xzalloc(sizeof *prinfo);
|
||||||
|
|
||||||
|
init_global_info(info, &prinfo->global, id, "presentation", version);
|
||||||
|
prinfo->global.print = print_presentation_info;
|
||||||
|
prinfo->global.destroy = destroy_presentation_info;
|
||||||
|
|
||||||
|
prinfo->clk_id = -1;
|
||||||
|
prinfo->presentation = wl_registry_bind(info->registry, id,
|
||||||
|
&presentation_interface, 1);
|
||||||
|
presentation_add_listener(prinfo->presentation, &presentation_listener,
|
||||||
|
prinfo);
|
||||||
|
|
||||||
|
info->roundtrip_needed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_global_info(void *data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_global_info(struct weston_info *info, uint32_t id,
|
||||||
|
const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
struct global_info *global = xzalloc(sizeof *global);
|
||||||
|
|
||||||
|
init_global_info(info, global, id, interface, version);
|
||||||
|
global->print = print_global_info;
|
||||||
|
global->destroy = destroy_global_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
global_handler(void *data, struct wl_registry *registry, uint32_t id,
|
||||||
|
const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
struct weston_info *info = data;
|
||||||
|
|
||||||
|
if (!strcmp(interface, "wl_seat"))
|
||||||
|
add_seat_info(info, id, version);
|
||||||
|
else if (!strcmp(interface, "wl_shm"))
|
||||||
|
add_shm_info(info, id, version);
|
||||||
|
else if (!strcmp(interface, "wl_output"))
|
||||||
|
add_output_info(info, id, version);
|
||||||
|
else if (!strcmp(interface, "presentation"))
|
||||||
|
add_presentation_info(info, id, version);
|
||||||
|
else
|
||||||
|
add_global_info(info, id, interface, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
global_handler,
|
||||||
|
global_remove_handler
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_infos(struct wl_list *infos)
|
||||||
|
{
|
||||||
|
struct global_info *info;
|
||||||
|
|
||||||
|
wl_list_for_each(info, infos, link)
|
||||||
|
info->print(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_info(void *data)
|
||||||
|
{
|
||||||
|
struct global_info *global = data;
|
||||||
|
|
||||||
|
global->destroy(data);
|
||||||
|
wl_list_remove(&global->link);
|
||||||
|
free(global->interface);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_infos(struct wl_list *infos)
|
||||||
|
{
|
||||||
|
struct global_info *info, *tmp;
|
||||||
|
wl_list_for_each_safe(info, tmp, infos, link)
|
||||||
|
destroy_info(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct weston_info info;
|
||||||
|
|
||||||
|
info.display = wl_display_connect(NULL);
|
||||||
|
if (!info.display) {
|
||||||
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_init(&info.infos);
|
||||||
|
|
||||||
|
info.registry = wl_display_get_registry(info.display);
|
||||||
|
wl_registry_add_listener(info.registry, ®istry_listener, &info);
|
||||||
|
|
||||||
|
do {
|
||||||
|
info.roundtrip_needed = false;
|
||||||
|
wl_display_roundtrip(info.display);
|
||||||
|
} while (info.roundtrip_needed);
|
||||||
|
|
||||||
|
print_infos(&info.infos);
|
||||||
|
destroy_infos(&info.infos);
|
||||||
|
|
||||||
|
wl_registry_destroy(info.registry);
|
||||||
|
wl_display_disconnect(info.display);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1,42 +1,38 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2012 Intel Corporation
|
* Copyright © 2012 Intel Corporation
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* its documentation for any purpose is hereby granted without fee, provided
|
||||||
* to deal in the Software without restriction, including without limitation
|
* that the above copyright notice appear in all copies and that both that
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* copyright notice and this permission notice appear in supporting
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* documentation, and that the name of the copyright holders not be used in
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* advertising or publicity pertaining to distribution of the software
|
||||||
|
* without specific, written prior permission. The copyright holders make
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* Software.
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
*
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include <config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "input-method-unstable-v1-client-protocol.h"
|
#include "input-method-client-protocol.h"
|
||||||
#include "shared/helpers.h"
|
|
||||||
|
|
||||||
enum compose_state {
|
enum compose_state {
|
||||||
state_normal,
|
state_normal,
|
||||||
|
|
@ -57,8 +53,8 @@ typedef void (*keyboard_input_key_handler_t)(struct simple_im *keyboard,
|
||||||
enum wl_keyboard_key_state state);
|
enum wl_keyboard_key_state state);
|
||||||
|
|
||||||
struct simple_im {
|
struct simple_im {
|
||||||
struct zwp_input_method_v1 *input_method;
|
struct wl_input_method *input_method;
|
||||||
struct zwp_input_method_context_v1 *context;
|
struct wl_input_method_context *context;
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_keyboard *keyboard;
|
struct wl_keyboard *keyboard;
|
||||||
|
|
@ -106,11 +102,9 @@ static const uint32_t ignore_keys_on_compose[] = {
|
||||||
XKB_KEY_Shift_R
|
XKB_KEY_Shift_R
|
||||||
};
|
};
|
||||||
|
|
||||||
static int running = 1;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_surrounding_text(void *data,
|
handle_surrounding_text(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
const char *text,
|
const char *text,
|
||||||
uint32_t cursor,
|
uint32_t cursor,
|
||||||
uint32_t anchor)
|
uint32_t anchor)
|
||||||
|
|
@ -120,7 +114,7 @@ handle_surrounding_text(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_reset(void *data,
|
handle_reset(void *data,
|
||||||
struct zwp_input_method_context_v1 *context)
|
struct wl_input_method_context *context)
|
||||||
{
|
{
|
||||||
struct simple_im *keyboard = data;
|
struct simple_im *keyboard = data;
|
||||||
|
|
||||||
|
|
@ -131,7 +125,7 @@ handle_reset(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_content_type(void *data,
|
handle_content_type(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
uint32_t hint,
|
uint32_t hint,
|
||||||
uint32_t purpose)
|
uint32_t purpose)
|
||||||
{
|
{
|
||||||
|
|
@ -139,7 +133,7 @@ handle_content_type(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_invoke_action(void *data,
|
handle_invoke_action(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
uint32_t button,
|
uint32_t button,
|
||||||
uint32_t index)
|
uint32_t index)
|
||||||
{
|
{
|
||||||
|
|
@ -147,7 +141,7 @@ handle_invoke_action(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_commit_state(void *data,
|
handle_commit_state(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
struct simple_im *keyboard = data;
|
struct simple_im *keyboard = data;
|
||||||
|
|
@ -157,12 +151,12 @@ handle_commit_state(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_preferred_language(void *data,
|
handle_preferred_language(void *data,
|
||||||
struct zwp_input_method_context_v1 *context,
|
struct wl_input_method_context *context,
|
||||||
const char *language)
|
const char *language)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_input_method_context_v1_listener input_method_context_listener = {
|
static const struct wl_input_method_context_listener input_method_context_listener = {
|
||||||
handle_surrounding_text,
|
handle_surrounding_text,
|
||||||
handle_reset,
|
handle_reset,
|
||||||
handle_content_type,
|
handle_content_type,
|
||||||
|
|
@ -196,19 +190,19 @@ input_method_keyboard_keymap(void *data,
|
||||||
xkb_keymap_new_from_string(keyboard->xkb_context,
|
xkb_keymap_new_from_string(keyboard->xkb_context,
|
||||||
map_str,
|
map_str,
|
||||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
0);
|
||||||
|
|
||||||
munmap(map_str, size);
|
munmap(map_str, size);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (!keyboard->keymap) {
|
if (!keyboard->keymap) {
|
||||||
fprintf(stderr, "Failed to compile keymap\n");
|
fprintf(stderr, "failed to compile keymap\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard->state = xkb_state_new(keyboard->keymap);
|
keyboard->state = xkb_state_new(keyboard->keymap);
|
||||||
if (!keyboard->state) {
|
if (!keyboard->state) {
|
||||||
fprintf(stderr, "Failed to create XKB state\n");
|
fprintf(stderr, "failed to create XKB state\n");
|
||||||
xkb_keymap_unref(keyboard->keymap);
|
xkb_keymap_unref(keyboard->keymap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +255,7 @@ input_method_keyboard_modifiers(void *data,
|
||||||
uint32_t group)
|
uint32_t group)
|
||||||
{
|
{
|
||||||
struct simple_im *keyboard = data;
|
struct simple_im *keyboard = data;
|
||||||
struct zwp_input_method_context_v1 *context = keyboard->context;
|
struct wl_input_method_context *context = keyboard->context;
|
||||||
xkb_mod_mask_t mask;
|
xkb_mod_mask_t mask;
|
||||||
|
|
||||||
xkb_state_update_mask(keyboard->state, mods_depressed,
|
xkb_state_update_mask(keyboard->state, mods_depressed,
|
||||||
|
|
@ -278,9 +272,9 @@ input_method_keyboard_modifiers(void *data,
|
||||||
if (mask & keyboard->shift_mask)
|
if (mask & keyboard->shift_mask)
|
||||||
keyboard->modifiers |= MOD_SHIFT_MASK;
|
keyboard->modifiers |= MOD_SHIFT_MASK;
|
||||||
|
|
||||||
zwp_input_method_context_v1_modifiers(context, serial,
|
wl_input_method_context_modifiers(context, serial,
|
||||||
mods_depressed, mods_latched,
|
mods_depressed, mods_depressed,
|
||||||
mods_locked, group);
|
mods_latched, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_keyboard_listener input_method_keyboard_listener = {
|
static const struct wl_keyboard_listener input_method_keyboard_listener = {
|
||||||
|
|
@ -293,23 +287,23 @@ static const struct wl_keyboard_listener input_method_keyboard_listener = {
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_method_activate(void *data,
|
input_method_activate(void *data,
|
||||||
struct zwp_input_method_v1 *input_method,
|
struct wl_input_method *input_method,
|
||||||
struct zwp_input_method_context_v1 *context)
|
struct wl_input_method_context *context)
|
||||||
{
|
{
|
||||||
struct simple_im *keyboard = data;
|
struct simple_im *keyboard = data;
|
||||||
|
|
||||||
if (keyboard->context)
|
if (keyboard->context)
|
||||||
zwp_input_method_context_v1_destroy(keyboard->context);
|
wl_input_method_context_destroy(keyboard->context);
|
||||||
|
|
||||||
keyboard->compose_state = state_normal;
|
keyboard->compose_state = state_normal;
|
||||||
|
|
||||||
keyboard->serial = 0;
|
keyboard->serial = 0;
|
||||||
|
|
||||||
keyboard->context = context;
|
keyboard->context = context;
|
||||||
zwp_input_method_context_v1_add_listener(context,
|
wl_input_method_context_add_listener(context,
|
||||||
&input_method_context_listener,
|
&input_method_context_listener,
|
||||||
keyboard);
|
keyboard);
|
||||||
keyboard->keyboard = zwp_input_method_context_v1_grab_keyboard(context);
|
keyboard->keyboard = wl_input_method_context_grab_keyboard(context);
|
||||||
wl_keyboard_add_listener(keyboard->keyboard,
|
wl_keyboard_add_listener(keyboard->keyboard,
|
||||||
&input_method_keyboard_listener,
|
&input_method_keyboard_listener,
|
||||||
keyboard);
|
keyboard);
|
||||||
|
|
@ -317,19 +311,19 @@ input_method_activate(void *data,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_method_deactivate(void *data,
|
input_method_deactivate(void *data,
|
||||||
struct zwp_input_method_v1 *input_method,
|
struct wl_input_method *input_method,
|
||||||
struct zwp_input_method_context_v1 *context)
|
struct wl_input_method_context *context)
|
||||||
{
|
{
|
||||||
struct simple_im *keyboard = data;
|
struct simple_im *keyboard = data;
|
||||||
|
|
||||||
if (!keyboard->context)
|
if (!keyboard->context)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zwp_input_method_context_v1_destroy(keyboard->context);
|
wl_input_method_context_destroy(keyboard->context);
|
||||||
keyboard->context = NULL;
|
keyboard->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_input_method_v1_listener input_method_listener = {
|
static const struct wl_input_method_listener input_method_listener = {
|
||||||
input_method_activate,
|
input_method_activate,
|
||||||
input_method_deactivate
|
input_method_deactivate
|
||||||
};
|
};
|
||||||
|
|
@ -340,12 +334,12 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
{
|
{
|
||||||
struct simple_im *keyboard = data;
|
struct simple_im *keyboard = data;
|
||||||
|
|
||||||
if (!strcmp(interface, "zwp_input_method_v1")) {
|
if (!strcmp(interface, "wl_input_method")) {
|
||||||
keyboard->input_method =
|
keyboard->input_method =
|
||||||
wl_registry_bind(registry, name,
|
wl_registry_bind(registry, name,
|
||||||
&zwp_input_method_v1_interface, 1);
|
&wl_input_method_interface, 1);
|
||||||
zwp_input_method_v1_add_listener(keyboard->input_method,
|
wl_input_method_add_listener(keyboard->input_method,
|
||||||
&input_method_listener, keyboard);
|
&input_method_listener, keyboard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -384,7 +378,7 @@ simple_im_key_handler(struct simple_im *keyboard,
|
||||||
uint32_t serial, uint32_t time, uint32_t key, uint32_t sym,
|
uint32_t serial, uint32_t time, uint32_t key, uint32_t sym,
|
||||||
enum wl_keyboard_key_state state)
|
enum wl_keyboard_key_state state)
|
||||||
{
|
{
|
||||||
struct zwp_input_method_context_v1 *context = keyboard->context;
|
struct wl_input_method_context *context = keyboard->context;
|
||||||
char text[64];
|
char text[64];
|
||||||
|
|
||||||
if (sym == XKB_KEY_Multi_key &&
|
if (sym == XKB_KEY_Multi_key &&
|
||||||
|
|
@ -397,18 +391,14 @@ simple_im_key_handler(struct simple_im *keyboard,
|
||||||
|
|
||||||
if (keyboard->compose_state == state_compose) {
|
if (keyboard->compose_state == state_compose) {
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
const struct compose_seq *cs;
|
struct compose_seq *cs;
|
||||||
|
|
||||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(ignore_keys_on_compose); i++) {
|
for (i = 0; i < sizeof(ignore_keys_on_compose) / sizeof(ignore_keys_on_compose[0]); i++) {
|
||||||
if (sym == ignore_keys_on_compose[i]) {
|
if (sym == ignore_keys_on_compose[i]) {
|
||||||
zwp_input_method_context_v1_key(context,
|
wl_input_method_context_key(context, keyboard->serial, time, key, state);
|
||||||
keyboard->serial,
|
|
||||||
time,
|
|
||||||
key,
|
|
||||||
state);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -418,21 +408,21 @@ simple_im_key_handler(struct simple_im *keyboard,
|
||||||
keyboard->compose_seq.keys[i] = sym;
|
keyboard->compose_seq.keys[i] = sym;
|
||||||
|
|
||||||
cs = bsearch (&keyboard->compose_seq, compose_seqs,
|
cs = bsearch (&keyboard->compose_seq, compose_seqs,
|
||||||
ARRAY_LENGTH(compose_seqs),
|
sizeof(compose_seqs) / sizeof(compose_seqs[0]),
|
||||||
sizeof(compose_seqs[0]), compare_compose_keys);
|
sizeof(compose_seqs[0]), compare_compose_keys);
|
||||||
|
|
||||||
if (cs) {
|
if (cs) {
|
||||||
if (cs->keys[i + 1] == 0) {
|
if (cs->keys[i + 1] == 0) {
|
||||||
zwp_input_method_context_v1_preedit_cursor(keyboard->context,
|
wl_input_method_context_preedit_cursor(keyboard->context,
|
||||||
0);
|
0);
|
||||||
zwp_input_method_context_v1_preedit_string(keyboard->context,
|
wl_input_method_context_preedit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
"", "");
|
"", "");
|
||||||
zwp_input_method_context_v1_cursor_position(keyboard->context,
|
wl_input_method_context_cursor_position(keyboard->context,
|
||||||
0, 0);
|
0, 0);
|
||||||
zwp_input_method_context_v1_commit_string(keyboard->context,
|
wl_input_method_context_commit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
cs->text);
|
cs->text);
|
||||||
keyboard->compose_state = state_normal;
|
keyboard->compose_state = state_normal;
|
||||||
} else {
|
} else {
|
||||||
uint32_t j = 0, idx = 0;
|
uint32_t j = 0, idx = 0;
|
||||||
|
|
@ -441,12 +431,12 @@ simple_im_key_handler(struct simple_im *keyboard,
|
||||||
idx += xkb_keysym_to_utf8(cs->keys[j], text + idx, sizeof(text) - idx);
|
idx += xkb_keysym_to_utf8(cs->keys[j], text + idx, sizeof(text) - idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
zwp_input_method_context_v1_preedit_cursor(keyboard->context,
|
wl_input_method_context_preedit_cursor(keyboard->context,
|
||||||
strlen(text));
|
strlen(text));
|
||||||
zwp_input_method_context_v1_preedit_string(keyboard->context,
|
wl_input_method_context_preedit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
text,
|
text,
|
||||||
text);
|
text);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint32_t j = 0, idx = 0;
|
uint32_t j = 0, idx = 0;
|
||||||
|
|
@ -454,55 +444,47 @@ simple_im_key_handler(struct simple_im *keyboard,
|
||||||
for (; j <= i; j++) {
|
for (; j <= i; j++) {
|
||||||
idx += xkb_keysym_to_utf8(keyboard->compose_seq.keys[j], text + idx, sizeof(text) - idx);
|
idx += xkb_keysym_to_utf8(keyboard->compose_seq.keys[j], text + idx, sizeof(text) - idx);
|
||||||
}
|
}
|
||||||
zwp_input_method_context_v1_preedit_cursor(keyboard->context,
|
wl_input_method_context_preedit_cursor(keyboard->context,
|
||||||
0);
|
0);
|
||||||
zwp_input_method_context_v1_preedit_string(keyboard->context,
|
wl_input_method_context_preedit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
"", "");
|
"", "");
|
||||||
zwp_input_method_context_v1_cursor_position(keyboard->context,
|
wl_input_method_context_cursor_position(keyboard->context,
|
||||||
0, 0);
|
0, 0);
|
||||||
zwp_input_method_context_v1_commit_string(keyboard->context,
|
wl_input_method_context_commit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
text);
|
text);
|
||||||
keyboard->compose_state = state_normal;
|
keyboard->compose_state = state_normal;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0) {
|
if (xkb_keysym_to_utf8(sym, text, sizeof(text)) <= 0) {
|
||||||
zwp_input_method_context_v1_key(context, serial, time, key, state);
|
wl_input_method_context_key(context, serial, time, key, state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zwp_input_method_context_v1_cursor_position(keyboard->context,
|
wl_input_method_context_cursor_position(keyboard->context,
|
||||||
0, 0);
|
0, 0);
|
||||||
zwp_input_method_context_v1_commit_string(keyboard->context,
|
wl_input_method_context_commit_string(keyboard->context,
|
||||||
keyboard->serial,
|
keyboard->serial,
|
||||||
text);
|
text);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
signal_int(int signum)
|
|
||||||
{
|
|
||||||
running = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct simple_im simple_im;
|
struct simple_im simple_im;
|
||||||
struct sigaction sigint;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
memset(&simple_im, 0, sizeof(simple_im));
|
memset(&simple_im, 0, sizeof(simple_im));
|
||||||
|
|
||||||
simple_im.display = wl_display_connect(NULL);
|
simple_im.display = wl_display_connect(NULL);
|
||||||
if (simple_im.display == NULL) {
|
if (simple_im.display == NULL) {
|
||||||
fprintf(stderr, "Failed to connect to server: %s\n",
|
fprintf(stderr, "failed to connect to server: %m\n");
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -512,10 +494,10 @@ main(int argc, char *argv[])
|
||||||
wl_display_roundtrip(simple_im.display);
|
wl_display_roundtrip(simple_im.display);
|
||||||
if (simple_im.input_method == NULL) {
|
if (simple_im.input_method == NULL) {
|
||||||
fprintf(stderr, "No input_method global\n");
|
fprintf(stderr, "No input_method global\n");
|
||||||
return -1;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
simple_im.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
simple_im.xkb_context = xkb_context_new(0);
|
||||||
if (simple_im.xkb_context == NULL) {
|
if (simple_im.xkb_context == NULL) {
|
||||||
fprintf(stderr, "Failed to create XKB context\n");
|
fprintf(stderr, "Failed to create XKB context\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -524,34 +506,12 @@ main(int argc, char *argv[])
|
||||||
simple_im.context = NULL;
|
simple_im.context = NULL;
|
||||||
simple_im.key_handler = simple_im_key_handler;
|
simple_im.key_handler = simple_im_key_handler;
|
||||||
|
|
||||||
sigint.sa_handler = signal_int;
|
while (ret != -1)
|
||||||
sigemptyset(&sigint.sa_mask);
|
|
||||||
sigint.sa_flags = SA_RESETHAND;
|
|
||||||
sigaction(SIGINT, &sigint, NULL);
|
|
||||||
|
|
||||||
while (running && ret != -1)
|
|
||||||
ret = wl_display_dispatch(simple_im.display);
|
ret = wl_display_dispatch(simple_im.display);
|
||||||
|
|
||||||
if (simple_im.input_method)
|
|
||||||
zwp_input_method_v1_destroy(simple_im.input_method);
|
|
||||||
|
|
||||||
if (simple_im.context)
|
|
||||||
zwp_input_method_context_v1_destroy(simple_im.context);
|
|
||||||
|
|
||||||
if (simple_im.keyboard)
|
|
||||||
wl_keyboard_destroy(simple_im.keyboard);
|
|
||||||
|
|
||||||
xkb_context_unref(simple_im.xkb_context);
|
|
||||||
xkb_state_unref(simple_im.state);
|
|
||||||
xkb_keymap_unref(simple_im.keymap);
|
|
||||||
|
|
||||||
wl_registry_destroy(simple_im.registry);
|
|
||||||
wl_display_flush(simple_im.display);
|
|
||||||
wl_display_disconnect(simple_im.display);
|
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
fprintf(stderr, "Dispatch error: %s\n", strerror(errno));
|
fprintf(stderr, "Dispatch error: %m\n");
|
||||||
return -1;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
3334
clients/window.c
365
clients/window.h
|
|
@ -1,24 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2008 Kristian Høgsberg
|
* Copyright © 2008 Kristian Høgsberg
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
* to deal in the Software without restriction, including without limitation
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
* that the name of the copyright holders not be used in advertising or
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice (including the next
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
* Software.
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
*
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* OF THIS SOFTWARE.
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _WINDOW_H_
|
#ifndef _WINDOW_H_
|
||||||
|
|
@ -26,22 +25,24 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <libweston/config-parser.h>
|
#include "../shared/config-parser.h"
|
||||||
#include <libweston/zalloc.h>
|
#include "../shared/zalloc.h"
|
||||||
#include "shared/platform.h"
|
#include "../shared/platform.h"
|
||||||
|
|
||||||
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
|
||||||
|
#define container_of(ptr, type, member) ({ \
|
||||||
|
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||||
|
|
||||||
struct window;
|
struct window;
|
||||||
struct widget;
|
struct widget;
|
||||||
struct display;
|
struct display;
|
||||||
struct input;
|
struct input;
|
||||||
struct output;
|
struct output;
|
||||||
struct tablet;
|
|
||||||
struct tablet_tool;
|
|
||||||
|
|
||||||
struct task {
|
struct task {
|
||||||
void (*run)(struct task *task, uint32_t events);
|
void (*run)(struct task *task, uint32_t events);
|
||||||
|
|
@ -55,6 +56,17 @@ struct rectangle {
|
||||||
int32_t height;
|
int32_t height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void *
|
||||||
|
fail_on_null(void *p);
|
||||||
|
void *
|
||||||
|
xmalloc(size_t s);
|
||||||
|
void *
|
||||||
|
xzalloc(size_t s);
|
||||||
|
char *
|
||||||
|
xstrdup(const char *s);
|
||||||
|
void *
|
||||||
|
xrealloc(char *p, size_t s);
|
||||||
|
|
||||||
struct display *
|
struct display *
|
||||||
display_create(int *argc, char *argv[]);
|
display_create(int *argc, char *argv[]);
|
||||||
|
|
||||||
|
|
@ -73,12 +85,12 @@ display_get_display(struct display *display);
|
||||||
int
|
int
|
||||||
display_has_subcompositor(struct display *display);
|
display_has_subcompositor(struct display *display);
|
||||||
|
|
||||||
|
cairo_device_t *
|
||||||
|
display_get_cairo_device(struct display *display);
|
||||||
|
|
||||||
struct wl_compositor *
|
struct wl_compositor *
|
||||||
display_get_compositor(struct display *display);
|
display_get_compositor(struct display *display);
|
||||||
|
|
||||||
struct wp_single_pixel_buffer_manager_v1 *
|
|
||||||
display_get_single_pixel_buffer_manager(struct display *display);
|
|
||||||
|
|
||||||
struct output *
|
struct output *
|
||||||
display_get_output(struct display *display);
|
display_get_output(struct display *display);
|
||||||
|
|
||||||
|
|
@ -116,11 +128,29 @@ display_set_output_configure_handler(struct display *display,
|
||||||
struct wl_data_source *
|
struct wl_data_source *
|
||||||
display_create_data_source(struct display *display);
|
display_create_data_source(struct display *display);
|
||||||
|
|
||||||
|
#ifdef EGL_NO_DISPLAY
|
||||||
|
EGLDisplay
|
||||||
|
display_get_egl_display(struct display *d);
|
||||||
|
|
||||||
|
EGLConfig
|
||||||
|
display_get_argb_egl_config(struct display *d);
|
||||||
|
|
||||||
|
int
|
||||||
|
display_acquire_window_surface(struct display *display,
|
||||||
|
struct window *window,
|
||||||
|
EGLContext ctx);
|
||||||
|
void
|
||||||
|
display_release_window_surface(struct display *display,
|
||||||
|
struct window *window);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SURFACE_OPAQUE 0x01
|
#define SURFACE_OPAQUE 0x01
|
||||||
#define SURFACE_SHM 0x02
|
#define SURFACE_SHM 0x02
|
||||||
|
|
||||||
#define SURFACE_HINT_RESIZE 0x10
|
#define SURFACE_HINT_RESIZE 0x10
|
||||||
|
|
||||||
|
#define SURFACE_HINT_RGB565 0x100
|
||||||
|
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
display_create_surface(struct display *display,
|
display_create_surface(struct display *display,
|
||||||
struct wl_surface *surface,
|
struct wl_surface *surface,
|
||||||
|
|
@ -150,9 +180,6 @@ display_run(struct display *d);
|
||||||
void
|
void
|
||||||
display_exit(struct display *d);
|
display_exit(struct display *d);
|
||||||
|
|
||||||
int
|
|
||||||
display_get_data_device_manager_version(struct display *d);
|
|
||||||
|
|
||||||
enum cursor_type {
|
enum cursor_type {
|
||||||
CURSOR_BOTTOM_LEFT,
|
CURSOR_BOTTOM_LEFT,
|
||||||
CURSOR_BOTTOM_RIGHT,
|
CURSOR_BOTTOM_RIGHT,
|
||||||
|
|
@ -167,9 +194,6 @@ enum cursor_type {
|
||||||
CURSOR_IBEAM,
|
CURSOR_IBEAM,
|
||||||
CURSOR_HAND1,
|
CURSOR_HAND1,
|
||||||
CURSOR_WATCH,
|
CURSOR_WATCH,
|
||||||
CURSOR_DND_MOVE,
|
|
||||||
CURSOR_DND_COPY,
|
|
||||||
CURSOR_DND_FORBIDDEN,
|
|
||||||
|
|
||||||
CURSOR_BLANK
|
CURSOR_BLANK
|
||||||
};
|
};
|
||||||
|
|
@ -199,29 +223,6 @@ typedef void (*window_output_handler_t)(struct window *window, struct output *ou
|
||||||
typedef void (*window_state_changed_handler_t)(struct window *window,
|
typedef void (*window_state_changed_handler_t)(struct window *window,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
|
||||||
typedef void (*window_locked_pointer_motion_handler_t)(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
uint32_t time,
|
|
||||||
float x, float y,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*locked_pointer_locked_handler_t)(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*locked_pointer_unlocked_handler_t)(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*confined_pointer_confined_handler_t)(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*confined_pointer_unconfined_handler_t)(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*widget_resize_handler_t)(struct widget *widget,
|
typedef void (*widget_resize_handler_t)(struct widget *widget,
|
||||||
int32_t width, int32_t height,
|
int32_t width, int32_t height,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
@ -261,87 +262,15 @@ typedef void (*widget_touch_motion_handler_t)(struct widget *widget,
|
||||||
float x,
|
float x,
|
||||||
float y,
|
float y,
|
||||||
void *data);
|
void *data);
|
||||||
typedef void (*widget_touch_frame_handler_t)(struct widget *widget,
|
typedef void (*widget_touch_frame_handler_t)(struct widget *widget,
|
||||||
struct input *input, void *data);
|
struct input *input, void *data);
|
||||||
typedef void (*widget_touch_cancel_handler_t)(struct widget *widget,
|
typedef void (*widget_touch_cancel_handler_t)(struct widget *widget,
|
||||||
struct input *input, void *data);
|
struct input *input, void *data);
|
||||||
typedef void (*widget_axis_handler_t)(struct widget *widget,
|
typedef void (*widget_axis_handler_t)(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
uint32_t axis,
|
uint32_t axis,
|
||||||
wl_fixed_t value,
|
wl_fixed_t value,
|
||||||
void *data);
|
void *data);
|
||||||
typedef int (*widget_tablet_tool_motion_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
float x, float y,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_down_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_up_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_pressure_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
uint32_t pressure,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_distance_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
uint32_t distance,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_tilt_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
int32_t tilt_x, int32_t tilt_y,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_rotation_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
int32_t rotation,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_slider_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
int32_t slider,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_wheel_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
wl_fixed_t degrees,
|
|
||||||
int32_t clicks,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_proximity_in_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
struct tablet *tablet,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_proximity_out_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_button_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
uint32_t button,
|
|
||||||
uint32_t state,
|
|
||||||
void *data);
|
|
||||||
typedef void (*widget_tablet_tool_frame_handler_t)(struct widget *widget,
|
|
||||||
struct tablet_tool *tool,
|
|
||||||
uint32_t time,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*widget_pointer_frame_handler_t)(struct widget *widget,
|
|
||||||
struct input *input,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*widget_axis_source_handler_t)(struct widget *widget,
|
|
||||||
struct input *input,
|
|
||||||
uint32_t source,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*widget_axis_stop_handler_t)(struct widget *widget,
|
|
||||||
struct input *input,
|
|
||||||
uint32_t time,
|
|
||||||
uint32_t axis,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*widget_axis_discrete_handler_t)(struct widget *widget,
|
|
||||||
struct input *input,
|
|
||||||
uint32_t axis,
|
|
||||||
int32_t discrete,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
struct window *
|
struct window *
|
||||||
window_create(struct display *display);
|
window_create(struct display *display);
|
||||||
|
|
@ -358,6 +287,11 @@ window_has_focus(struct window *window);
|
||||||
|
|
||||||
typedef void (*menu_func_t)(void *data, struct input *input, int index);
|
typedef void (*menu_func_t)(void *data, struct input *input, int index);
|
||||||
|
|
||||||
|
struct window *
|
||||||
|
window_create_menu(struct display *display,
|
||||||
|
struct input *input, uint32_t time,
|
||||||
|
menu_func_t func, const char **entries, int count,
|
||||||
|
void *user_data);
|
||||||
void
|
void
|
||||||
window_show_menu(struct display *display,
|
window_show_menu(struct display *display,
|
||||||
struct input *input, uint32_t time, struct window *parent,
|
struct input *input, uint32_t time, struct window *parent,
|
||||||
|
|
@ -414,34 +348,9 @@ window_schedule_redraw(struct window *window);
|
||||||
void
|
void
|
||||||
window_schedule_resize(struct window *window, int width, int height);
|
window_schedule_resize(struct window *window, int width, int height);
|
||||||
|
|
||||||
int
|
|
||||||
window_lock_pointer(struct window *window, struct input *input);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
window_unlock_pointer(struct window *window);
|
window_damage(struct window *window, int32_t x, int32_t y,
|
||||||
|
int32_t width, int32_t height);
|
||||||
void
|
|
||||||
widget_set_locked_pointer_cursor_hint(struct widget *widget,
|
|
||||||
float x, float y);
|
|
||||||
|
|
||||||
int
|
|
||||||
window_confine_pointer_to_rectangles(struct window *window,
|
|
||||||
struct input *input,
|
|
||||||
struct rectangle *rectangles,
|
|
||||||
int num_rectangles);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_update_confine_rectangles(struct window *window,
|
|
||||||
struct rectangle *rectangles,
|
|
||||||
int num_rectangles);
|
|
||||||
|
|
||||||
int
|
|
||||||
window_confine_pointer_to_widget(struct window *window,
|
|
||||||
struct widget *widget,
|
|
||||||
struct input *input);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_unconfine_pointer(struct window *window);
|
|
||||||
|
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
window_get_surface(struct window *window);
|
window_get_surface(struct window *window);
|
||||||
|
|
@ -453,6 +362,7 @@ struct wl_subsurface *
|
||||||
widget_get_wl_subsurface(struct widget *widget);
|
widget_get_wl_subsurface(struct widget *widget);
|
||||||
|
|
||||||
enum window_buffer_type {
|
enum window_buffer_type {
|
||||||
|
WINDOW_BUFFER_TYPE_EGL_WINDOW,
|
||||||
WINDOW_BUFFER_TYPE_SHM,
|
WINDOW_BUFFER_TYPE_SHM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -519,62 +429,23 @@ void
|
||||||
window_set_state_changed_handler(struct window *window,
|
window_set_state_changed_handler(struct window *window,
|
||||||
window_state_changed_handler_t handler);
|
window_state_changed_handler_t handler);
|
||||||
|
|
||||||
void
|
|
||||||
window_set_pointer_locked_handler(struct window *window,
|
|
||||||
locked_pointer_locked_handler_t locked,
|
|
||||||
locked_pointer_unlocked_handler_t unlocked);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_set_pointer_confined_handler(struct window *window,
|
|
||||||
confined_pointer_confined_handler_t confined,
|
|
||||||
confined_pointer_unconfined_handler_t unconfined);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_set_locked_pointer_motion_handler(
|
|
||||||
struct window *window, window_locked_pointer_motion_handler_t handler);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_set_shadow(struct window *window);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_unset_shadow(struct window *window);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
window_set_title(struct window *window, const char *title);
|
window_set_title(struct window *window, const char *title);
|
||||||
|
|
||||||
void
|
|
||||||
window_set_appid(struct window *window, const char *appid);
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
window_get_title(struct window *window);
|
window_get_title(struct window *window);
|
||||||
|
|
||||||
const char *
|
|
||||||
window_get_appid(struct window *window);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
window_set_text_cursor_position(struct window *window, int32_t x, int32_t y);
|
window_set_text_cursor_position(struct window *window, int32_t x, int32_t y);
|
||||||
|
|
||||||
enum render_intent {
|
enum preferred_format {
|
||||||
RENDER_INTENT_PERCEPTUAL,
|
WINDOW_PREFERRED_FORMAT_NONE,
|
||||||
RENDER_INTENT_RELATIVE,
|
WINDOW_PREFERRED_FORMAT_RGB565
|
||||||
RENDER_INTENT_RELATIVE_BPC,
|
|
||||||
RENDER_INTENT_SATURATION,
|
|
||||||
RENDER_INTENT_ABSOLUTE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct render_intent_info {
|
void
|
||||||
enum render_intent intent;
|
window_set_preferred_format(struct window *window,
|
||||||
uint32_t protocol_intent;
|
enum preferred_format format);
|
||||||
const char *desc;
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct render_intent_info *
|
|
||||||
render_intent_info_from(enum render_intent intent);
|
|
||||||
|
|
||||||
bool
|
|
||||||
widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
|
||||||
uint32_t length, uint32_t offset,
|
|
||||||
enum render_intent intent, char **err_msg);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
widget_set_tooltip(struct widget *parent, char *entry, float x, float y);
|
widget_set_tooltip(struct widget *parent, char *entry, float x, float y);
|
||||||
|
|
@ -590,8 +461,6 @@ widget_destroy(struct widget *widget);
|
||||||
void
|
void
|
||||||
widget_set_default_cursor(struct widget *widget, int cursor);
|
widget_set_default_cursor(struct widget *widget, int cursor);
|
||||||
void
|
void
|
||||||
widget_set_default_tablet_cursor(struct widget *widget, int cursor);
|
|
||||||
void
|
|
||||||
widget_get_allocation(struct widget *widget, struct rectangle *allocation);
|
widget_get_allocation(struct widget *widget, struct rectangle *allocation);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -613,9 +482,6 @@ widget_cairo_create(struct widget *widget);
|
||||||
struct wl_surface *
|
struct wl_surface *
|
||||||
widget_get_wl_surface(struct widget *widget);
|
widget_get_wl_surface(struct widget *widget);
|
||||||
|
|
||||||
void
|
|
||||||
widget_surface_flush(struct widget *widget);
|
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
widget_get_last_time(struct widget *widget);
|
widget_get_last_time(struct widget *widget);
|
||||||
|
|
||||||
|
|
@ -659,57 +525,10 @@ void
|
||||||
widget_set_axis_handler(struct widget *widget,
|
widget_set_axis_handler(struct widget *widget,
|
||||||
widget_axis_handler_t handler);
|
widget_axis_handler_t handler);
|
||||||
void
|
void
|
||||||
widget_set_pointer_frame_handler(struct widget *widget,
|
|
||||||
widget_pointer_frame_handler_t handler);
|
|
||||||
void
|
|
||||||
widget_set_axis_handlers(struct widget *widget,
|
|
||||||
widget_axis_handler_t axis_handler,
|
|
||||||
widget_axis_source_handler_t axis_source_handler,
|
|
||||||
widget_axis_stop_handler_t axis_stop_handler,
|
|
||||||
widget_axis_discrete_handler_t axis_discrete_handler);
|
|
||||||
void
|
|
||||||
widget_set_tablet_tool_axis_handlers(struct widget *widget,
|
|
||||||
widget_tablet_tool_motion_handler_t motion,
|
|
||||||
widget_tablet_tool_pressure_handler_t pressure,
|
|
||||||
widget_tablet_tool_distance_handler_t distance,
|
|
||||||
widget_tablet_tool_tilt_handler_t tilt,
|
|
||||||
widget_tablet_tool_rotation_handler_t rotation,
|
|
||||||
widget_tablet_tool_slider_handler_t slider,
|
|
||||||
widget_tablet_tool_wheel_handler_t wheel);
|
|
||||||
void
|
|
||||||
widget_set_tablet_tool_up_handler(struct widget *widget,
|
|
||||||
widget_tablet_tool_up_handler_t handler);
|
|
||||||
void
|
|
||||||
widget_set_tablet_tool_down_handler(struct widget *widget,
|
|
||||||
widget_tablet_tool_down_handler_t handler);
|
|
||||||
void
|
|
||||||
widget_set_tablet_tool_proximity_handlers(struct widget *widget,
|
|
||||||
widget_tablet_tool_proximity_in_handler_t in_handler,
|
|
||||||
widget_tablet_tool_proximity_out_handler_t out_handler);
|
|
||||||
void
|
|
||||||
widget_set_tablet_tool_button_handler(struct widget *widget,
|
|
||||||
widget_tablet_tool_button_handler_t handler);
|
|
||||||
void
|
|
||||||
widget_set_tablet_tool_frame_handler(struct widget *widget,
|
|
||||||
widget_tablet_tool_frame_handler_t handler);
|
|
||||||
|
|
||||||
void
|
|
||||||
window_inhibit_redraw(struct window *window);
|
|
||||||
void
|
|
||||||
window_uninhibit_redraw(struct window *window);
|
|
||||||
void
|
|
||||||
widget_schedule_redraw(struct widget *widget);
|
widget_schedule_redraw(struct widget *widget);
|
||||||
void
|
void
|
||||||
widget_set_use_cairo(struct widget *widget, int use_cairo);
|
widget_set_use_cairo(struct widget *widget, int use_cairo);
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the viewport destination for the widget's surface
|
|
||||||
* return 0 on success and -1 on failure. Set width and height to
|
|
||||||
* -1 to reset the viewport.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
widget_set_viewport_destination(struct widget *widget, int width, int height);
|
|
||||||
|
|
||||||
struct widget *
|
struct widget *
|
||||||
window_frame_create(struct window *window, void *data);
|
window_frame_create(struct window *window, void *data);
|
||||||
|
|
||||||
|
|
@ -815,42 +634,4 @@ xkb_mod_mask_t
|
||||||
keysym_modifiers_get_mask(struct wl_array *modifiers_map,
|
keysym_modifiers_get_mask(struct wl_array *modifiers_map,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
|
||||||
uint32_t
|
|
||||||
tablet_tool_get_type(struct tablet_tool *tool);
|
|
||||||
|
|
||||||
uint64_t
|
|
||||||
tablet_tool_get_serial(struct tablet_tool *tool);
|
|
||||||
|
|
||||||
uint64_t
|
|
||||||
tablet_tool_get_hwid(struct tablet_tool *tool);
|
|
||||||
|
|
||||||
void
|
|
||||||
tablet_tool_set_cursor_image(struct tablet_tool *tool, int cursor);
|
|
||||||
|
|
||||||
struct toytimer;
|
|
||||||
typedef void (*toytimer_cb)(struct toytimer *);
|
|
||||||
|
|
||||||
struct toytimer {
|
|
||||||
struct display *display;
|
|
||||||
struct task tsk;
|
|
||||||
int fd;
|
|
||||||
toytimer_cb callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
toytimer_init(struct toytimer *tt, clockid_t clock, struct display *display,
|
|
||||||
toytimer_cb callback);
|
|
||||||
|
|
||||||
void
|
|
||||||
toytimer_fini(struct toytimer *tt);
|
|
||||||
|
|
||||||
void
|
|
||||||
toytimer_arm(struct toytimer *tt, const struct itimerspec *its);
|
|
||||||
|
|
||||||
void
|
|
||||||
toytimer_arm_once_usec(struct toytimer *tt, uint32_t usec);
|
|
||||||
|
|
||||||
void
|
|
||||||
toytimer_disarm(struct toytimer *tt);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
148
clients/wscreensaver-glue.c
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wscreensaver-glue.h"
|
||||||
|
|
||||||
|
double frand(double f)
|
||||||
|
{
|
||||||
|
double r = random();
|
||||||
|
return r * f / (double)RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_gl_error(void)
|
||||||
|
{
|
||||||
|
while (glGetError() != GL_NO_ERROR)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_gl_error(const char *msg)
|
||||||
|
{
|
||||||
|
const char *emsg;
|
||||||
|
int err = glGetError();
|
||||||
|
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case GL_NO_ERROR:
|
||||||
|
return;
|
||||||
|
|
||||||
|
#define ERR(tok) case tok: emsg = #tok; break;
|
||||||
|
ERR(GL_INVALID_ENUM)
|
||||||
|
ERR(GL_INVALID_VALUE)
|
||||||
|
ERR(GL_INVALID_OPERATION)
|
||||||
|
ERR(GL_STACK_OVERFLOW)
|
||||||
|
ERR(GL_STACK_UNDERFLOW)
|
||||||
|
ERR(GL_OUT_OF_MEMORY)
|
||||||
|
#undef ERR
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: %s: unknown GL error 0x%04x\n",
|
||||||
|
progname, msg, err);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: %s: GL error %s\n", progname, msg, emsg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_xpm_color(uint32_t *ctable, const char *line)
|
||||||
|
{
|
||||||
|
unsigned char key;
|
||||||
|
char cstr[10];
|
||||||
|
char *end;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
if (sscanf(line, "%1c c %9s", &key, cstr) < 2) {
|
||||||
|
fprintf(stderr, "%s: error in XPM color definition '%s'\n",
|
||||||
|
progname, line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = strtol(&cstr[1], &end, 16);
|
||||||
|
|
||||||
|
if (strcmp(cstr, "None") == 0)
|
||||||
|
ctable[key] = 0x00000000;
|
||||||
|
else if (cstr[0] != '#' || !(cstr[1] != '\0' && *end == '\0')) {
|
||||||
|
fprintf(stderr, "%s: error interpreting XPM color '%s'\n",
|
||||||
|
progname, cstr);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ctable[key] = value | 0xff000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_xpm_row(char *data, const char *line, uint32_t *ctable, int width)
|
||||||
|
{
|
||||||
|
uint32_t *pixel = (uint32_t *)data;
|
||||||
|
uint8_t *p = (uint8_t *)line;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < width; ++i)
|
||||||
|
pixel[i] = ctable[p[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
XImage *xpm_to_ximage(char **xpm_data)
|
||||||
|
{
|
||||||
|
XImage *xi;
|
||||||
|
int colors;
|
||||||
|
int cpp;
|
||||||
|
int i;
|
||||||
|
uint32_t ctable[256] = { 0 };
|
||||||
|
|
||||||
|
xi = malloc(sizeof *xi);
|
||||||
|
if (!xi)
|
||||||
|
return NULL;
|
||||||
|
xi->data = NULL;
|
||||||
|
|
||||||
|
if (sscanf(xpm_data[0], "%d %d %d %d", &xi->width,
|
||||||
|
&xi->height, &colors, &cpp) < 4)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
if (xi->width < 1 || xi->height < 1 || cpp != 1)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
xi->bytes_per_line = xi->width * sizeof(uint32_t);
|
||||||
|
xi->data = malloc(xi->height * xi->bytes_per_line);
|
||||||
|
if (!xi->data)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
for (i = 0; i < colors; ++i)
|
||||||
|
read_xpm_color(ctable, xpm_data[i + 1]);
|
||||||
|
|
||||||
|
for (i = 0; i < xi->height; ++i)
|
||||||
|
read_xpm_row(xi->data + i * xi->bytes_per_line,
|
||||||
|
xpm_data[i + colors + 1], ctable, xi->width);
|
||||||
|
|
||||||
|
return xi;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
fprintf(stderr, "%s: error processing XPM data.\n", progname);
|
||||||
|
XDestroyImage(xi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XDestroyImage(XImage *xi)
|
||||||
|
{
|
||||||
|
free(xi->data);
|
||||||
|
free(xi);
|
||||||
|
}
|
||||||
120
clients/wscreensaver-glue.h
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WSCREENSAVER_GLUE_H
|
||||||
|
#define WSCREENSAVER_GLUE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is glue, that tries to avoid changing glmatrix.c from the
|
||||||
|
* original too much, hopefully easing the porting of other (GL)
|
||||||
|
* xscreensaver "hacks".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wscreensaver.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
#define ENTRYPOINT static
|
||||||
|
|
||||||
|
typedef bool Bool;
|
||||||
|
#define True true
|
||||||
|
#define False false
|
||||||
|
|
||||||
|
typedef struct ModeInfo ModeInfo;
|
||||||
|
|
||||||
|
#define MI_DISPLAY(mi) NULL
|
||||||
|
#define MI_WINDOW(mi) (mi)
|
||||||
|
#define MI_SCREEN(mi) ((mi)->instance_number)
|
||||||
|
#define MI_WIDTH(mi) ((mi)->width)
|
||||||
|
#define MI_HEIGHT(mi) ((mi)->height)
|
||||||
|
#define MI_IS_WIREFRAME(mi) 0
|
||||||
|
#define MI_NUM_SCREENS(mi) 16
|
||||||
|
|
||||||
|
typedef EGLContext GLXContext;
|
||||||
|
|
||||||
|
double frand(double f);
|
||||||
|
void clear_gl_error(void);
|
||||||
|
void check_gl_error(const char *msg);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
glXMakeCurrent(void *dummy, ModeInfo *mi, EGLContext ctx)
|
||||||
|
{
|
||||||
|
assert(mi->eglctx == ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
glXSwapBuffers(void *dummy, ModeInfo *mi)
|
||||||
|
{
|
||||||
|
mi->swap_buffers = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
do_fps(ModeInfo *mi)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* just enough XImage to satisfy glmatrix.c */
|
||||||
|
|
||||||
|
typedef struct _XImage {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
char *data;
|
||||||
|
int bytes_per_line;
|
||||||
|
} XImage;
|
||||||
|
|
||||||
|
XImage *xpm_to_ximage(char **xpm_data);
|
||||||
|
void XDestroyImage(XImage *xi);
|
||||||
|
|
||||||
|
static inline unsigned long
|
||||||
|
XGetPixel(XImage *xi, int x, int y)
|
||||||
|
{
|
||||||
|
return *(uint32_t *)(xi->data + xi->bytes_per_line * y + 4 * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
XPutPixel(XImage *xi, int x, int y, unsigned long pixel)
|
||||||
|
{
|
||||||
|
*(uint32_t *)(xi->data + xi->bytes_per_line * y + 4 * x) = pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* override glViewport from the plugin, so we can set it up properly
|
||||||
|
* rendering to a regular decorated Wayland window.
|
||||||
|
*/
|
||||||
|
#ifdef glViewport
|
||||||
|
#undef glViewport
|
||||||
|
#endif
|
||||||
|
#define glViewport(x,y,w,h) do {} while (0)
|
||||||
|
|
||||||
|
#endif /* WSCREENSAVER_GLUE_H */
|
||||||
348
clients/wscreensaver.c
Normal file
|
|
@ -0,0 +1,348 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
|
#include "wscreensaver.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "desktop-shell-client-protocol.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
extern struct wscreensaver_plugin glmatrix_screensaver;
|
||||||
|
|
||||||
|
static const struct wscreensaver_plugin * const plugins[] = {
|
||||||
|
&glmatrix_screensaver,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *progname = NULL;
|
||||||
|
|
||||||
|
static int demo_mode;
|
||||||
|
|
||||||
|
struct wscreensaver {
|
||||||
|
struct screensaver *interface;
|
||||||
|
|
||||||
|
struct display *display;
|
||||||
|
|
||||||
|
struct ModeInfo *demomode;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLConfig config;
|
||||||
|
} egl;
|
||||||
|
|
||||||
|
const struct wscreensaver_plugin *plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_callback(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
struct ModeInfo *mi = data;
|
||||||
|
|
||||||
|
window_schedule_redraw(mi->window);
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_callback_listener listener = {
|
||||||
|
frame_callback
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
redraw_handler(struct widget *widget, void *data)
|
||||||
|
{
|
||||||
|
struct ModeInfo *mi = data;
|
||||||
|
struct wscreensaver *wscr = mi->priv;
|
||||||
|
struct rectangle drawarea;
|
||||||
|
struct rectangle winarea;
|
||||||
|
struct wl_callback *callback;
|
||||||
|
int bottom;
|
||||||
|
|
||||||
|
mi->swap_buffers = 0;
|
||||||
|
|
||||||
|
widget_get_allocation(mi->widget, &drawarea);
|
||||||
|
window_get_allocation(mi->window, &winarea);
|
||||||
|
|
||||||
|
if (display_acquire_window_surface(wscr->display,
|
||||||
|
mi->window,
|
||||||
|
mi->eglctx) < 0) {
|
||||||
|
fprintf(stderr, "%s: unable to acquire window surface",
|
||||||
|
progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bottom = winarea.height - (drawarea.height + drawarea.y);
|
||||||
|
glViewport(drawarea.x, bottom, drawarea.width, drawarea.height);
|
||||||
|
glScissor(drawarea.x, bottom, drawarea.width, drawarea.height);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
if (mi->width != drawarea.width || mi->height != drawarea.height) {
|
||||||
|
mi->width = drawarea.width;
|
||||||
|
mi->height = drawarea.height;
|
||||||
|
wscr->plugin->reshape(mi, mi->width, mi->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
wscr->plugin->draw(mi);
|
||||||
|
|
||||||
|
if (mi->swap_buffers == 0)
|
||||||
|
fprintf(stderr, "%s: swapBuffers not called\n", progname);
|
||||||
|
|
||||||
|
display_release_window_surface(wscr->display, mi->window);
|
||||||
|
|
||||||
|
callback = wl_surface_frame(window_get_wl_surface(mi->window));
|
||||||
|
wl_callback_add_listener(callback, &listener, mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_frand(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
srandom(tv.tv_sec * 100 + tv.tv_usec / 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT EGLContext *
|
||||||
|
init_GL(struct ModeInfo *mi)
|
||||||
|
{
|
||||||
|
struct wscreensaver *wscr = mi->priv;
|
||||||
|
EGLContext *pctx;
|
||||||
|
|
||||||
|
pctx = malloc(sizeof *pctx);
|
||||||
|
if (!pctx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (mi->eglctx != EGL_NO_CONTEXT) {
|
||||||
|
fprintf(stderr, "%s: multiple GL contexts are not supported",
|
||||||
|
progname);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
mi->eglctx = eglCreateContext(wscr->egl.display, wscr->egl.config,
|
||||||
|
EGL_NO_CONTEXT, NULL);
|
||||||
|
if (mi->eglctx == EGL_NO_CONTEXT) {
|
||||||
|
fprintf(stderr, "%s: init_GL failed to create EGL context\n",
|
||||||
|
progname);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(wscr->egl.display, NULL, NULL, mi->eglctx)) {
|
||||||
|
fprintf(stderr, "%s: init_GL failed on eglMakeCurrent\n",
|
||||||
|
progname);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
*pctx = mi->eglctx;
|
||||||
|
return pctx;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
free(pctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ModeInfo *
|
||||||
|
create_wscreensaver_instance(struct wscreensaver *screensaver,
|
||||||
|
struct wl_output *output, int width, int height)
|
||||||
|
{
|
||||||
|
static int instance;
|
||||||
|
struct ModeInfo *mi;
|
||||||
|
struct rectangle drawarea;
|
||||||
|
|
||||||
|
mi = calloc(1, sizeof *mi);
|
||||||
|
if (!mi)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (demo_mode)
|
||||||
|
mi->window = window_create(screensaver->display);
|
||||||
|
else
|
||||||
|
mi->window = window_create_custom(screensaver->display);
|
||||||
|
|
||||||
|
if (!mi->window) {
|
||||||
|
fprintf(stderr, "%s: creating a window failed.\n", progname);
|
||||||
|
free(mi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_set_title(mi->window, progname);
|
||||||
|
|
||||||
|
if (screensaver->interface && !demo_mode) {
|
||||||
|
mi->widget = window_add_widget(mi->window, mi);
|
||||||
|
screensaver_set_surface(screensaver->interface,
|
||||||
|
window_get_wl_surface(mi->window),
|
||||||
|
output);
|
||||||
|
} else {
|
||||||
|
mi->widget = window_frame_create(mi->window, mi);
|
||||||
|
}
|
||||||
|
widget_set_redraw_handler(mi->widget, redraw_handler);
|
||||||
|
|
||||||
|
mi->priv = screensaver;
|
||||||
|
mi->eglctx = EGL_NO_CONTEXT;
|
||||||
|
mi->instance_number = instance++; /* XXX */
|
||||||
|
|
||||||
|
widget_get_allocation(mi->widget, &drawarea);
|
||||||
|
mi->width = drawarea.width;
|
||||||
|
mi->height = drawarea.height;
|
||||||
|
|
||||||
|
screensaver->plugin->init(mi);
|
||||||
|
|
||||||
|
window_schedule_resize(mi->window, width, height);
|
||||||
|
return mi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_output_destroy(struct output *output, void *data)
|
||||||
|
{
|
||||||
|
/* struct ModeInfo *mi = data;
|
||||||
|
* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_output_configure(struct output *output, void *data)
|
||||||
|
{
|
||||||
|
struct wscreensaver *screensaver = data;
|
||||||
|
struct ModeInfo *mi;
|
||||||
|
struct rectangle area;
|
||||||
|
|
||||||
|
/* skip existing outputs */
|
||||||
|
if (output_get_user_data(output))
|
||||||
|
return;
|
||||||
|
|
||||||
|
output_get_allocation(output, &area);
|
||||||
|
mi = create_wscreensaver_instance(screensaver,
|
||||||
|
output_get_wl_output(output),
|
||||||
|
area.width, area.height);
|
||||||
|
output_set_user_data(output, mi);
|
||||||
|
output_set_destroy_handler(output, handle_output_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_wscreensaver(struct wscreensaver *wscr, struct display *display)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
const char prefix[] = "wscreensaver::";
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
display_set_user_data(display, wscr);
|
||||||
|
wscr->display = display;
|
||||||
|
wscr->plugin = plugins[0];
|
||||||
|
|
||||||
|
size = sizeof(prefix) + strlen(wscr->plugin->name);
|
||||||
|
str = malloc(size);
|
||||||
|
if (!str) {
|
||||||
|
fprintf(stderr, "init: out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(str, size, "%s%s", prefix, wscr->plugin->name);
|
||||||
|
progname = str;
|
||||||
|
|
||||||
|
wscr->egl.display = display_get_egl_display(wscr->display);
|
||||||
|
if (!wscr->egl.display) {
|
||||||
|
fprintf(stderr, "init: no EGL display\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglBindAPI(EGL_OPENGL_API);
|
||||||
|
wscr->egl.config = display_get_argb_egl_config(wscr->display);
|
||||||
|
|
||||||
|
if (demo_mode) {
|
||||||
|
struct wl_output *o =
|
||||||
|
output_get_wl_output(display_get_output(display));
|
||||||
|
/* only one instance */
|
||||||
|
wscr->demomode =
|
||||||
|
create_wscreensaver_instance(wscr, o, 400, 300);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_set_output_configure_handler(display, handle_output_configure);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
global_handler(struct display *display, uint32_t name,
|
||||||
|
const char *interface, uint32_t version, void *data)
|
||||||
|
{
|
||||||
|
struct wscreensaver *screensaver = data;
|
||||||
|
|
||||||
|
if (!strcmp(interface, "screensaver")) {
|
||||||
|
screensaver->interface =
|
||||||
|
display_bind(display, name, &screensaver_interface, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct weston_option wscreensaver_options[] = {
|
||||||
|
{ WESTON_OPTION_BOOLEAN, "demo", 0, &demo_mode },
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct display *d;
|
||||||
|
struct wscreensaver screensaver = { 0 };
|
||||||
|
|
||||||
|
init_frand();
|
||||||
|
|
||||||
|
if (parse_options(wscreensaver_options,
|
||||||
|
ARRAY_LENGTH(wscreensaver_options), &argc, argv) > 1) {
|
||||||
|
printf("Usage: %s [OPTIONS]\n --demo for demo mode\n",
|
||||||
|
argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
d = display_create(&argc, argv);
|
||||||
|
if (d == NULL) {
|
||||||
|
fprintf(stderr, "failed to create display: %m\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!demo_mode) {
|
||||||
|
/* iterates already known globals immediately */
|
||||||
|
display_set_user_data(d, &screensaver);
|
||||||
|
display_set_global_handler(d, global_handler);
|
||||||
|
if (!screensaver.interface) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Server did not offer screensaver interface,"
|
||||||
|
" exiting.\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_wscreensaver(&screensaver, d) < 0) {
|
||||||
|
fprintf(stderr, "wscreensaver init failed.\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_run(d);
|
||||||
|
|
||||||
|
free((void *)progname);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
63
clients/wscreensaver.h
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WSCREENSAVER_H
|
||||||
|
#define WSCREENSAVER_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define MESA_EGL_NO_X11_HEADERS
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
|
extern const char *progname;
|
||||||
|
|
||||||
|
struct wscreensaver;
|
||||||
|
|
||||||
|
struct ModeInfo {
|
||||||
|
struct wscreensaver *priv;
|
||||||
|
EGLContext eglctx;
|
||||||
|
int swap_buffers;
|
||||||
|
|
||||||
|
struct window *window;
|
||||||
|
struct widget *widget;
|
||||||
|
|
||||||
|
int instance_number;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
unsigned long polygon_count;
|
||||||
|
int fps_p;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wscreensaver_plugin {
|
||||||
|
const char *name;
|
||||||
|
void (*init)(struct ModeInfo *mi);
|
||||||
|
void (*draw)(struct ModeInfo *mi);
|
||||||
|
void (*reshape)(struct ModeInfo *mi, int w, int h);
|
||||||
|
/* void (*refresh)(struct ModeInfo *mi);
|
||||||
|
void (*finish)(struct ModeInfo *mi);*/
|
||||||
|
};
|
||||||
|
|
||||||
|
EGLContext *
|
||||||
|
init_GL(struct ModeInfo *mi);
|
||||||
|
|
||||||
|
#endif /* WSCREENSAVER_H */
|
||||||
559
configure.ac
Normal file
|
|
@ -0,0 +1,559 @@
|
||||||
|
m4_define([weston_major_version], [1])
|
||||||
|
m4_define([weston_minor_version], [7])
|
||||||
|
m4_define([weston_micro_version], [92])
|
||||||
|
m4_define([weston_version],
|
||||||
|
[weston_major_version.weston_minor_version.weston_micro_version])
|
||||||
|
|
||||||
|
AC_PREREQ([2.64])
|
||||||
|
AC_INIT([weston],
|
||||||
|
[weston_version],
|
||||||
|
[https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=weston&version=weston_version],
|
||||||
|
[weston],
|
||||||
|
[http://wayland.freedesktop.org])
|
||||||
|
|
||||||
|
AC_SUBST([WESTON_VERSION_MAJOR], [weston_major_version])
|
||||||
|
AC_SUBST([WESTON_VERSION_MINOR], [weston_minor_version])
|
||||||
|
AC_SUBST([WESTON_VERSION_MICRO], [weston_micro_version])
|
||||||
|
AC_SUBST([WESTON_VERSION], [weston_version])
|
||||||
|
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([1.11 parallel-tests foreign no-dist-gzip dist-xz color-tests subdir-objects])
|
||||||
|
|
||||||
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
|
# Check for programs
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_SED
|
||||||
|
|
||||||
|
# Initialize libtool
|
||||||
|
LT_PREREQ([2.2])
|
||||||
|
LT_INIT([disable-static])
|
||||||
|
|
||||||
|
AC_ARG_VAR([WESTON_NATIVE_BACKEND],
|
||||||
|
[Set the native backend to use, if Weston is not running under Wayland nor X11. @<:@default=drm-backend.so@:>@])
|
||||||
|
AC_ARG_VAR([WESTON_SHELL_CLIENT],
|
||||||
|
[Set the default desktop shell client to load if none is specified in weston.ini. @<:@default=weston-desktop-shell@:>@])
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG()
|
||||||
|
|
||||||
|
AC_CHECK_FUNC([dlopen], [],
|
||||||
|
AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl"))
|
||||||
|
AC_SUBST(DLOPEN_LIBS)
|
||||||
|
|
||||||
|
AC_CHECK_DECL(SFD_CLOEXEC,[],
|
||||||
|
[AC_MSG_ERROR("SFD_CLOEXEC is needed to compile weston")],
|
||||||
|
[[#include <sys/signalfd.h>]])
|
||||||
|
AC_CHECK_DECL(TFD_CLOEXEC,[],
|
||||||
|
[AC_MSG_ERROR("TFD_CLOEXEC is needed to compile weston")],
|
||||||
|
[[#include <sys/timerfd.h>]])
|
||||||
|
AC_CHECK_DECL(CLOCK_MONOTONIC,[],
|
||||||
|
[AC_MSG_ERROR("CLOCK_MONOTONIC is needed to compile weston")],
|
||||||
|
[[#include <time.h>]])
|
||||||
|
AC_CHECK_HEADERS([execinfo.h])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS([mkostemp strchrnul initgroups posix_fallocate])
|
||||||
|
|
||||||
|
COMPOSITOR_MODULES="wayland-server >= 1.7.92 pixman-1 >= 0.25.2"
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(egl, [ --disable-egl],,
|
||||||
|
enable_egl=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_EGL, test x$enable_egl = xyes)
|
||||||
|
if test x$enable_egl = xyes; then
|
||||||
|
AC_DEFINE([ENABLE_EGL], [1], [Build Weston with EGL support])
|
||||||
|
PKG_CHECK_MODULES(EGL, [egl >= 7.10 glesv2])
|
||||||
|
PKG_CHECK_MODULES([EGL_TESTS], [egl >= 7.10 glesv2 wayland-client wayland-egl])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(xkbcommon,
|
||||||
|
AS_HELP_STRING([--disable-xkbcommon], [Disable libxkbcommon
|
||||||
|
support: This is only useful in environments
|
||||||
|
where you do not have a hardware keyboard. If
|
||||||
|
libxkbcommon support is disabled clients will not
|
||||||
|
be sent a keymap and and must know how to
|
||||||
|
interpret the keycode sent for any key event.]),,
|
||||||
|
enable_xkbcommon=yes)
|
||||||
|
if test x$enable_xkbcommon = xyes; then
|
||||||
|
AC_DEFINE(ENABLE_XKBCOMMON, [1], [Build Weston with libxkbcommon support])
|
||||||
|
COMPOSITOR_MODULES="$COMPOSITOR_MODULES xkbcommon >= 0.3.0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(setuid-install, [ --enable-setuid-install],,
|
||||||
|
enable_setuid_install=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_SETUID_INSTALL, test x$enable_setuid_install = xyes)
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(xwayland, [ --enable-xwayland],,
|
||||||
|
enable_xwayland=yes)
|
||||||
|
AC_ARG_ENABLE(xwayland-test, [ --enable-xwayland-test],,
|
||||||
|
enable_xwayland_test=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_XWAYLAND, test x$enable_xwayland = xyes)
|
||||||
|
AM_CONDITIONAL(ENABLE_XWAYLAND_TEST, test x$enable_xwayland = xyes -a x$enable_xwayland_test = xyes)
|
||||||
|
if test x$enable_xwayland = xyes; then
|
||||||
|
PKG_CHECK_MODULES([XWAYLAND], xcb xcb-xfixes xcb-composite xcursor cairo-xcb)
|
||||||
|
AC_DEFINE([BUILD_XWAYLAND], [1], [Build the X server launcher])
|
||||||
|
|
||||||
|
AC_ARG_WITH(xserver-path, AS_HELP_STRING([--with-xserver-path=PATH],
|
||||||
|
[Path to X server]), [XSERVER_PATH="$withval"],
|
||||||
|
[XSERVER_PATH="/usr/bin/Xwayland"])
|
||||||
|
AC_SUBST([XSERVER_PATH])
|
||||||
|
if test x$enable_xwayland_test = xyes; then
|
||||||
|
PKG_CHECK_MODULES([XWAYLAND_TEST], x11)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBDRM, [libdrm],
|
||||||
|
[AC_DEFINE(HAVE_LIBDRM, 1, [Define if libdrm is available]) have_libdrm=yes], have_libdrm=no)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(x11-compositor, [ --enable-x11-compositor],,
|
||||||
|
enable_x11_compositor=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_X11_COMPOSITOR, test x$enable_x11_compositor = xyes)
|
||||||
|
if test x$enable_x11_compositor = xyes; then
|
||||||
|
PKG_CHECK_MODULES([XCB], xcb)
|
||||||
|
xcb_save_LIBS=$LIBS
|
||||||
|
xcb_save_CFLAGS=$CFLAGS
|
||||||
|
CFLAGS=$XCB_CFLAGS
|
||||||
|
LIBS=$XCB_LIBS
|
||||||
|
AC_CHECK_FUNCS([xcb_poll_for_queued_event])
|
||||||
|
LIBS=$xcb_save_LIBS
|
||||||
|
CFLAGS=$xcb_save_CFLAGS
|
||||||
|
|
||||||
|
X11_COMPOSITOR_MODULES="x11 x11-xcb xcb-shm"
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(X11_COMPOSITOR_XKB, [xcb-xkb],
|
||||||
|
[have_xcb_xkb="yes"], [have_xcb_xkb="no"])
|
||||||
|
if test "x$have_xcb_xkb" = xyes; then
|
||||||
|
# Most versions of XCB have totally broken XKB bindings, where the
|
||||||
|
# events don't work. Make sure we can actually use them.
|
||||||
|
xcb_xkb_save_CFLAGS=$CFLAGS
|
||||||
|
CFLAGS=$X11_COMPOSITOR_XKB_CFLAGS
|
||||||
|
AC_CHECK_MEMBER([struct xcb_xkb_state_notify_event_t.xkbType],
|
||||||
|
[], [have_xcb_xkb=no], [[#include <xcb/xkb.h>]])
|
||||||
|
CFLAGS=$xcb_xkb_save_CFLAGS
|
||||||
|
fi
|
||||||
|
if test "x$have_xcb_xkb" = xyes; then
|
||||||
|
X11_COMPOSITOR_MODULES="$X11_COMPOSITOR_MODULES xcb-xkb"
|
||||||
|
AC_DEFINE([HAVE_XCB_XKB], [1], [libxcb supports XKB protocol])
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(X11_COMPOSITOR, [$X11_COMPOSITOR_MODULES])
|
||||||
|
AC_DEFINE([BUILD_X11_COMPOSITOR], [1], [Build the X11 compositor])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(drm-compositor, [ --enable-drm-compositor],,
|
||||||
|
enable_drm_compositor=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor = xyes)
|
||||||
|
if test x$enable_drm_compositor = xyes; then
|
||||||
|
AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor])
|
||||||
|
PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm mtdev >= 1.1.0])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0])
|
||||||
|
PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(wayland-compositor, [ --enable-wayland-compositor],,
|
||||||
|
enable_wayland_compositor=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_WAYLAND_COMPOSITOR,
|
||||||
|
test x$enable_wayland_compositor = xyes -a x$enable_egl = xyes)
|
||||||
|
if test x$enable_wayland_compositor = xyes -a x$enable_egl = xyes; then
|
||||||
|
AC_DEFINE([BUILD_WAYLAND_COMPOSITOR], [1],
|
||||||
|
[Build the Wayland (nested) compositor])
|
||||||
|
PKG_CHECK_MODULES(WAYLAND_COMPOSITOR, [wayland-client >= 1.5.91 wayland-egl wayland-cursor])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(headless-compositor, [ --enable-headless-compositor],,
|
||||||
|
enable_headless_compositor=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_HEADLESS_COMPOSITOR,
|
||||||
|
test x$enable_headless_compositor = xyes)
|
||||||
|
if test x$enable_headless_compositor = xyes; then
|
||||||
|
AC_DEFINE([BUILD_HEADLESS_COMPOSITOR], [1], [Build the headless compositor])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(rpi-compositor,
|
||||||
|
AS_HELP_STRING([--disable-rpi-compositor],
|
||||||
|
[do not build the Raspberry Pi backend]),,
|
||||||
|
enable_rpi_compositor=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_RPI_COMPOSITOR, test "x$enable_rpi_compositor" = "xyes")
|
||||||
|
have_bcm_host="no"
|
||||||
|
if test "x$enable_rpi_compositor" = "xyes"; then
|
||||||
|
AC_DEFINE([BUILD_RPI_COMPOSITOR], [1], [Build the compositor for Raspberry Pi])
|
||||||
|
PKG_CHECK_MODULES(RPI_COMPOSITOR, [libudev >= 136 mtdev >= 1.1.0])
|
||||||
|
PKG_CHECK_MODULES(RPI_BCM_HOST, [bcm_host],
|
||||||
|
[have_bcm_host="yes"
|
||||||
|
AC_DEFINE([HAVE_BCM_HOST], [1], [have Raspberry Pi BCM headers])],
|
||||||
|
[AC_MSG_WARN([Raspberry Pi BCM host libraries not found, will use stubs instead.])])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(INSTALL_RPI_COMPOSITOR, test "x$have_bcm_host" = "xyes")
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([fbdev-compositor], [ --enable-fbdev-compositor],,
|
||||||
|
enable_fbdev_compositor=yes)
|
||||||
|
AM_CONDITIONAL([ENABLE_FBDEV_COMPOSITOR],
|
||||||
|
[test x$enable_fbdev_compositor = xyes])
|
||||||
|
AS_IF([test x$enable_fbdev_compositor = xyes], [
|
||||||
|
AC_DEFINE([BUILD_FBDEV_COMPOSITOR], [1], [Build the fbdev compositor])
|
||||||
|
PKG_CHECK_MODULES([FBDEV_COMPOSITOR], [libudev >= 136 mtdev >= 1.1.0])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([rdp-compositor], [ --enable-rdp-compositor],,
|
||||||
|
enable_rdp_compositor=no)
|
||||||
|
AM_CONDITIONAL([ENABLE_RDP_COMPOSITOR],
|
||||||
|
[test x$enable_rdp_compositor = xyes])
|
||||||
|
if test x$enable_rdp_compositor = xyes; then
|
||||||
|
AC_DEFINE([BUILD_RDP_COMPOSITOR], [1], [Build the RDP compositor])
|
||||||
|
PKG_CHECK_MODULES(RDP_COMPOSITOR, [freerdp >= 1.1.0])
|
||||||
|
|
||||||
|
SAVED_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $RDP_COMPOSITOR_CFLAGS"
|
||||||
|
AC_CHECK_HEADERS([freerdp/version.h])
|
||||||
|
CPPFLAGS="$SAVED_CPPFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([screen-sharing], [ --enable-screen-sharing],,
|
||||||
|
enable_screen_sharing=no)
|
||||||
|
AM_CONDITIONAL([ENABLE_SCREEN_SHARING],
|
||||||
|
[test x$enable_screen_sharing = xyes])
|
||||||
|
if test x$enable_screen_sharing = xyes; then
|
||||||
|
PKG_CHECK_MODULES(SCREEN_SHARE, [wayland-client])
|
||||||
|
|
||||||
|
if test x$enable_rdp_compositor != xyes; then
|
||||||
|
AC_MSG_WARN([The screen-share.so module requires the RDP backend.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_WITH(cairo,
|
||||||
|
AS_HELP_STRING([--with-cairo=@<:@image|gl|glesv2@:>@]
|
||||||
|
[Which Cairo renderer to use for the clients]),
|
||||||
|
[],[with_cairo="image"])
|
||||||
|
|
||||||
|
if test "x$with_cairo" = "ximage"; then
|
||||||
|
cairo_modules="cairo"
|
||||||
|
else
|
||||||
|
if test "x$with_cairo" = "xgl"; then
|
||||||
|
cairo_modules="cairo-gl"
|
||||||
|
else
|
||||||
|
if test "x$with_cairo" = "xglesv2"; then
|
||||||
|
cairo_modules="cairo-glesv2"
|
||||||
|
else
|
||||||
|
AC_ERROR([Unknown cairo renderer requested])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Included for legacy compat
|
||||||
|
AC_ARG_WITH(cairo-glesv2,
|
||||||
|
AS_HELP_STRING([--with-cairo-glesv2],
|
||||||
|
[Use GLESv2 cairo]))
|
||||||
|
if test "x$with_cairo_glesv2" = "xyes"; then
|
||||||
|
cairo_modules="cairo-glesv2"
|
||||||
|
with_cairo="glesv2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$cairo_modules" = "xcairo-glesv2"; then
|
||||||
|
AC_DEFINE([USE_CAIRO_GLESV2], [1], [Use the GLESv2 GL cairo backend])
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(PIXMAN, [pixman-1])
|
||||||
|
PKG_CHECK_MODULES(PNG, [libpng])
|
||||||
|
PKG_CHECK_MODULES(WEBP, [libwebp], [have_webp=yes], [have_webp=no])
|
||||||
|
AS_IF([test "x$have_webp" = "xyes"],
|
||||||
|
[AC_DEFINE([HAVE_WEBP], [1], [Have webp])])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(vaapi-recorder, [ --enable-vaapi-recorder],,
|
||||||
|
enable_vaapi_recorder=auto)
|
||||||
|
if test x$enable_vaapi_recorder != xno; then
|
||||||
|
PKG_CHECK_MODULES(LIBVA, [libva >= 0.34.0 libva-drm >= 0.34.0],
|
||||||
|
[have_libva=yes], [have_libva=no])
|
||||||
|
if test "x$have_libva" = "xno" -a "x$enable_vaapi_recorder" = "xyes"; then
|
||||||
|
AC_MSG_ERROR([vaapi-recorder explicitly enabled, but libva couldn't be found])
|
||||||
|
fi
|
||||||
|
AS_IF([test "x$have_libva" = "xyes"],
|
||||||
|
[AC_DEFINE([BUILD_VAAPI_RECORDER], [1], [Build the vaapi recorder])])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(ENABLE_VAAPI_RECORDER, test "x$have_libva" = xyes)
|
||||||
|
|
||||||
|
|
||||||
|
AC_CHECK_LIB([jpeg], [jpeg_CreateDecompress], have_jpeglib=yes)
|
||||||
|
if test x$have_jpeglib = xyes; then
|
||||||
|
JPEG_LIBS="-ljpeg"
|
||||||
|
else
|
||||||
|
AC_ERROR([libjpeg not found])
|
||||||
|
fi
|
||||||
|
AC_SUBST(JPEG_LIBS)
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(CAIRO, [cairo])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(TEST_CLIENT, [wayland-client >= 1.7.92])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(simple-clients,
|
||||||
|
AS_HELP_STRING([--disable-simple-clients],
|
||||||
|
[do not build the simple wl_shm clients]),,
|
||||||
|
enable_simple_clients=yes)
|
||||||
|
AM_CONDITIONAL(BUILD_SIMPLE_CLIENTS, test "x$enable_simple_clients" = "xyes")
|
||||||
|
if test x$enable_simple_clients = xyes; then
|
||||||
|
PKG_CHECK_MODULES(SIMPLE_CLIENT, [wayland-client])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(simple-egl-clients,
|
||||||
|
AS_HELP_STRING([--disable-simple-egl-clients],
|
||||||
|
[do not build the simple EGL clients]),,
|
||||||
|
enable_simple_egl_clients="$enable_egl")
|
||||||
|
AM_CONDITIONAL(BUILD_SIMPLE_EGL_CLIENTS, test "x$enable_simple_egl_clients" = "xyes")
|
||||||
|
if test x$enable_simple_egl_clients = xyes; then
|
||||||
|
PKG_CHECK_MODULES(SIMPLE_EGL_CLIENT,
|
||||||
|
[egl >= 7.10 glesv2 wayland-client wayland-egl wayland-cursor])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(clients, [ --enable-clients],, enable_clients=yes)
|
||||||
|
AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes)
|
||||||
|
if test x$enable_clients = xyes; then
|
||||||
|
AC_DEFINE([BUILD_CLIENTS], [1], [Build the Wayland clients])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(CLIENT, [wayland-client >= 1.5.91 cairo >= 1.10.0 xkbcommon wayland-cursor])
|
||||||
|
PKG_CHECK_MODULES(SERVER, [wayland-server])
|
||||||
|
PKG_CHECK_MODULES(WESTON_INFO, [wayland-client >= 1.5.91])
|
||||||
|
|
||||||
|
# Only check for cairo-egl if a GL or GLES renderer requested
|
||||||
|
AS_IF([test "x$cairo_modules" = "xcairo-gl" -o "x$cairo_modules" = "xcairo-glesv2"], [
|
||||||
|
PKG_CHECK_MODULES(CAIRO_EGL, [wayland-egl egl >= 7.10 cairo-egl >= 1.11.3 $cairo_modules],
|
||||||
|
[have_cairo_egl=yes], [have_cairo_egl=no])
|
||||||
|
AS_IF([test "x$have_cairo_egl" = "xyes"],
|
||||||
|
[AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])],
|
||||||
|
[AC_ERROR([cairo-egl not used because $CAIRO_EGL_PKG_ERRORS])])],
|
||||||
|
[have_cairo_egl=no])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(PANGO, [pangocairo], [have_pango=yes], [have_pango=no])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(resize-optimization,
|
||||||
|
AS_HELP_STRING([--disable-resize-optimization],
|
||||||
|
[disable resize optimization allocating a big buffer in toytoolkit]),,
|
||||||
|
enable_resize_optimization=yes)
|
||||||
|
AS_IF([test "x$enable_resize_optimization" = "xyes"],
|
||||||
|
[AC_DEFINE([USE_RESIZE_POOL], [1], [Use resize memory pool as a performance optimization])])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login >= 198],
|
||||||
|
[have_systemd_login=yes], [have_systemd_login=no])
|
||||||
|
AS_IF([test "x$have_systemd_login" = "xyes"],
|
||||||
|
[AC_DEFINE([HAVE_SYSTEMD_LOGIN], [1], [Have systemd-login])])
|
||||||
|
AM_CONDITIONAL(HAVE_SYSTEMD_LOGIN, test "x$have_systemd_login" = "xyes")
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(SYSTEMD_LOGIN_209, [libsystemd-login >= 209],
|
||||||
|
[have_systemd_login_209=yes], [have_systemd_login_209=no])
|
||||||
|
AS_IF([test "x$have_systemd_login_209" = "xyes"],
|
||||||
|
[AC_DEFINE([HAVE_SYSTEMD_LOGIN_209], [1], [Have systemd-login >= 209])])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(weston-launch, [ --enable-weston-launch],, enable_weston_launch=yes)
|
||||||
|
AM_CONDITIONAL(BUILD_WESTON_LAUNCH, test x$enable_weston_launch == xyes)
|
||||||
|
if test x$enable_weston_launch == xyes; then
|
||||||
|
AC_CHECK_LIB([pam], [pam_open_session], [have_pam=yes], [have_pam=no])
|
||||||
|
if test x$have_pam == xno; then
|
||||||
|
AC_ERROR([weston-launch requires pam])
|
||||||
|
fi
|
||||||
|
PAM_LIBS=-lpam
|
||||||
|
AC_SUBST(PAM_LIBS)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$enable_egl = xyes; then
|
||||||
|
PKG_CHECK_MODULES(GLU, [glu], [have_glu=yes], [have_glu=no])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_GLU, test "x$have_glu" = "xyes")
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_PANGO, test "x$have_pango" = "xyes")
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_CAIRO_GLESV2,
|
||||||
|
[test "x$have_cairo_egl" = "xyes" -a "x$cairo_modules" = "xcairo-glesv2" -a "x$enable_egl" = "xyes"])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(BUILD_FULL_GL_CLIENTS,
|
||||||
|
test x$cairo_modules = "xcairo-gl" -a "x$have_cairo_egl" = "xyes" -a "x$enable_egl" = "xyes")
|
||||||
|
|
||||||
|
AM_CONDITIONAL(BUILD_SUBSURFACES_CLIENT,
|
||||||
|
[test '(' "x$have_cairo_egl" != "xyes" -o "x$cairo_modules" = "xcairo-glesv2" ')' -a "x$enable_simple_egl_clients" = "xyes"])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(ENABLE_DESKTOP_SHELL, true)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(fullscreen-shell,
|
||||||
|
AS_HELP_STRING([--disable-fullscreen-shell],
|
||||||
|
[do not build fullscreen-shell server plugin]),,
|
||||||
|
enable_fullscreen_shell=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_FULLSCREEN_SHELL,
|
||||||
|
test "x$enable_fullscreen_shell" = "xyes")
|
||||||
|
|
||||||
|
# CMS modules
|
||||||
|
AC_ARG_ENABLE(colord,
|
||||||
|
AS_HELP_STRING([--disable-colord],
|
||||||
|
[do not build colord CMS support]),,
|
||||||
|
enable_colord=auto)
|
||||||
|
if test "x$enable_colord" != "xno"; then
|
||||||
|
PKG_CHECK_MODULES(COLORD,
|
||||||
|
colord >= 0.1.27,
|
||||||
|
have_colord=yes,
|
||||||
|
have_colord=no)
|
||||||
|
if test "x$have_colord" = "xno" -a "x$enable_colord" = "xyes"; then
|
||||||
|
AC_MSG_ERROR([colord support explicitly requested, but colord couldn't be found])
|
||||||
|
fi
|
||||||
|
if test "x$have_colord" = "xyes"; then
|
||||||
|
enable_colord=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(ENABLE_COLORD, test "x$enable_colord" = "xyes")
|
||||||
|
|
||||||
|
# dbus support
|
||||||
|
AC_ARG_ENABLE(dbus,
|
||||||
|
AS_HELP_STRING([--disable-dbus],
|
||||||
|
[do not build with dbus support]),,
|
||||||
|
enable_dbus=auto)
|
||||||
|
if test "x$enable_dbus" != "xno"; then
|
||||||
|
PKG_CHECK_MODULES(DBUS,
|
||||||
|
dbus-1 >= 1.6,
|
||||||
|
have_dbus=yes,
|
||||||
|
have_dbus=no)
|
||||||
|
if test "x$have_dbus" = "xno" -a "x$enable_dbus" = "xyes"; then
|
||||||
|
AC_MSG_ERROR([dbus support explicitly requested, but libdbus couldn't be found])
|
||||||
|
fi
|
||||||
|
if test "x$have_dbus" = "xyes"; then
|
||||||
|
enable_dbus=yes
|
||||||
|
AC_DEFINE([HAVE_DBUS], [1], [Build with dbus support])
|
||||||
|
else
|
||||||
|
enable_dbus=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(ENABLE_DBUS, test "x$enable_dbus" = "xyes")
|
||||||
|
|
||||||
|
# ivi-shell support
|
||||||
|
AC_ARG_ENABLE(ivi-shell,
|
||||||
|
AS_HELP_STRING([--disable-ivi-shell],
|
||||||
|
[do not build ivi-shell server plugin and client]),,
|
||||||
|
enable_ivi_shell=yes)
|
||||||
|
AM_CONDITIONAL(ENABLE_IVI_SHELL, test "x$enable_ivi_shell" = "xyes")
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(wcap-tools, [ --disable-wcap-tools],, enable_wcap_tools=yes)
|
||||||
|
AM_CONDITIONAL(BUILD_WCAP_TOOLS, test x$enable_wcap_tools = xyes)
|
||||||
|
if test x$enable_wcap_tools = xyes; then
|
||||||
|
AC_DEFINE([BUILD_WCAP_TOOLS], [1], [Build the wcap tools])
|
||||||
|
PKG_CHECK_MODULES(WCAP, [cairo])
|
||||||
|
WCAP_LIBS="$WCAP_LIBS -lm"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(SETBACKLIGHT, [libudev libdrm], enable_setbacklight=yes, enable_setbacklight=no)
|
||||||
|
AM_CONDITIONAL(BUILD_SETBACKLIGHT, test "x$enable_setbacklight" = "xyes")
|
||||||
|
|
||||||
|
if test "x$GCC" = "xyes"; then
|
||||||
|
GCC_CFLAGS="-Wall -Wextra -Wno-unused-parameter \
|
||||||
|
-Wno-missing-field-initializers -g -fvisibility=hidden \
|
||||||
|
-Wstrict-prototypes -Wmissing-prototypes -Wsign-compare"
|
||||||
|
fi
|
||||||
|
AC_SUBST(GCC_CFLAGS)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(libunwind,
|
||||||
|
AS_HELP_STRING([--disable-libunwind],
|
||||||
|
[Disable libunwind usage for backtraces]),,
|
||||||
|
enable_libunwind=auto)
|
||||||
|
AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$enable_libunwind" = xyes])
|
||||||
|
if test "x$enable_libunwind" != "xno"; then
|
||||||
|
PKG_CHECK_MODULES(LIBUNWIND,
|
||||||
|
libunwind,
|
||||||
|
have_libunwind=yes,
|
||||||
|
have_libunwind=no)
|
||||||
|
if test "x$have_libunwind" = "xno" -a "x$enable_libunwind" = "xyes"; then
|
||||||
|
AC_MSG_ERROR([libunwind support explicitly requested, but libunwind couldn't be found])
|
||||||
|
fi
|
||||||
|
if test "x$have_libunwind" = "xyes"; then
|
||||||
|
enable_libunwind=yes
|
||||||
|
AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if test "x$WESTON_NATIVE_BACKEND" = "x"; then
|
||||||
|
WESTON_NATIVE_BACKEND="drm-backend.so"
|
||||||
|
fi
|
||||||
|
AC_MSG_NOTICE([Weston's native backend: $WESTON_NATIVE_BACKEND])
|
||||||
|
AC_DEFINE_UNQUOTED([WESTON_NATIVE_BACKEND], ["$WESTON_NATIVE_BACKEND"],
|
||||||
|
[The default backend to load, if not wayland nor x11.])
|
||||||
|
|
||||||
|
if test "x$WESTON_SHELL_CLIENT" = "x"; then
|
||||||
|
WESTON_SHELL_CLIENT="weston-desktop-shell"
|
||||||
|
fi
|
||||||
|
AC_MSG_NOTICE([Weston's default desktop shell client: $WESTON_SHELL_CLIENT])
|
||||||
|
AC_DEFINE_UNQUOTED([WESTON_SHELL_CLIENT], ["$WESTON_SHELL_CLIENT"],
|
||||||
|
[The default desktop shell client to load.])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(demo-clients-install,
|
||||||
|
AS_HELP_STRING([--enable-demo-clients-install],
|
||||||
|
[Install demo clients built with weston]),,
|
||||||
|
enable_demo_clients_install=no)
|
||||||
|
AM_CONDITIONAL(INSTALL_DEMO_CLIENTS, [test "x$enable_demo_clients_install" = "xyes"])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LCMS, lcms2,
|
||||||
|
[have_lcms=yes], [have_lcms=no])
|
||||||
|
if test "x$have_lcms" = xyes; then
|
||||||
|
AC_DEFINE(HAVE_LCMS, 1, [Have lcms support])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_LCMS, [test "x$have_lcms" = xyes])
|
||||||
|
|
||||||
|
AC_PATH_PROG([wayland_scanner], [wayland-scanner])
|
||||||
|
if test x$wayland_scanner = x; then
|
||||||
|
PKG_CHECK_MODULES(WAYLAND_SCANNER, [wayland-scanner])
|
||||||
|
wayland_scanner=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile src/version.h src/weston.pc])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([HAVE_GIT_REPO], [test -f $srcdir/.git/logs/HEAD])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
AC_MSG_RESULT([
|
||||||
|
Native Backend ${WESTON_NATIVE_BACKEND}
|
||||||
|
setuid Install ${enable_setuid_install}
|
||||||
|
|
||||||
|
Cairo Renderer ${with_cairo}
|
||||||
|
EGL ${enable_egl}
|
||||||
|
libxkbcommon ${enable_xkbcommon}
|
||||||
|
xcb_xkb ${have_xcb_xkb}
|
||||||
|
XWayland ${enable_xwayland}
|
||||||
|
dbus ${enable_dbus}
|
||||||
|
|
||||||
|
ivi-shell ${enable_ivi_shell}
|
||||||
|
|
||||||
|
Build wcap utility ${enable_wcap_tools}
|
||||||
|
Build Fullscreen Shell ${enable_fullscreen_shell}
|
||||||
|
|
||||||
|
weston-launch utility ${enable_weston_launch}
|
||||||
|
systemd-login support ${have_systemd_login}
|
||||||
|
|
||||||
|
DRM Compositor ${enable_drm_compositor}
|
||||||
|
X11 Compositor ${enable_x11_compositor}
|
||||||
|
Wayland Compositor ${enable_wayland_compositor}
|
||||||
|
Headless Compositor ${enable_headless_compositor}
|
||||||
|
RPI Compositor ${enable_rpi_compositor}
|
||||||
|
FBDEV Compositor ${enable_fbdev_compositor}
|
||||||
|
RDP Compositor ${enable_rdp_compositor}
|
||||||
|
Screen Sharing ${enable_screen_sharing}
|
||||||
|
|
||||||
|
Raspberry Pi BCM headers ${have_bcm_host}
|
||||||
|
|
||||||
|
Build Clients ${enable_clients}
|
||||||
|
Build EGL Clients ${have_cairo_egl}
|
||||||
|
Build Simple Clients ${enable_simple_clients}
|
||||||
|
Build Simple EGL Clients ${enable_simple_egl_clients}
|
||||||
|
|
||||||
|
Install Demo Clients ${enable_demo_clients_install}
|
||||||
|
|
||||||
|
Colord Support ${have_colord}
|
||||||
|
GLU Support ${have_glu}
|
||||||
|
LCMS2 Support ${have_lcms}
|
||||||
|
libwebp Support ${have_webp}
|
||||||
|
libunwind Support ${have_libunwind}
|
||||||
|
VA H.264 encoding Support ${have_libva}
|
||||||
|
])
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
prog_gcovr = find_program('gcovr', required: false, disabler: true)
|
|
||||||
|
|
||||||
# Configure the build:
|
|
||||||
# $ meson configure -Db_sanitize=none -Db_coverage=true -Dwerror=true
|
|
||||||
#
|
|
||||||
# Ensure there are no stale .gcno or .gcda files around:
|
|
||||||
# $ meson setup --wipe ~/git/weston
|
|
||||||
#
|
|
||||||
# Run the test suite:
|
|
||||||
# $ meson compile
|
|
||||||
# $ meson test
|
|
||||||
#
|
|
||||||
# Generate the reports:
|
|
||||||
# $ meson compile gcovr-report
|
|
||||||
|
|
||||||
run_target(
|
|
||||||
'gcovr-report',
|
|
||||||
command: [
|
|
||||||
prog_gcovr,
|
|
||||||
'--root', '@SOURCE_ROOT@',
|
|
||||||
'--cobertura', meson.current_build_dir() / 'cobertura.xml',
|
|
||||||
'--html', meson.current_build_dir() / 'index.html',
|
|
||||||
'--html-nested',
|
|
||||||
'--html-theme', 'github.green',
|
|
||||||
'--html-title', 'Weston test suite coverage',
|
|
||||||
'--print-summary',
|
|
||||||
meson.project_build_root(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
19
data/COPYING
|
|
@ -33,24 +33,5 @@ home.png
|
||||||
icon_ivi_clickdot.png
|
icon_ivi_clickdot.png
|
||||||
icon_ivi_flower.png
|
icon_ivi_flower.png
|
||||||
icon_ivi_simple-egl.png
|
icon_ivi_simple-egl.png
|
||||||
icon_ivi_simple-egl-vertical.png
|
|
||||||
icon_ivi_simple-shm.png
|
icon_ivi_simple-shm.png
|
||||||
icon_ivi_smoke.png
|
icon_ivi_smoke.png
|
||||||
|
|
||||||
|
|
||||||
For the SVG icons:
|
|
||||||
|
|
||||||
© 2016 Samsung Electronics Co., Ltd
|
|
||||||
|
|
||||||
This work is dual-licenced under both the MIT "Expat" License and the
|
|
||||||
Creative Commons Attribution-Share Alike 3.0 United States License, and
|
|
||||||
may be redistributed under either (or both) licenses as desired. See
|
|
||||||
Weston's COPYING for details of the MIT license. To view a copy of the
|
|
||||||
CC-SA-3.0 licence, visit http://creativecommons.org/licenses/by-sa/3.0/
|
|
||||||
or send a letter to Creative Commons, 171 Second Street, Suite 300, San
|
|
||||||
Francisco, California 94105, USA.
|
|
||||||
|
|
||||||
icons.svg
|
|
||||||
icon_terminal.png
|
|
||||||
icon_editor.png
|
|
||||||
icon_flower.png
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 240 KiB |
BIN
data/border.png
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
data/home.png
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 737 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 525 B |
|
Before Width: | Height: | Size: 86 B After Width: | Height: | Size: 161 B |
1012
data/icons.svg
|
Before Width: | Height: | Size: 47 KiB |
|
|
@ -1,30 +0,0 @@
|
||||||
install_data(
|
|
||||||
[
|
|
||||||
'background.png',
|
|
||||||
'border.png',
|
|
||||||
'fullscreen.png',
|
|
||||||
'home.png',
|
|
||||||
'icon_editor.png',
|
|
||||||
'icon_flower.png',
|
|
||||||
'icon_ivi_clickdot.png',
|
|
||||||
'icon_ivi_flower.png',
|
|
||||||
'icon_ivi_simple-egl.png',
|
|
||||||
'icon_ivi_simple-egl-vertical.png',
|
|
||||||
'icon_ivi_simple-shm.png',
|
|
||||||
'icon_ivi_smoke.png',
|
|
||||||
'icon_terminal.png',
|
|
||||||
'icon_window.png',
|
|
||||||
'panel.png',
|
|
||||||
'pattern.png',
|
|
||||||
'random.png',
|
|
||||||
'sidebyside.png',
|
|
||||||
'sign_close.png',
|
|
||||||
'sign_maximize.png',
|
|
||||||
'sign_minimize.png',
|
|
||||||
'terminal.png',
|
|
||||||
'tiling.png',
|
|
||||||
'wayland.png',
|
|
||||||
'wayland.svg',
|
|
||||||
],
|
|
||||||
install_dir: dir_data / 'weston'
|
|
||||||
)
|
|
||||||
BIN
data/panel.png
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 41 KiB |
BIN
data/pattern.png
|
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 1.8 KiB |
BIN
data/random.png
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 235 B |
|
Before Width: | Height: | Size: 85 B After Width: | Height: | Size: 204 B |
|
Before Width: | Height: | Size: 79 B After Width: | Height: | Size: 191 B |