diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 2bd707e8..00000000 --- a/.editorconfig +++ /dev/null @@ -1,24 +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,xsl}] -indent_style = space -indent_size = 2 -tab_width = 8 - -[*.py] -indent_style = space -indent_size = 4 - -[*.yml] -indent_style = space -indent_size = 2 -max_line_length = off diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs deleted file mode 100644 index 311e3e0e..00000000 --- a/.git-blame-ignore-revs +++ /dev/null @@ -1,4 +0,0 @@ -# Use the following command to ignore the following commits in git blame: -# git config blame.ignoreRevsFile .git-blame-ignore-revs - -77b9eb76369e27142b8be296b5f2eb1ca466272a # protocol: reindent wayland.xml diff --git a/.gitignore b/.gitignore index 4fefe5d3..d9d26ed3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,58 @@ -*.announce -*.sig +*.deps +*.jpg +*.la +*.lo +*.o +*.pc +*.so *.swp +*.3 +*.7 *.log +*.trs *.tar.xz *~ +.libs +.dirstamp cscope.out ctags +/aclocal.m4 +/wayland-scanner.m4 +/autom4te.cache +/compile +/config.guess +/config.h +/config.h.in +/config.log +/config.mk +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/missing +/stamp-h1 +/test-driver +Makefile +Makefile.in +array-test +client-test +connection-test +display-test +event-loop-test +exec-fd-leak-checker +fixed-benchmark +fixed-test +list-test +map-test +message-test +os-wrappers-test +queue-test +resources-test +sanity-test +signal-test +socket-test +wayland-scanner +protocol/*.[ch] diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index cd7b5113..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,356 +0,0 @@ -# This file uses the freedesktop ci-templates to build Wayland 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/ - -include: - - project: 'freedesktop/ci-templates' - # 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. - ref: 48c2c583a865bd59be21e8938df247faf460099c - file: - - '/templates/debian.yml' - - '/templates/freebsd.yml' - - '/templates/ci-fairy.yml' - -variables: - FDO_UPSTREAM_REPO: wayland/wayland - FDO_REPO_SUFFIX: "$BUILD_OS/$BUILD_ARCH" - - -# Define the build stages. These are used for UI grouping as well as -# dependencies. -stages: - - "Merge request checks" - - "Base container" - - "Build and test" - - "Other build configurations" - -workflow: - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS - when: never - - if: $CI_COMMIT_BRANCH - -.ci-rules: - rules: - - when: on_success - -# Base variables used for anything using a Debian environment -.os-debian: - variables: - BUILD_OS: debian - FDO_DISTRIBUTION_VERSION: trixie - FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config libexpat1-dev libffi-dev libxml2-dev doxygen graphviz xmlto xsltproc docbook-xsl mdbook meson ninja-build' - # bump this tag every time you change something which requires rebuilding the - # base image - FDO_DISTRIBUTION_TAG: "2026-01-31.0" - -.debian-x86_64: - extends: - - .os-debian - variables: - BUILD_ARCH: "x86-64" - -.debian-aarch64: - extends: - - .os-debian - variables: - BUILD_ARCH: "aarch64" - -.debian-armv7: - extends: - - .os-debian - variables: - BUILD_ARCH: "armv7" - FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7" - - -# Does not inherit .ci-rules as we only want it to run in MR context. -check-commit: - extends: - - .fdo.ci-fairy - stage: "Merge request checks" - rules: - - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - when: always - - when: never - script: - - ci-fairy check-commits --signed-off-by --junit-xml=results.xml - variables: - GIT_DEPTH: 100 - artifacts: - reports: - junit: results.xml - - -# 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-container_prep: - extends: - - .ci-rules - - .debian-x86_64 - - .fdo.container-build@debian - stage: "Base container" - variables: - GIT_STRATEGY: none - -aarch64-debian-container_prep: - extends: - - .ci-rules - - .debian-aarch64 - - .fdo.container-build@debian - tags: - - aarch64 - stage: "Base container" - variables: - GIT_STRATEGY: none - -armv7-debian-container_prep: - extends: - - .ci-rules - - .debian-armv7 - - .fdo.container-build@debian - tags: - - aarch64 - stage: "Base container" - variables: - GIT_STRATEGY: none - - -# Core build environment. -.build-env: - variables: - MESON_BUILD_TYPE: "-Dbuildtype=debug -Doptimization=0 -Db_sanitize=address,undefined -Ddocbook_validation=true" - # See https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/154 - ASAN_OPTIONS: "detect_odr_violation=0" - before_script: - - export BUILD_ID="wayland-$CI_JOB_NAME" - - export PREFIX="${CI_PROJECT_DIR}/prefix-${BUILD_ID}" - - export BUILDDIR="${CI_PROJECT_DIR}/build-${BUILD_ID}" - - mkdir "$BUILDDIR" "$PREFIX" - - -# Build variants to be stacked on as required. -.build-release: - stage: "Other build configurations" - variables: - MESON_BUILD_TYPE: "-Dbuildtype=release" - - -# OS/architecture-specific variants -.build-env-debian-x86_64: - extends: - - .fdo.suffixed-image@debian - - .debian-x86_64 - - .build-env - needs: - - job: x86_64-debian-container_prep - artifacts: false - -.build-env-debian-aarch64: - extends: - - .fdo.suffixed-image@debian - - .debian-aarch64 - - .build-env - variables: - # At least with the versions we have, the LSan runtime makes fork unusably - # slow on AArch64, which is bad news since the test suite decides to fork - # for every single subtest. For now, in order to get AArch64 builds and - # tests into CI, just assume that we're not going to leak any more on - # AArch64 than we would on ARMv7 or x86-64. - ASAN_OPTIONS: "detect_leaks=0,detect_odr_violation=0" - tags: - - aarch64 - needs: - - job: aarch64-debian-container_prep - artifacts: false - -.build-env-debian-armv7: - extends: - - .fdo.suffixed-image@debian - - .debian-armv7 - - .build-env - tags: - - aarch64 - needs: - - job: armv7-debian-container_prep - artifacts: false - - -# Full build and test. -.do-build: - extends: - - .ci-rules - stage: "Build and test" - script: - - meson setup $BUILDDIR --prefix="$PREFIX" -Dicon_directory=/usr/share/X11/icons --fatal-meson-warnings -Dwerror=true ${MESON_BUILD_TYPE} - - ninja -C $BUILDDIR -k0 -j${FDO_CI_CONCURRENT:-4} - - meson test -C $BUILDDIR --num-processes ${FDO_CI_CONCURRENT:-4} - - ninja -C $BUILDDIR install - - ninja -C $BUILDDIR clean - artifacts: - name: wayland-$CI_JOB_NAME - when: always - paths: - - build-*/meson-logs - - prefix-* - reports: - junit: build-*/meson-logs/testlog.junit.xml - -# Full build and test. -.do-build-qemu: - extends: - - .ci-rules - stage: "Build and test" - script: - # Start the VM and copy our workspace to the VM - - /app/vmctl start - - scp -r $PWD "vm:" - # The `set +e is needed to ensure that we always copy the meson logs back to - # the workspace to see details about the failed tests. - - | - set +e - /app/vmctl exec "pkg info; cd $CI_PROJECT_NAME ; meson setup $BUILDDIR --prefix=$PREFIX $MESON_BUILD_TYPE $MESON_ARGS && ninja -C $BUILDDIR -j${FDO_CI_CONCURRENT:-4}" - /app/vmctl exec "meson test --print-errorlogs -C $BUILDDIR --num-processes ${FDO_CI_CONCURRENT:-4}" && touch .tests-successful - set -ex - scp -r vm:$BUILDDIR/meson-logs . - /app/vmctl exec "ninja -C $BUILDDIR install" - mkdir -p $PREFIX && scp -r vm:$PREFIX/ $PREFIX/ - # Finally, shut down the VM. - - /app/vmctl stop - - test -f .tests-successful || exit 1 - artifacts: - name: wayland-$CI_JOB_NAME - when: always - paths: - - meson-logs - - prefix-* - reports: - junit: meson-logs/testlog.junit.xml - -# Full build and test. -x86_64-debian-build: - extends: - - .build-env-debian-x86_64 - - .do-build - -x86_64-release-debian-build: - extends: - - .build-env-debian-x86_64 - - .do-build - - .build-release - -aarch64-debian-build: - extends: - - .build-env-debian-aarch64 - - .do-build - -aarch64-release-debian-build: - extends: - - .build-env-debian-aarch64 - - .do-build - - .build-release - -armv7-debian-build: - extends: - - .build-env-debian-armv7 - - .do-build - -armv7-release-debian-build: - extends: - - .build-env-debian-armv7 - - .do-build - - .build-release - -# Base variables used for anything using a FreeBSD environment -.os-freebsd: - variables: - BUILD_OS: freebsd - FDO_DISTRIBUTION_VERSION: "14.4" - FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2' - # bump this tag every time you change something which requires rebuilding the - # base image - FDO_DISTRIBUTION_TAG: "2026-03-10.0" - # Don't build documentation since installing the required tools massively - # increases the VM image (and therefore container) size. - MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false" - -.freebsd-x86_64: - extends: - - .os-freebsd - variables: - BUILD_ARCH: "x86_64" - -x86_64-freebsd-container_prep: - extends: - - .ci-rules - - .freebsd-x86_64 - - .fdo.qemu-build@freebsd@x86_64 - stage: "Base container" - variables: - GIT_STRATEGY: none - -.build-env-freebsd-x86_64: - variables: - # Compiling with ASan+UBSan appears to trigger an infinite loop in the - # compiler shipped with FreeBSD 13.0, so we only use UBSan here. - # Additionally, sanitizers can't be used with b_lundef on FreeBSD. - MESON_BUILD_TYPE: "-Dbuildtype=debug -Db_sanitize=undefined -Db_lundef=false" - extends: - - .fdo.suffixed-image@freebsd - - .freebsd-x86_64 - - .build-env - needs: - - job: x86_64-freebsd-container_prep - artifacts: false - -# Full build and test. -x86_64-freebsd-build: - extends: - - .build-env-freebsd-x86_64 - - .do-build-qemu - -x86_64-release-freebsd-build: - extends: - - .build-env-freebsd-x86_64 - - .do-build-qemu - - .build-release diff --git a/.gitlab/issue_templates/default.md b/.gitlab/issue_templates/default.md deleted file mode 100644 index f8149cee..00000000 --- a/.gitlab/issue_templates/default.md +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/.mailmap b/.mailmap deleted file mode 100644 index bdb791e7..00000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -Faith Ekstrand -Faith Ekstrand -Faith Ekstrand diff --git a/.triage-policies.yml b/.triage-policies.yml deleted file mode 100644 index 580bead4..00000000 --- a/.triage-policies.yml +++ /dev/null @@ -1,33 +0,0 @@ -# This is a set of bugbot commands for issues and merge requests - setting any of the -# bugbot::foo labels will trigger gitlab-triage to run with this ruleset (well, the -# one we have on the main branch at the time) -# -# Note that for adding labels, the label must first created in the project. -resource_rules: - issues: - rules: - - name: "Close bugs that aren't Wayland bugs" - conditions: - labels: - - "bugbot::not-wayland" - actions: - remove_labels: - - "bugbot::not-wayland" - comment: | - Thank you for the report, but your issue does not look like it would belong here. Sorry. - - This repository is for the Wayland protocol specification and the - low-level C library that deals with the protocol. - - This issue here is a bug not with the protocol itself but with either - - your compositor or desktop environment's implementation of the Wayland protocol and surrounding functionality, - - the individual application that triggers this issue, or - - the kernel driver used by your hardware - - Please file the issue against your compositor/desktop environment, the application - or the kernel drivers instead, whichever seems more likely to you. If you are not sure, - file an issue against the application. - status: "close" - merge_requests: - rules: - [] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 1ea351f0..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,344 +0,0 @@ -Contributing to Wayland -======================= - -Sending patches ---------------- - -Patches should be sent via -[GitLab merge requests](https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.html). -Wayland is -[hosted on freedesktop.org's GitLab](https://gitlab.freedesktop.org/wayland/wayland/): -in order to submit code, you should create an account on this GitLab instance, -fork the core Wayland repository, push your changes to a branch in your new -repository, and then submit these patches for review through a merge request. - -Wayland 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/). -Some old patches continue to be sent this way, and we may accept small new -patches sent to the list, but please send all new patches through GitLab merge -requests. - - -Formatting and separating commits ---------------------------------- - -Unlike many projects using GitHub and GitLab, Wayland 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: - - connection: plug a fd leak - plug another fd leak - connection: init fds to -1 - close all fds - refactor checks into a new function - don't close fds we handed out - -we aim to have a clean history which only reflects the final state, broken up -into functional groupings: - - connection: Refactor out closure allocation - connection: Clear fds we shouldn't close to -1 - connection: Make wl_closure_destroy() close fds of undispatched closures - -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: - - protocol: Support scaled outputs and surfaces - -and - - doc: generate server documentation from XML too - -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 should also include a Signed-off-by line with your name and -email address. If you're not the patch's original author, you should -also gather S-o-b's by them (and/or whomever gave the patch to you.) 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. - -We won't reject patches that lack S-o-b, but it is strongly recommended. - -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 Wayland -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 elsewhere -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 implemented 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); -``` - -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 -========= - -Wayland 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, Wayland 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 diff --git a/COPYING b/COPYING index eb25a4e2..6ba3d981 100644 --- a/COPYING +++ b/COPYING @@ -3,27 +3,20 @@ Copyright © 2010-2012 Intel Corporation Copyright © 2011 Benjamin Franzke Copyright © 2012 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: +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 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. - ---- - -The above is the version of the MIT "Expat" License used by X.org: - - http://cgit.freedesktop.org/xorg/xserver/tree/COPYING +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. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..1551762a --- /dev/null +++ b/Makefile.am @@ -0,0 +1,198 @@ +if BUILD_DOCS +SUBDIRS = doc +endif + +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +aclocaldir = $(datadir)/aclocal +dist_aclocal_DATA = wayland-scanner.m4 + +dist_pkgdata_DATA = \ + wayland-scanner.mk \ + protocol/wayland.xml \ + protocol/wayland.dtd + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = + +lib_LTLIBRARIES = libwayland-server.la libwayland-client.la +noinst_LTLIBRARIES = libwayland-util.la + +include_HEADERS = \ + src/wayland-util.h \ + src/wayland-server.h \ + src/wayland-client.h \ + src/wayland-egl.h \ + src/wayland-version.h + +nodist_include_HEADERS = \ + protocol/wayland-server-protocol.h \ + protocol/wayland-client-protocol.h + +libwayland_util_la_SOURCES = \ + src/connection.c \ + src/wayland-util.c \ + src/wayland-util.h \ + src/wayland-os.c \ + src/wayland-os.h \ + src/wayland-private.h + +libwayland_server_la_CFLAGS = $(FFI_CFLAGS) $(GCC_CFLAGS) -pthread +libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm +libwayland_server_la_LDFLAGS = -version-info 1:0:1 +libwayland_server_la_SOURCES = \ + src/wayland-server.c \ + src/wayland-shm.c \ + src/event-loop.c + +nodist_libwayland_server_la_SOURCES = \ + protocol/wayland-server-protocol.h \ + protocol/wayland-protocol.c + +libwayland_client_la_CFLAGS = $(FFI_CFLAGS) $(GCC_CFLAGS) -pthread +libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm +libwayland_client_la_LDFLAGS = -version-info 3:0:3 +libwayland_client_la_SOURCES = \ + src/wayland-client.c + +nodist_libwayland_client_la_SOURCES = \ + protocol/wayland-client-protocol.h \ + protocol/wayland-protocol.c + +pkgconfig_DATA += src/wayland-client.pc src/wayland-server.pc + +if ENABLE_SCANNER +wayland_scanner = $(top_builddir)/wayland-scanner +bin_PROGRAMS = wayland-scanner +wayland_scanner_SOURCES = src/scanner.c +wayland_scanner_LDADD = $(EXPAT_LIBS) libwayland-util.la +$(BUILT_SOURCES) : wayland-scanner +pkgconfig_DATA += src/wayland-scanner.pc +else +wayland_scanner = wayland-scanner +endif + +protocol/%-protocol.c : $(top_srcdir)/protocol/%.xml + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) code < $< > $@ + +protocol/%-server-protocol.h : $(top_srcdir)/protocol/%.xml + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) server-header < $< > $@ + +protocol/%-client-protocol.h : $(top_srcdir)/protocol/%.xml + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) client-header < $< > $@ + +BUILT_SOURCES = \ + $(nodist_libwayland_server_la_SOURCES) \ + $(nodist_libwayland_client_la_SOURCES) + +CLEANFILES = $(BUILT_SOURCES) +DISTCLEANFILES = src/wayland-version.h +EXTRA_DIST = src/wayland-version.h.in + + + +lib_LTLIBRARIES += libwayland-cursor.la + +include_HEADERS += cursor/wayland-cursor.h + +libwayland_cursor_la_SOURCES = \ + cursor/wayland-cursor.c \ + cursor/os-compatibility.c \ + cursor/os-compatibility.h \ + cursor/cursor-data.h \ + cursor/xcursor.c \ + cursor/xcursor.h +libwayland_cursor_la_LIBADD = libwayland-client.la + +pkgconfig_DATA += cursor/wayland-cursor.pc + +libwayland_cursor_la_CFLAGS = \ + $(GCC_CFLAGS) \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -DICONDIR=\"$(ICONDIR)\" + + +TESTS = \ + array-test \ + client-test \ + display-test \ + connection-test \ + event-loop-test \ + fixed-test \ + list-test \ + map-test \ + os-wrappers-test \ + sanity-test \ + socket-test \ + queue-test \ + signal-test \ + resources-test \ + message-test + +check_PROGRAMS = \ + $(TESTS) \ + exec-fd-leak-checker + +noinst_PROGRAMS = \ + fixed-benchmark + +check_LTLIBRARIES = libtest-runner.la + +libtest_runner_la_SOURCES = \ + tests/test-runner.c \ + tests/test-runner.h \ + tests/test-helpers.c \ + tests/test-compositor.h \ + tests/test-compositor.c +libtest_runner_la_LIBADD = \ + libwayland-util.la \ + libwayland-client.la \ + libwayland-server.la \ + -lrt -ldl $(FFI_LIBS) + + +array_test_SOURCES = tests/array-test.c +array_test_LDADD = libtest-runner.la +client_test_SOURCES = tests/client-test.c +client_test_LDADD = libtest-runner.la +display_test_SOURCES = tests/display-test.c +display_test_LDADD = libtest-runner.la +connection_test_SOURCES = tests/connection-test.c +connection_test_LDADD = libtest-runner.la +event_loop_test_SOURCES = tests/event-loop-test.c +event_loop_test_LDADD = libtest-runner.la +fixed_test_SOURCES = tests/fixed-test.c +fixed_test_LDADD = libtest-runner.la +list_test_SOURCES = tests/list-test.c +list_test_LDADD = libtest-runner.la +map_test_SOURCES = tests/map-test.c +map_test_LDADD = libtest-runner.la +sanity_test_SOURCES = tests/sanity-test.c +sanity_test_LDADD = libtest-runner.la +socket_test_SOURCES = tests/socket-test.c +socket_test_LDADD = libtest-runner.la +queue_test_SOURCES = tests/queue-test.c +queue_test_LDADD = libtest-runner.la +signal_test_SOURCES = tests/signal-test.c +signal_test_LDADD = libtest-runner.la +resources_test_SOURCES = tests/resources-test.c +resources_test_LDADD = libtest-runner.la +message_test_SOURCES = tests/message-test.c +message_test_LDADD = libtest-runner.la + +fixed_benchmark_SOURCES = tests/fixed-benchmark.c +fixed_benchmark_LDADD = libtest-runner.la + +os_wrappers_test_SOURCES = tests/os-wrappers-test.c +os_wrappers_test_LDADD = libtest-runner.la + +AM_CPPFLAGS = \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/protocol + +AM_CFLAGS = $(GCC_CFLAGS) $(FFI_CFLAGS) + +exec_fd_leak_checker_SOURCES = tests/exec-fd-leak-checker.c +exec_fd_leak_checker_LDADD = libtest-runner.la diff --git a/README.md b/README similarity index 70% rename from README.md rename to README index 437b39da..ca26cc06 100644 --- a/README.md +++ b/README @@ -1,4 +1,4 @@ -# Wayland +What is Wayland Wayland is a project to define a protocol for a compositor to talk to its clients as well as a library implementation of the protocol. The @@ -17,14 +17,19 @@ protocol does not handle rendering, which is one of the features that makes wayland so simple. All clients are expected to handle rendering themselves, typically through cairo or OpenGL. +The weston compositor is a reference implementation of a wayland +compositor and the weston repository also includes a few example +clients. + Building the wayland libraries is fairly simple, aside from libffi, they don't have many dependencies: - $ git clone https://gitlab.freedesktop.org/wayland/wayland + $ git clone git://anongit.freedesktop.org/wayland/wayland $ cd wayland - $ meson build/ --prefix=PREFIX - $ ninja -C build/ install + $ ./autogen.sh --prefix=PREFIX + $ make + $ make install -where PREFIX is where you want to install the libraries. - -See https://wayland.freedesktop.org for documentation. +where PREFIX is where you want to install the libraries. See +http://wayland.freedesktop.org for more complete build instructions +for wayland, weston, xwayland and various toolkits. diff --git a/TODO b/TODO new file mode 100644 index 00000000..8cb8d346 --- /dev/null +++ b/TODO @@ -0,0 +1,149 @@ +Core wayland protocol + + - Maybe try to make remote wayland actually happen, to see if there + is something in the protocol/architecture that makes it harder than + it should be. + +ICCCM + + - mime-type guidelines for data_source (ie, both dnd and selection): + recommended types for text or images, types that a clipboard + manager must support, mime-types must be listed in preferred order + + - we need a "no kb focus please" mechanism. Or should this be + implicit in a specific surface type? + +EWMH + + - configure should provide dx_left, dx_right, dy_top, dy_bottom, or + dx, dy, width and height. + + - move to workspace, keep on top, on all workspaces, minimize etc + requests for implementing client side window menu? or just make a + "show window menu" request to let the compositor display and manage + a popup window? + + - window move and resize functionality for kb and touch. + + - Protocol for specifying title bar rectangle (for moving + unresponsive apps). Rectangle for close button, so we can popup + force-close dialog if application doesn't respond to ping event + when user clicks there. We could use the region mechanism here + too. + + - popup placement protocol logic. + + - subsurface mechanism. we need this for cases where we would use an + X subwindow for gl or video other different visual type. + +EGL/gbm + + - Land Robert Braggs EGL extensions: frame age, swap with damage + + - Make it possible to share buffers from compositor to clients. + Tricky part here is how to indicate to EGL on the server side that + it should make an EGLImage available to a client. We'll need a + "create a wl_buffer for this EGLImage for this client" kind of + entry point. + + - Protocol for arbitrating access to scanout buffers (physically + contiguous memory). When a client goes fullscreen (or ideally as + the compositor starts the animation that will make it fullscreen) + we send a "give up your scanout buffer" to the current fullscreen + client (if any) and when the client acks that we send a "try to + allocate a scanout buffer now" event to the fullscreen-to-be + client. + + +Misc + + - glyph cache + + - Needs a mechanism to pass buffers to client. + + buffer = drm.create_buffer(); /* buffer with stuff in it */ + + cache.upload(buffer, x, y, width, height, int hash) + + drm.buffer: id, name, stride etc /* event to announce cache buffer */ + + cache.image: hash, buffer, x, y, stride /* event to announce + * location in cache */ + + cache.reject: hash /* no upload for you! */ + + cache.retire: buffer /* cache has stopped using buffer, please + * reupload whatever you had in that buffer */ + + - A "please suspend" event from the compositor, to indicate to an + application that it's no longer visible/active. Or maybe discard + buffer, as in "wayland discarded your buffer, it's no longer + visible, you can stop updating it now.", reattach, as in "oh hey, + I'm about to show your buffer that I threw away, what was it + again?". for wayland system compositor vt switcing, for example, + to be able to throw away the surfaces in the session we're + switching away from. for minimized windows that we don't want live + thumb nails for. etc. + + +Clients and ports + + - port gtk+ + + - draw window decorations in gtkwindow.c + + - Details about pointer grabs. wayland doesn't have active grabs, + menus will behave subtly different. Under X, clicking a menu + open grabs the pointer and clicking outside the window pops down + the menu and swallows the click. without active grabs we can't + swallow the click. I'm sure there much more... + + - dnd, copy-paste + + - Investigate DirectFB on Wayland (or is that Wayland on DirectFB?) + + - SDL port, bnf has work in progress here: + http://cgit.freedesktop.org/~bnf/sdl-wayland/ + + +Ideas + + - A wayland settings protocol to tell clients about themes (icons, + cursors, widget themes), fonts details (family, hinting + preferences) etc. Just send all settings at connect time, send + updates when a setting change. Getting a little close to gconf + here, but could be pretty simple: + + interface "settings": + event int_value(string name, int value) + event string_value(string name, string value) + + but maybe it's better to just require that clients get that from + somewhere else (gconf/dbus). + + +Crazy ideas + + - AF_WAYLAND - A new socket type. Eliminate compositor context + switch by making kernel understand enough of wayland that it can + forward input events as wayland events and do page flipping in + response to surface_attach requests: + + - ioctl(wayland_fd, "surface_attach to object 5 should do a kms page + flip on ctrc 2"); + + - what about multiple crtcs? what about frame event for other + clients? + + - forward these input devices to the client + + - "scancode 124 pressed or released with scan codes 18,22 and 30 + held down gives control back to userspace wayland. + + - what about maintaining cursor position? what about pointer + acceleration? maybe this only works in "client cursor mode", + where wayland hides the cursor and only sends relative events? + Solves the composited cursor problem. How does X show its + cursor then? + + - Probably not worth it. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..916169a4 --- /dev/null +++ b/autogen.sh @@ -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" "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..5deed2be --- /dev/null +++ b/configure.ac @@ -0,0 +1,143 @@ +AC_PREREQ([2.64]) + +m4_define([wayland_major_version], [1]) +m4_define([wayland_minor_version], [5]) +m4_define([wayland_micro_version], [92]) +m4_define([wayland_version], + [wayland_major_version.wayland_minor_version.wayland_micro_version]) + +AC_INIT([wayland], + [wayland_version], + [https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=wayland&version=wayland_version], + [wayland], + [http://wayland.freedesktop.org/]) + +AC_SUBST([WAYLAND_VERSION_MAJOR], [wayland_major_version]) +AC_SUBST([WAYLAND_VERSION_MINOR], [wayland_minor_version]) +AC_SUBST([WAYLAND_VERSION_MICRO], [wayland_micro_version]) +AC_SUBST([WAYLAND_VERSION], [wayland_version]) + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz subdir-objects]) + +AM_SILENT_RULES([yes]) + +# Check for programs +AC_PROG_CC + +# Initialize libtool +LT_PREREQ([2.2]) +LT_INIT + +PKG_PROG_PKG_CONFIG() +PKG_CHECK_MODULES(FFI, [libffi]) + +if test "x$GCC" = "xyes"; then + GCC_CFLAGS="-Wall -Wextra -Wno-unused-parameter -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden" +fi +AC_SUBST(GCC_CFLAGS) + +AC_CHECK_FUNCS([accept4 mkostemp posix_fallocate]) + +AC_CHECK_DECL(SFD_CLOEXEC,[], + [AC_MSG_ERROR("SFD_CLOEXEC is needed to compile wayland")], + [[#include ]]) +AC_CHECK_DECL(TFD_CLOEXEC,[], + [AC_MSG_ERROR("TFD_CLOEXEC is needed to compile wayland")], + [[#include ]]) +AC_CHECK_DECL(CLOCK_MONOTONIC,[], + [AC_MSG_ERROR("CLOCK_MONOTONIC is needed to compile wayland")], + [[#include ]]) +AC_CHECK_HEADERS([execinfo.h]) + +AC_ARG_ENABLE([scanner], + [AC_HELP_STRING([--disable-scanner], + [Disable compilation of wayland-scanner])], + [], + [enable_scanner=yes]) + +AC_ARG_ENABLE([documentation], + [AC_HELP_STRING([--disable-documentation], + [Disable building the documentation])], + [], + [enable_documentation=yes]) + +AM_CONDITIONAL(ENABLE_SCANNER, test "x$enable_scanner" = xyes) + +AC_ARG_WITH(icondir, [ --with-icondir= Look for cursor icons here], + [ ICONDIR=$withval], + [ ICONDIR=${datadir}/icons]) +AC_SUBST([ICONDIR]) + +EXPAT_LIB="" +AC_ARG_WITH(expat, [ --with-expat= Use expat from here], + [ expat=$withval + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" ] ) +if test "x$enable_scanner" = "xyes"; then + AC_CHECK_HEADERS(expat.h, [AC_DEFINE(HAVE_EXPAT_H)], + [AC_MSG_ERROR([Can't find expat.h. Please install expat.])]) + AC_CHECK_LIB(expat, XML_ParserCreate, [EXPAT_LIBS="-lexpat"], + [AC_MSG_ERROR([Can't find expat library. Please install expat.])]) + AC_SUBST(EXPAT_LIBS) +fi + +AC_PATH_PROG(XSLTPROC, xsltproc) +AM_CONDITIONAL([HAVE_XSLTPROC], [test "x$XSLTPROC" != "x"]) + +AC_MSG_CHECKING([for docbook manpages stylesheet]) +MANPAGES_STYLESHEET=http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl +AC_PATH_PROGS_FEATURE_CHECK([XSLTPROC_TMP], [xsltproc], + AS_IF([`"$ac_path_XSLTPROC_TMP" --nonet "$MANPAGES_STYLESHEET" > /dev/null 2>&1`], + [HAVE_MANPAGES_STYLESHEET=yes])) +if test "x$HAVE_MANPAGES_STYLESHEET" = "xyes"; then + AM_CONDITIONAL([HAVE_MANPAGES_STYLESHEET], true) + AC_SUBST(MANPAGES_STYLESHEET) + AC_MSG_RESULT([yes]) +else + AM_CONDITIONAL([HAVE_MANPAGES_STYLESHEET], false) + AC_MSG_RESULT([no]) +fi + +AM_CONDITIONAL(BUILD_DOCS, [test x$enable_documentation = xyes]) +if test "x$enable_documentation" = "xyes"; then + AC_PATH_PROG(DOXYGEN, doxygen) + + if test "x$DOXYGEN" = "x"; then + AC_MSG_ERROR([Documentation build requested but doxygen not found. Install doxygen or disable the documentation using --disable-documentation]) + fi + + AC_PATH_PROG(PUBLICAN, publican) + + if test "x$PUBLICAN" != "x"; then + PUBLICAN_VERSION=[`$PUBLICAN -v | sed -e 's/version=v\?\([0-9]*\.[0-9]*\).*/\1/'`] + + if test [ 1 -eq `echo "${PUBLICAN_VERSION} < 2.8" | bc` ]; then + AC_MSG_ERROR([Publican version is not supported. Install publican >= 2.8 or disable the documentation using --disable-documentation]) + fi + fi + + AC_CONFIG_FILES([ + doc/doxygen/wayland.doxygen + ]) + +fi +AM_CONDITIONAL([HAVE_PUBLICAN], [test "x$PUBLICAN" != "x"]) + +AC_CONFIG_FILES([Makefile + cursor/wayland-cursor.pc + cursor/wayland-cursor-uninstalled.pc + doc/Makefile + doc/publican/Makefile + doc/doxygen/Makefile + doc/man/Makefile + src/wayland-server-uninstalled.pc + src/wayland-client-uninstalled.pc + src/wayland-scanner-uninstalled.pc + src/wayland-server.pc + src/wayland-client.pc + src/wayland-scanner.pc + src/wayland-version.h]) +AC_OUTPUT diff --git a/cursor/convert_font.c b/cursor/convert_font.c index 77e34c20..de1b8ad5 100644 --- a/cursor/convert_font.c +++ b/cursor/convert_font.c @@ -1,26 +1,23 @@ /* * Copyright © 2012 Philipp Brüschweiler * - * 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: + * 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 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. + * 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. */ /* @@ -29,6 +26,7 @@ * http://fontforge.org/pcf-format.html */ +#include #include #include #include @@ -332,38 +330,30 @@ reconstruct_glyph(struct glyph *cursor, struct glyph *mask, char *name, } } -/* - * Originally from - * http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c - * Changed to the MIT "Expat" style license for Wayland.. - */ +/* From http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c */ static const char cursor_licence[] = "/*\n" - "* Copyright 1999 SuSE, Inc.\n" - "*\n" - "* Permission is hereby granted, free of charge, to any person obtaining\n" - "* a copy of this software and associated documentation files (the\n" - "* \"Software\"), to deal in the Software without restriction, including\n" - "* without limitation the rights to use, copy, modify, merge, publish,\n" - "* distribute, sublicense, and/or sell copies of the Software, and to\n" - "* permit persons to whom the Software is furnished to do so, subject to\n" - "* the following conditions:\n" - "*\n" - "* The above copyright notice and this permission notice (including the\n" - "* next paragraph) shall be included in all copies or substantial\n" - "* portions of the Software.\n" - "*\n" - "* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n" - "* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n" - "* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n" - "* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n" - "* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n" - "* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n" - "* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" - "* SOFTWARE.\n" - "*\n" - "* Author: Keith Packard, SuSE, Inc.\n" - "*/\n"; + "* Copyright 1999 SuSE, Inc.\n" + "*\n" + "* Permission to use, copy, modify, distribute, and sell this software and its\n" + "* documentation for any purpose is hereby granted without fee, provided that\n" + "* the above copyright notice appear in all copies and that both that\n" + "* copyright notice and this permission notice appear in supporting\n" + "* documentation, and that the name of SuSE not be used in advertising or\n" + "* publicity pertaining to distribution of the software without specific,\n" + "* written prior permission. SuSE makes no representations about the\n" + "* suitability of this software for any purpose. It is provided \"as is\"\n" + "* without express or implied warranty.\n" + "*\n" + "* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL\n" + "* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE\n" + "* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n" + "* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n" + "* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n" + "* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n" + "*\n" + "* Author: Keith Packard, SuSE, Inc.\n" + "*/\n"; static void write_output_file(struct reconstructed_glyph *glyphs, int n) @@ -498,11 +488,6 @@ output_interesting_cursors() struct reconstructed_glyph *glyphs = malloc(n * sizeof(*glyphs)); - if (!glyphs) { - printf("reconstructed_glyph malloc failed\n"); - abort(); - } - for (i = 0; i < n; ++i) { struct glyph *cursor, *mask; find_cursor_and_mask(interesting_cursors[i].source_name, diff --git a/cursor/cursor-data.h b/cursor/cursor-data.h index 2ee2f8a7..4c5e6723 100644 --- a/cursor/cursor-data.h +++ b/cursor/cursor-data.h @@ -1,535 +1,529 @@ /* * Copyright 1999 SuSE, Inc. * -* 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: +* 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 SuSE not be used in advertising or +* publicity pertaining to distribution of the software without specific, +* written prior permission. SuSE makes 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 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. +* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE +* 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. * * Author: Keith Packard, SuSE, Inc. */ -#include - static uint32_t cursor_data[] = { - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, - 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, - 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, - 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0xff000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, - 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, + 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0xff000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, }; static struct cursor_metadata { @@ -551,19 +545,4 @@ static struct cursor_metadata { { "xterm", 9, 16, 4, 8, 2400 }, { "hand1", 13, 16, 12, 0, 2544 }, { "watch", 16, 16, 15, 9, 2752 }, - - /* https://www.freedesktop.org/wiki/Specifications/cursor-spec/ */ - { "sw-resize", 16, 16, 1, 14, 0 }, - { "se-resize", 16, 16, 14, 14, 256 }, - { "s-resize", 15, 16, 7, 14, 512 }, - { "all-scroll", 16, 16, 8, 8, 752 }, - { "default", 10, 16, 1, 1, 1008 }, - { "w-resize", 16, 15, 1, 7, 1168 }, - { "e-resize", 16, 15, 14, 7, 1408 }, - { "nw-resize", 16, 16, 1, 1, 1648 }, - { "ne-resize", 16, 16, 14, 1, 1904 }, - { "n-resize", 15, 16, 7, 1, 2160 }, - { "text", 9, 16, 4, 8, 2400 }, - { "pointer", 13, 16, 12, 0, 2544 }, - { "wait", 16, 16, 15, 9, 2752 }, }; diff --git a/cursor/meson.build b/cursor/meson.build deleted file mode 100644 index f7d82e4e..00000000 --- a/cursor/meson.build +++ /dev/null @@ -1,47 +0,0 @@ -icondir = get_option('icon_directory') -if icondir == '' - icondir = join_paths(get_option('prefix'), get_option('datadir'), 'icons') -endif - -if wayland_version[0] != '1' - # The versioning used for the shared libraries assumes that the major - # version of Wayland as a whole will increase to 2 if and only if there - # is an ABI break, at which point we should probably bump the SONAME of - # all libraries to .so.2. For more details see - # https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/177 - error('We probably need to bump the SONAME of libwayland-cursor') -endif - -wayland_cursor = library( - 'wayland-cursor', - sources: [ - 'wayland-cursor.c', - 'os-compatibility.c', - 'xcursor.c', - ], - # To avoid an unnecessary SONAME bump, wayland 1.x.y produces - # libwayland-cursor.so.0.x.y. - version: '.'.join(['0', wayland_version[1], wayland_version[2]]), - dependencies: [ wayland_client_dep ], - c_args: [ '-DICONDIR="@0@"'.format(icondir) ], - install: true, -) - -install_headers('wayland-cursor.h') - -pkgconfig.generate( - name: 'Wayland Cursor', - description: 'Wayland cursor helper library', - version: meson.project_version(), - libraries: wayland_cursor, - filebase: 'wayland-cursor', -) - -wayland_cursor_dep = declare_dependency( - link_with: wayland_cursor, - include_directories: [ root_inc, include_directories('.') ], -) - -if meson.version().version_compare('>= 0.54.0') - meson.override_dependency('wayland-cursor', wayland_cursor_dep) -endif diff --git a/cursor/os-compatibility.c b/cursor/os-compatibility.c index 2b54bae2..0c412428 100644 --- a/cursor/os-compatibility.c +++ b/cursor/os-compatibility.c @@ -1,50 +1,35 @@ /* * Copyright © 2012 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: + * 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 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. + * 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. */ #define _GNU_SOURCE -#include "config.h" - #include #include #include #include -#include #include -#include #include -#ifdef HAVE_MEMFD_CREATE -#include -#endif - -/* Fallback to no flag when missing the definition */ -#ifndef MFD_NOEXEC_SEAL -#define MFD_NOEXEC_SEAL 0 -#endif - +#include "config.h" #include "os-compatibility.h" #ifndef HAVE_MKOSTEMP @@ -108,115 +93,53 @@ create_tmpfile_cloexec(char *tmpname) * * If the C library implements posix_fallocate(), it is used to * guarantee that disk space is available for the file at the - * given size. If disk space is insufficient, errno is set to ENOSPC. + * given size. If disk space is insufficent, errno is set to ENOSPC. * If posix_fallocate() is not supported, program may receive * SIGBUS on accessing mmap()'ed file contents instead. - * - * If the C library implements memfd_create(), it is used to create the - * file purely in memory, without any backing file name on the file - * system, and then sealing off the possibility of shrinking it. This - * can then be checked before accessing mmap()'ed file contents, to - * make sure SIGBUS can't happen. It also avoids requiring - * XDG_RUNTIME_DIR. */ int os_create_anonymous_file(off_t size) { - static const char template[] = "/wayland-cursor-shared-XXXXXX"; + static const char template[] = "/weston-shared-XXXXXX"; const char *path; char *name; - size_t name_size; int fd; + int ret; -#ifdef HAVE_MEMFD_CREATE - /* - * Linux kernels older than 6.3 reject MFD_NOEXEC_SEAL with EINVAL. - * Try first *with* it, and if that fails, try again *without* it. - */ - errno = 0; - fd = memfd_create( - "wayland-cursor", - MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL); - - if (fd < 0 && errno == EINVAL && MFD_NOEXEC_SEAL != 0) { - fd = memfd_create( - "wayland-cursor", - MFD_CLOEXEC | MFD_ALLOW_SEALING); + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; } - if (fd >= 0) { - /* We can add this seal before calling posix_fallocate(), as - * the file is currently zero-sized anyway. - * - * There is also no need to check for the return value, we - * couldn't do anything with it anyway. - */ - fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL); - } else -#endif - { - path = getenv("XDG_RUNTIME_DIR"); - if (!path || path[0] != '/') { - errno = ENOENT; - return -1; - } + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; - name_size = strlen(path) + sizeof(template); - name = malloc(name_size); - if (!name) - return -1; + strcpy(name, path); + strcat(name, template); - snprintf(name, name_size, "%s%s", path, template); + fd = create_tmpfile_cloexec(name); - fd = create_tmpfile_cloexec(name); + free(name); - free(name); + if (fd < 0) + return -1; - if (fd < 0) - return -1; +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; } - - if (os_resize_anonymous_file(fd, size) < 0) { +#else + ret = ftruncate(fd, size); + if (ret < 0) { close(fd); return -1; } +#endif return fd; } - -int -os_resize_anonymous_file(int fd, off_t size) -{ -#ifdef HAVE_POSIX_FALLOCATE - sigset_t mask; - sigset_t old_mask; - - /* - * posix_fallocate() might be interrupted, so we need to check - * for EINTR and retry in that case. - * However, in the presence of an alarm, the interrupt may trigger - * repeatedly and prevent a large posix_fallocate() to ever complete - * successfully, so we need to first block SIGALRM to prevent - * this. - */ - sigemptyset(&mask); - sigaddset(&mask, SIGALRM); - sigprocmask(SIG_BLOCK, &mask, &old_mask); - /* - * Filesystems that do not support fallocate will return EINVAL or - * EOPNOTSUPP. In this case we need to fall back to ftruncate - */ - do { - errno = posix_fallocate(fd, 0, size); - } while (errno == EINTR); - sigprocmask(SIG_SETMASK, &old_mask, NULL); - if (errno == 0) - return 0; - else if (errno != EINVAL && errno != EOPNOTSUPP) - return -1; -#endif - if (ftruncate(fd, size) < 0) - return -1; - - return 0; -} diff --git a/cursor/os-compatibility.h b/cursor/os-compatibility.h index fdfeb78b..947555c5 100644 --- a/cursor/os-compatibility.h +++ b/cursor/os-compatibility.h @@ -1,26 +1,23 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 OS_COMPATIBILITY_H @@ -31,7 +28,4 @@ int os_create_anonymous_file(off_t size); -int -os_resize_anonymous_file(int fd, off_t size); - #endif /* OS_COMPATIBILITY_H */ diff --git a/cursor/wayland-cursor-uninstalled.pc.in b/cursor/wayland-cursor-uninstalled.pc.in new file mode 100644 index 00000000..f52b1131 --- /dev/null +++ b/cursor/wayland-cursor-uninstalled.pc.in @@ -0,0 +1,8 @@ +libdir=@abs_builddir@/.libs +includedir=@abs_srcdir@ + +Name: Wayland Cursor +Description: Wayland cursor helper library (not installed) +Version: @WAYLAND_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lwayland-cursor diff --git a/cursor/wayland-cursor.c b/cursor/wayland-cursor.c index 2e21db73..dba3b510 100644 --- a/cursor/wayland-cursor.c +++ b/cursor/wayland-cursor.c @@ -1,36 +1,31 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 "xcursor.h" #include "wayland-cursor.h" #include "wayland-client.h" -#include #include #include -#include #include #include #include @@ -69,16 +64,11 @@ shm_pool_create(struct wl_shm *shm, int size) goto err_close; pool->pool = wl_shm_create_pool(shm, pool->fd, size); - if (!pool->pool) - goto err_unmap; - pool->size = size; pool->used = 0; return pool; -err_unmap: - munmap(pool->data, size); err_close: close(pool->fd); err_free: @@ -89,16 +79,22 @@ err_free: static int shm_pool_resize(struct shm_pool *pool, int size) { - if (os_resize_anonymous_file(pool->fd, size) < 0) + if (ftruncate(pool->fd, size) < 0) return 0; +#ifdef HAVE_POSIX_FALLOCATE + errno = posix_fallocate(pool->fd, 0, size); + if (errno != 0) + return 0; +#endif + wl_shm_pool_resize(pool->pool, size); munmap(pool->data, pool->size); pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, pool->fd, 0); - if (pool->data == MAP_FAILED) + if (pool->data == (void *)-1) return 0; pool->size = size; @@ -135,6 +131,7 @@ struct wl_cursor_theme { struct wl_cursor **cursors; struct wl_shm *shm; struct shm_pool *pool; + char *name; int size; }; @@ -157,32 +154,32 @@ struct cursor { * the returned buffer. */ WL_EXPORT struct wl_buffer * -wl_cursor_image_get_buffer(struct wl_cursor_image *image) +wl_cursor_image_get_buffer(struct wl_cursor_image *_img) { - struct cursor_image *img = (struct cursor_image *) image; - struct wl_cursor_theme *theme = img->theme; + struct cursor_image *image = (struct cursor_image *) _img; + struct wl_cursor_theme *theme = image->theme; - if (!img->buffer) { - img->buffer = + if (!image->buffer) { + image->buffer = wl_shm_pool_create_buffer(theme->pool->pool, - img->offset, - image->width, image->height, - image->width * 4, + image->offset, + _img->width, _img->height, + _img->width * 4, WL_SHM_FORMAT_ARGB8888); }; - return img->buffer; + return image->buffer; } static void -wl_cursor_image_destroy(struct wl_cursor_image *image) +wl_cursor_image_destroy(struct wl_cursor_image *_img) { - struct cursor_image *img = (struct cursor_image *) image; + struct cursor_image *image = (struct cursor_image *) _img; - if (img->buffer) - wl_buffer_destroy(img->buffer); + if (image->buffer) + wl_buffer_destroy(image->buffer); - free(img); + free(image); } static void @@ -193,7 +190,6 @@ wl_cursor_destroy(struct wl_cursor *cursor) for (i = 0; i < cursor->image_count; i++) wl_cursor_image_destroy(cursor->images[i]); - free(cursor->images); free(cursor->name); free(cursor); } @@ -257,10 +253,13 @@ err_free_cursor: } static void -load_fallback_theme(struct wl_cursor_theme *theme) +load_default_theme(struct wl_cursor_theme *theme) { uint32_t i; + free(theme->name); + theme->name = strdup("default"); + theme->cursor_count = ARRAY_LENGTH(cursor_metadata); theme->cursors = malloc(theme->cursor_count * sizeof(*theme->cursors)); @@ -280,13 +279,12 @@ load_fallback_theme(struct wl_cursor_theme *theme) } static struct wl_cursor * -wl_cursor_create_from_xcursor_images(struct xcursor_images *images, +wl_cursor_create_from_xcursor_images(XcursorImages *images, struct wl_cursor_theme *theme) { struct cursor *cursor; struct cursor_image *image; - size_t size; - int i; + int i, size; cursor = malloc(sizeof *cursor); if (!cursor) @@ -316,12 +314,7 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images, image->image.hotspot_y = images->images[i]->yhot; image->image.delay = images->images[i]->delay; - size = (size_t) image->image.width * image->image.height * 4; - if (size > INT_MAX) { - free(image); - break; - } - + size = image->image.width * image->image.height * 4; image->offset = shm_pool_allocate(theme->pool, size); if (image->offset < 0) { free(image); @@ -347,34 +340,33 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images, } static void -load_callback(struct xcursor_images *images, void *data) +load_callback(XcursorImages *images, void *data) { struct wl_cursor_theme *theme = data; struct wl_cursor *cursor; - struct wl_cursor **p; - size_t s; if (wl_cursor_theme_get_cursor(theme, images->name)) { - xcursor_images_destroy(images); + XcursorImagesDestroy(images); return; } cursor = wl_cursor_create_from_xcursor_images(images, theme); if (cursor) { - s = theme->cursor_count + 1; - p = realloc(theme->cursors, s * sizeof theme->cursors[0]); + theme->cursor_count++; + theme->cursors = + realloc(theme->cursors, + theme->cursor_count * sizeof theme->cursors[0]); - if (p == NULL) { + if (theme->cursors == NULL) { + theme->cursor_count--; free(cursor); } else { - theme->cursor_count = s; - theme->cursors = p; theme->cursors[theme->cursor_count - 1] = cursor; } } - xcursor_images_destroy(images); + XcursorImagesDestroy(images); } /** Load a cursor theme to memory shared with the compositor @@ -397,31 +389,30 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm) if (!theme) return NULL; - if (size < 0 || (size > 0 && INT_MAX / size / 4 < size)) - goto err; - if (!name) name = "default"; + theme->name = strdup(name); + if (!theme->name) + goto out_error_name; theme->size = size; theme->cursor_count = 0; theme->cursors = NULL; theme->pool = shm_pool_create(shm, size * size * 4); if (!theme->pool) - goto err; + goto out_error_pool; xcursor_load_theme(name, size, load_callback, theme); if (theme->cursor_count == 0) - xcursor_load_theme(NULL, size, load_callback, theme); - - if (theme->cursor_count == 0) - load_fallback_theme(theme); + load_default_theme(theme); return theme; -err: +out_error_pool: + free(theme->name); +out_error_name: free(theme); return NULL; } @@ -440,6 +431,7 @@ wl_cursor_theme_destroy(struct wl_cursor_theme *theme) shm_pool_destroy(theme->pool); + free(theme->name); free(theme->cursors); free(theme); } @@ -466,67 +458,28 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme, } /** Find the frame for a given elapsed time in a cursor animation - * as well as the time left until next cursor change. * * \param cursor The cursor - * \param time Elapsed time in ms since the beginning of the animation - * \param duration pointer to uint32_t to store time left for this image or - * zero if the cursor won't change. + * \param time Elapsed time since the beginning of the animation * * \return The index of the image that should be displayed for the * given time in the cursor animation. */ WL_EXPORT int -wl_cursor_frame_and_duration(struct wl_cursor *cursor, uint32_t time, - uint32_t *duration) +wl_cursor_frame(struct wl_cursor *_cursor, uint32_t time) { - struct cursor *cur = (struct cursor *) cursor; + struct cursor *cursor = (struct cursor *) _cursor; uint32_t t; int i; - if (cur->cursor.image_count == 1 || cur->total_delay == 0) { - if (duration) - *duration = 0; + if (cursor->cursor.image_count == 1) return 0; - } i = 0; - t = time % cur->total_delay; + t = time % cursor->total_delay; - /* If there is a 0 delay in the image set then this - * loop breaks on it and we display that cursor until - * time % cursor->total_delay wraps again. - * Since a 0 delay is silly, and we've never actually - * seen one in a cursor file, we haven't bothered to - * "fix" this. - */ - while (t - cur->cursor.images[i]->delay < t) - t -= cur->cursor.images[i++]->delay; - - if (!duration) - return i; - - /* Make sure we don't accidentally tell the caller this is - * a static cursor image. - */ - if (t >= cur->cursor.images[i]->delay) - *duration = 1; - else - *duration = cur->cursor.images[i]->delay - t; + while (t - cursor->cursor.images[i]->delay < t) + t -= cursor->cursor.images[i++]->delay; return i; } - -/** Find the frame for a given elapsed time in a cursor animation - * - * \param cursor The cursor - * \param time Elapsed time in ms since the beginning of the animation - * - * \return The index of the image that should be displayed for the - * given time in the cursor animation. - */ -WL_EXPORT int -wl_cursor_frame(struct wl_cursor *cursor, uint32_t time) -{ - return wl_cursor_frame_and_duration(cursor, time, NULL); -} diff --git a/cursor/wayland-cursor.h b/cursor/wayland-cursor.h index 915a1100..c7548ae7 100644 --- a/cursor/wayland-cursor.h +++ b/cursor/wayland-cursor.h @@ -1,26 +1,23 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 WAYLAND_CURSOR_H @@ -33,42 +30,23 @@ extern "C" { #endif struct wl_cursor_theme; -struct wl_buffer; -struct wl_shm; -/** A still image part of a cursor - * - * Use `wl_cursor_image_get_buffer()` to get the corresponding `struct - * wl_buffer` to attach to your `struct wl_surface`. */ struct wl_cursor_image { - /** Actual width */ - uint32_t width; - - /** Actual height */ - uint32_t height; - - /** Hot spot x (must be inside image) */ - uint32_t hotspot_x; - - /** Hot spot y (must be inside image) */ - uint32_t hotspot_y; - - /** Animation delay to next frame (ms) */ - uint32_t delay; + uint32_t width; /* actual width */ + uint32_t height; /* actual height */ + uint32_t hotspot_x; /* hot spot x (must be inside image) */ + uint32_t hotspot_y; /* hot spot y (must be inside image) */ + uint32_t delay; /* animation delay to next frame (ms) */ }; -/** A cursor, as returned by `wl_cursor_theme_get_cursor()` */ struct wl_cursor { - /** How many images there are in this cursor’s animation */ unsigned int image_count; - - /** The array of still images composing this animation */ struct wl_cursor_image **images; - - /** The name of this cursor */ char *name; }; +struct wl_shm; + struct wl_cursor_theme * wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm); @@ -85,10 +63,6 @@ wl_cursor_image_get_buffer(struct wl_cursor_image *image); int wl_cursor_frame(struct wl_cursor *cursor, uint32_t time); -int -wl_cursor_frame_and_duration(struct wl_cursor *cursor, uint32_t time, - uint32_t *duration); - #ifdef __cplusplus } #endif diff --git a/cursor/wayland-cursor.pc.in b/cursor/wayland-cursor.pc.in new file mode 100644 index 00000000..fbbf5fff --- /dev/null +++ b/cursor/wayland-cursor.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Wayland Cursor +Description: Wayland cursor helper library +Version: @WAYLAND_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lwayland-cursor diff --git a/cursor/xcursor.c b/cursor/xcursor.c index 28aab045..f9d9669b 100644 --- a/cursor/xcursor.c +++ b/cursor/xcursor.c @@ -1,36 +1,38 @@ /* * Copyright © 2002 Keith Packard * - * 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: + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes 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 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. + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. */ -#define _GNU_SOURCE #include "xcursor.h" -#include #include #include #include #include +/* + * From libXcursor/include/X11/extensions/Xcursor.h + */ + +#define XcursorTrue 1 +#define XcursorFalse 0 + /* * Cursor files start with a header. The header * contains a magic number, a version number and a @@ -62,31 +64,43 @@ * CARD32 position absolute file position */ -#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */ +#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */ + +/* + * Current Xcursor version number. Will be substituted by configure + * from the version in the libXcursor configure.ac file. + */ + +#define XCURSOR_LIB_MAJOR 1 +#define XCURSOR_LIB_MINOR 1 +#define XCURSOR_LIB_REVISION 13 +#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \ + (XCURSOR_LIB_MINOR * 100) + \ + (XCURSOR_LIB_REVISION)) /* * This version number is stored in cursor files; changes to the * file format require updating this version number */ -#define XCURSOR_FILE_MAJOR 1 -#define XCURSOR_FILE_MINOR 0 -#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR)) -#define XCURSOR_FILE_HEADER_LEN (4 * 4) -#define XCURSOR_FILE_TOC_LEN (3 * 4) +#define XCURSOR_FILE_MAJOR 1 +#define XCURSOR_FILE_MINOR 0 +#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR)) +#define XCURSOR_FILE_HEADER_LEN (4 * 4) +#define XCURSOR_FILE_TOC_LEN (3 * 4) -struct xcursor_file_toc { - uint32_t type; /* chunk type */ - uint32_t subtype; /* subtype (size for images) */ - uint32_t position; /* absolute position in file */ -}; +typedef struct _XcursorFileToc { + XcursorUInt type; /* chunk type */ + XcursorUInt subtype; /* subtype (size for images) */ + XcursorUInt position; /* absolute position in file */ +} XcursorFileToc; -struct xcursor_file_header { - uint32_t magic; /* magic number */ - uint32_t header; /* byte length of header */ - uint32_t version; /* file version number */ - uint32_t ntoc; /* number of toc entries */ - struct xcursor_file_toc *tocs; /* table of contents */ -}; +typedef struct _XcursorFileHeader { + XcursorUInt magic; /* magic number */ + XcursorUInt header; /* byte length of header */ + XcursorUInt version; /* file version number */ + XcursorUInt ntoc; /* number of toc entries */ + XcursorFileToc *tocs; /* table of contents */ +} XcursorFileHeader; /* * The rest of the file is a list of chunks, each tagged by type @@ -104,14 +118,42 @@ struct xcursor_file_header { * CARD32 version chunk type version */ -#define XCURSOR_CHUNK_HEADER_LEN (4 * 4) +#define XCURSOR_CHUNK_HEADER_LEN (4 * 4) -struct xcursor_chunk_header { - uint32_t header; /* bytes in chunk header */ - uint32_t type; /* chunk type */ - uint32_t subtype; /* chunk subtype (size for images) */ - uint32_t version; /* version of this type */ -}; +typedef struct _XcursorChunkHeader { + XcursorUInt header; /* bytes in chunk header */ + XcursorUInt type; /* chunk type */ + XcursorUInt subtype; /* chunk subtype (size for images) */ + XcursorUInt version; /* version of this type */ +} XcursorChunkHeader; + +/* + * Here's a list of the known chunk types + */ + +/* + * Comments consist of a 4-byte length field followed by + * UTF-8 encoded text + * + * Comment: + * ChunkHeader header chunk header + * CARD32 length bytes in text + * LISTofCARD8 text UTF-8 encoded text + */ + +#define XCURSOR_COMMENT_TYPE 0xfffe0001 +#define XCURSOR_COMMENT_VERSION 1 +#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4)) +#define XCURSOR_COMMENT_COPYRIGHT 1 +#define XCURSOR_COMMENT_LICENSE 2 +#define XCURSOR_COMMENT_OTHER 3 +#define XCURSOR_COMMENT_MAX_LEN 0x100000 + +typedef struct _XcursorComment { + XcursorUInt version; + XcursorUInt comment_type; + char *comment; +} XcursorComment; /* * Each cursor image occupies a separate image chunk. @@ -129,356 +171,432 @@ struct xcursor_chunk_header { * LISTofCARD32 pixels ARGB pixels */ -#define XCURSOR_IMAGE_TYPE 0xfffd0002 -#define XCURSOR_IMAGE_VERSION 1 -#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4)) -#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ +#define XCURSOR_IMAGE_TYPE 0xfffd0002 +#define XCURSOR_IMAGE_VERSION 1 +#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4)) +#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ + +typedef struct _XcursorFile XcursorFile; + +struct _XcursorFile { + void *closure; + int (*read) (XcursorFile *file, unsigned char *buf, int len); + int (*write) (XcursorFile *file, unsigned char *buf, int len); + int (*seek) (XcursorFile *file, long offset, int whence); +}; + +typedef struct _XcursorComments { + int ncomment; /* number of comments */ + XcursorComment **comments; /* array of XcursorComment pointers */ +} XcursorComments; /* * From libXcursor/src/file.c */ -static struct xcursor_image * -xcursor_image_create(int width, int height) +static XcursorImage * +XcursorImageCreate (int width, int height) { - struct xcursor_image *image; + XcursorImage *image; - if (width < 0 || height < 0) - return NULL; - if (width > XCURSOR_IMAGE_MAX_SIZE || height > XCURSOR_IMAGE_MAX_SIZE) - return NULL; - - image = malloc(sizeof(struct xcursor_image) + - width * height * sizeof(uint32_t)); - if (!image) - return NULL; - image->version = XCURSOR_IMAGE_VERSION; - image->pixels = (uint32_t *) (image + 1); - image->size = width > height ? width : height; - image->width = width; - image->height = height; - image->delay = 0; - return image; + image = malloc (sizeof (XcursorImage) + + width * height * sizeof (XcursorPixel)); + if (!image) + return NULL; + image->version = XCURSOR_IMAGE_VERSION; + image->pixels = (XcursorPixel *) (image + 1); + image->size = width > height ? width : height; + image->width = width; + image->height = height; + image->delay = 0; + return image; } static void -xcursor_image_destroy(struct xcursor_image *image) +XcursorImageDestroy (XcursorImage *image) { - free(image); + free (image); } -static struct xcursor_images * -xcursor_images_create(int size) +static XcursorImages * +XcursorImagesCreate (int size) { - struct xcursor_images *images; + XcursorImages *images; - images = malloc(sizeof(struct xcursor_images) + - size * sizeof(struct xcursor_image *)); - if (!images) - return NULL; - images->nimage = 0; - images->images = (struct xcursor_image **) (images + 1); - images->name = NULL; - return images; + images = malloc (sizeof (XcursorImages) + + size * sizeof (XcursorImage *)); + if (!images) + return NULL; + images->nimage = 0; + images->images = (XcursorImage **) (images + 1); + images->name = NULL; + return images; } void -xcursor_images_destroy(struct xcursor_images *images) +XcursorImagesDestroy (XcursorImages *images) { - int n; + int n; - if (!images) - return; + if (!images) + return; - for (n = 0; n < images->nimage; n++) - xcursor_image_destroy(images->images[n]); - free(images->name); - free(images); -} - -static bool -xcursor_read_uint(FILE *file, uint32_t *u) -{ - unsigned char bytes[4]; - - if (!file || !u) - return false; - - if (fread(bytes, 1, 4, file) != 4) - return false; - - *u = ((uint32_t)(bytes[0]) << 0) | - ((uint32_t)(bytes[1]) << 8) | - ((uint32_t)(bytes[2]) << 16) | - ((uint32_t)(bytes[3]) << 24); - return true; + for (n = 0; n < images->nimage; n++) + XcursorImageDestroy (images->images[n]); + if (images->name) + free (images->name); + free (images); } static void -xcursor_file_header_destroy(struct xcursor_file_header *file_header) +XcursorImagesSetName (XcursorImages *images, const char *name) { - free(file_header); + char *new; + + if (!images || !name) + return; + + new = malloc (strlen (name) + 1); + + if (!new) + return; + + strcpy (new, name); + if (images->name) + free (images->name); + images->name = new; } -static struct xcursor_file_header * -xcursor_file_header_create(uint32_t ntoc) +static XcursorBool +_XcursorReadUInt (XcursorFile *file, XcursorUInt *u) { - struct xcursor_file_header *file_header; + unsigned char bytes[4]; - if (ntoc > 0x10000) - return NULL; - file_header = malloc(sizeof(struct xcursor_file_header) + - ntoc * sizeof(struct xcursor_file_toc)); - if (!file_header) - return NULL; - file_header->magic = XCURSOR_MAGIC; - file_header->header = XCURSOR_FILE_HEADER_LEN; - file_header->version = XCURSOR_FILE_VERSION; - file_header->ntoc = ntoc; - file_header->tocs = (struct xcursor_file_toc *) (file_header + 1); - return file_header; + if (!file || !u) + return XcursorFalse; + + if ((*file->read) (file, bytes, 4) != 4) + return XcursorFalse; + *u = ((bytes[0] << 0) | + (bytes[1] << 8) | + (bytes[2] << 16) | + (bytes[3] << 24)); + return XcursorTrue; } -static struct xcursor_file_header * -xcursor_read_file_header(FILE *file) +static void +_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader) { - struct xcursor_file_header head, *file_header; - uint32_t skip; - unsigned int n; + free (fileHeader); +} - if (!file) - return NULL; +static XcursorFileHeader * +_XcursorFileHeaderCreate (int ntoc) +{ + XcursorFileHeader *fileHeader; - if (!xcursor_read_uint(file, &head.magic)) - return NULL; - if (head.magic != XCURSOR_MAGIC) - return NULL; - if (!xcursor_read_uint(file, &head.header)) - return NULL; - if (!xcursor_read_uint(file, &head.version)) - return NULL; - if (!xcursor_read_uint(file, &head.ntoc)) - return NULL; - if (head.header < XCURSOR_FILE_HEADER_LEN) - return NULL; - skip = head.header - XCURSOR_FILE_HEADER_LEN; - if (skip) - if (fseek(file, skip, SEEK_CUR) == EOF) - return NULL; - file_header = xcursor_file_header_create(head.ntoc); - if (!file_header) - return NULL; - file_header->magic = head.magic; - file_header->header = head.header; - file_header->version = head.version; - file_header->ntoc = head.ntoc; - for (n = 0; n < file_header->ntoc; n++) { - if (!xcursor_read_uint(file, &file_header->tocs[n].type)) - break; - if (!xcursor_read_uint(file, &file_header->tocs[n].subtype)) - break; - if (!xcursor_read_uint(file, &file_header->tocs[n].position)) - break; + if (ntoc > 0x10000) + return NULL; + fileHeader = malloc (sizeof (XcursorFileHeader) + + ntoc * sizeof (XcursorFileToc)); + if (!fileHeader) + return NULL; + fileHeader->magic = XCURSOR_MAGIC; + fileHeader->header = XCURSOR_FILE_HEADER_LEN; + fileHeader->version = XCURSOR_FILE_VERSION; + fileHeader->ntoc = ntoc; + fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1); + return fileHeader; +} + +static XcursorFileHeader * +_XcursorReadFileHeader (XcursorFile *file) +{ + XcursorFileHeader head, *fileHeader; + XcursorUInt skip; + unsigned int n; + + if (!file) + return NULL; + + if (!_XcursorReadUInt (file, &head.magic)) + return NULL; + if (head.magic != XCURSOR_MAGIC) + return NULL; + if (!_XcursorReadUInt (file, &head.header)) + return NULL; + if (!_XcursorReadUInt (file, &head.version)) + return NULL; + if (!_XcursorReadUInt (file, &head.ntoc)) + return NULL; + skip = head.header - XCURSOR_FILE_HEADER_LEN; + if (skip) + if ((*file->seek) (file, skip, SEEK_CUR) == EOF) + return NULL; + fileHeader = _XcursorFileHeaderCreate (head.ntoc); + if (!fileHeader) + return NULL; + fileHeader->magic = head.magic; + fileHeader->header = head.header; + fileHeader->version = head.version; + fileHeader->ntoc = head.ntoc; + for (n = 0; n < fileHeader->ntoc; n++) + { + if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type)) + break; + if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype)) + break; + if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position)) + break; + } + if (n != fileHeader->ntoc) + { + _XcursorFileHeaderDestroy (fileHeader); + return NULL; + } + return fileHeader; +} + +static XcursorBool +_XcursorSeekToToc (XcursorFile *file, + XcursorFileHeader *fileHeader, + int toc) +{ + if (!file || !fileHeader || \ + (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF) + return XcursorFalse; + return XcursorTrue; +} + +static XcursorBool +_XcursorFileReadChunkHeader (XcursorFile *file, + XcursorFileHeader *fileHeader, + int toc, + XcursorChunkHeader *chunkHeader) +{ + if (!file || !fileHeader || !chunkHeader) + return XcursorFalse; + if (!_XcursorSeekToToc (file, fileHeader, toc)) + return XcursorFalse; + if (!_XcursorReadUInt (file, &chunkHeader->header)) + return XcursorFalse; + if (!_XcursorReadUInt (file, &chunkHeader->type)) + return XcursorFalse; + if (!_XcursorReadUInt (file, &chunkHeader->subtype)) + return XcursorFalse; + if (!_XcursorReadUInt (file, &chunkHeader->version)) + return XcursorFalse; + /* sanity check */ + if (chunkHeader->type != fileHeader->tocs[toc].type || + chunkHeader->subtype != fileHeader->tocs[toc].subtype) + return XcursorFalse; + return XcursorTrue; +} + +#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a)) + +static XcursorDim +_XcursorFindBestSize (XcursorFileHeader *fileHeader, + XcursorDim size, + int *nsizesp) +{ + unsigned int n; + int nsizes = 0; + XcursorDim bestSize = 0; + XcursorDim thisSize; + + if (!fileHeader || !nsizesp) + return 0; + + for (n = 0; n < fileHeader->ntoc; n++) + { + if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE) + continue; + thisSize = fileHeader->tocs[n].subtype; + if (!bestSize || dist (thisSize, size) < dist (bestSize, size)) + { + bestSize = thisSize; + nsizes = 1; } - if (n != file_header->ntoc) { - xcursor_file_header_destroy(file_header); - return NULL; - } - return file_header; -} - -static bool -xcursor_seek_to_toc(FILE *file, - struct xcursor_file_header *file_header, - int toc) -{ - if (!file || !file_header || - fseek(file, file_header->tocs[toc].position, SEEK_SET) == EOF) - return false; - return true; -} - -static bool -xcursor_file_read_chunk_header(FILE *file, - struct xcursor_file_header *file_header, - int toc, - struct xcursor_chunk_header *chunk_header) -{ - if (!file || !file_header || !chunk_header) - return false; - if (!xcursor_seek_to_toc(file, file_header, toc)) - return false; - if (!xcursor_read_uint(file, &chunk_header->header)) - return false; - if (!xcursor_read_uint(file, &chunk_header->type)) - return false; - if (!xcursor_read_uint(file, &chunk_header->subtype)) - return false; - if (!xcursor_read_uint(file, &chunk_header->version)) - return false; - /* sanity check */ - if (chunk_header->type != file_header->tocs[toc].type || - chunk_header->subtype != file_header->tocs[toc].subtype) - return false; - return true; -} - -static uint32_t -dist(uint32_t a, uint32_t b) -{ - return a > b ? a - b : b - a; -} - -static uint32_t -xcursor_file_best_size(struct xcursor_file_header *file_header, - uint32_t size, int *nsizesp) -{ - unsigned int n; - int nsizes = 0; - uint32_t best_size = 0; - uint32_t this_size; - - if (!file_header || !nsizesp) - return 0; - - for (n = 0; n < file_header->ntoc; n++) { - if (file_header->tocs[n].type != XCURSOR_IMAGE_TYPE) - continue; - this_size = file_header->tocs[n].subtype; - if (!best_size || dist(this_size, size) < dist(best_size, size)) { - best_size = this_size; - nsizes = 1; - } else if (this_size == best_size) { - nsizes++; - } - } - *nsizesp = nsizes; - return best_size; + else if (thisSize == bestSize) + nsizes++; + } + *nsizesp = nsizes; + return bestSize; } static int -xcursor_find_image_toc(struct xcursor_file_header *file_header, - uint32_t size, int count) +_XcursorFindImageToc (XcursorFileHeader *fileHeader, + XcursorDim size, + int count) { - unsigned int toc; - uint32_t this_size; + unsigned int toc; + XcursorDim thisSize; - if (!file_header) - return 0; + if (!fileHeader) + return 0; - for (toc = 0; toc < file_header->ntoc; toc++) { - if (file_header->tocs[toc].type != XCURSOR_IMAGE_TYPE) - continue; - this_size = file_header->tocs[toc].subtype; - if (this_size != size) - continue; - if (!count) - break; - count--; - } - if (toc == file_header->ntoc) - return -1; - return toc; + for (toc = 0; toc < fileHeader->ntoc; toc++) + { + if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE) + continue; + thisSize = fileHeader->tocs[toc].subtype; + if (thisSize != size) + continue; + if (!count) + break; + count--; + } + if (toc == fileHeader->ntoc) + return -1; + return toc; } -static struct xcursor_image * -xcursor_read_image(FILE *file, - struct xcursor_file_header *file_header, - int toc) +static XcursorImage * +_XcursorReadImage (XcursorFile *file, + XcursorFileHeader *fileHeader, + int toc) { - struct xcursor_chunk_header chunk_header; - struct xcursor_image head; - struct xcursor_image *image; - int n; - uint32_t *p; + XcursorChunkHeader chunkHeader; + XcursorImage head; + XcursorImage *image; + int n; + XcursorPixel *p; - if (!file || !file_header) - return NULL; + if (!file || !fileHeader) + return NULL; - if (!xcursor_file_read_chunk_header(file, file_header, toc, &chunk_header)) - return NULL; - if (!xcursor_read_uint(file, &head.width)) - return NULL; - if (!xcursor_read_uint(file, &head.height)) - return NULL; - if (!xcursor_read_uint(file, &head.xhot)) - return NULL; - if (!xcursor_read_uint(file, &head.yhot)) - return NULL; - if (!xcursor_read_uint(file, &head.delay)) - return NULL; - /* sanity check data */ - if (head.width > XCURSOR_IMAGE_MAX_SIZE || - head.height > XCURSOR_IMAGE_MAX_SIZE) - return NULL; - if (head.width == 0 || head.height == 0) - return NULL; - if (head.xhot > head.width || head.yhot > head.height) - return NULL; + if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader)) + return NULL; + if (!_XcursorReadUInt (file, &head.width)) + return NULL; + if (!_XcursorReadUInt (file, &head.height)) + return NULL; + if (!_XcursorReadUInt (file, &head.xhot)) + return NULL; + if (!_XcursorReadUInt (file, &head.yhot)) + return NULL; + if (!_XcursorReadUInt (file, &head.delay)) + return NULL; + /* sanity check data */ + if (head.width >= 0x10000 || head.height > 0x10000) + return NULL; + if (head.width == 0 || head.height == 0) + return NULL; + if (head.xhot > head.width || head.yhot > head.height) + return NULL; - /* Create the image and initialize it */ - image = xcursor_image_create(head.width, head.height); - if (image == NULL) - return NULL; - if (chunk_header.version < image->version) - image->version = chunk_header.version; - image->size = chunk_header.subtype; - image->xhot = head.xhot; - image->yhot = head.yhot; - image->delay = head.delay; - n = image->width * image->height; - p = image->pixels; - while (n--) { - if (!xcursor_read_uint(file, p)) { - xcursor_image_destroy(image); - return NULL; - } - p++; + /* Create the image and initialize it */ + image = XcursorImageCreate (head.width, head.height); + if (image == NULL) + return NULL; + if (chunkHeader.version < image->version) + image->version = chunkHeader.version; + image->size = chunkHeader.subtype; + image->xhot = head.xhot; + image->yhot = head.yhot; + image->delay = head.delay; + n = image->width * image->height; + p = image->pixels; + while (n--) + { + if (!_XcursorReadUInt (file, p)) + { + XcursorImageDestroy (image); + return NULL; } - return image; + p++; + } + return image; } -static struct xcursor_images * -xcursor_xc_file_load_images(FILE *file, int size) +static XcursorImages * +XcursorXcFileLoadImages (XcursorFile *file, int size) { - struct xcursor_file_header *file_header; - uint32_t best_size; - int nsize; - struct xcursor_images *images; - int n; - int toc; + XcursorFileHeader *fileHeader; + XcursorDim bestSize; + int nsize; + XcursorImages *images; + int n; + int toc; - if (!file || size < 0) - return NULL; - file_header = xcursor_read_file_header(file); - if (!file_header) - return NULL; - best_size = xcursor_file_best_size(file_header, (uint32_t) size, &nsize); - if (!best_size) { - xcursor_file_header_destroy(file_header); - return NULL; - } - images = xcursor_images_create(nsize); - if (!images) { - xcursor_file_header_destroy(file_header); - return NULL; - } - for (n = 0; n < nsize; n++) { - toc = xcursor_find_image_toc(file_header, best_size, n); - if (toc < 0) - break; - images->images[images->nimage] = xcursor_read_image(file, file_header, - toc); - if (!images->images[images->nimage]) - break; - images->nimage++; - } - xcursor_file_header_destroy(file_header); - if (images->nimage != nsize) { - xcursor_images_destroy(images); - images = NULL; - } - return images; + if (!file || size < 0) + return NULL; + fileHeader = _XcursorReadFileHeader (file); + if (!fileHeader) + return NULL; + bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize); + if (!bestSize) + { + _XcursorFileHeaderDestroy (fileHeader); + return NULL; + } + images = XcursorImagesCreate (nsize); + if (!images) + { + _XcursorFileHeaderDestroy (fileHeader); + return NULL; + } + for (n = 0; n < nsize; n++) + { + toc = _XcursorFindImageToc (fileHeader, bestSize, n); + if (toc < 0) + break; + images->images[images->nimage] = _XcursorReadImage (file, fileHeader, + toc); + if (!images->images[images->nimage]) + break; + images->nimage++; + } + _XcursorFileHeaderDestroy (fileHeader); + if (images->nimage != nsize) + { + XcursorImagesDestroy (images); + images = NULL; + } + return images; +} + +static int +_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len) +{ + FILE *f = file->closure; + return fread (buf, 1, len, f); +} + +static int +_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len) +{ + FILE *f = file->closure; + return fwrite (buf, 1, len, f); +} + +static int +_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence) +{ + FILE *f = file->closure; + return fseek (f, offset, whence); +} + +static void +_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file) +{ + file->closure = stdfile; + file->read = _XcursorStdioFileRead; + file->write = _XcursorStdioFileWrite; + file->seek = _XcursorStdioFileSeek; +} + +static XcursorImages * +XcursorFileLoadImages (FILE *file, int size) +{ + XcursorFile f; + + if (!file) + return NULL; + + _XcursorStdioFileInitialize (file, &f); + return XcursorXcFileLoadImages (&f, size); } /* @@ -493,222 +611,275 @@ xcursor_xc_file_load_images(FILE *file, int size) #define XCURSORPATH "~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:"ICONDIR #endif -#define XDG_DATA_HOME_FALLBACK "~/.local/share" -#define CURSORDIR "/icons" - -/** Get search path for cursor themes - * - * This function builds the list of directories to look for cursor - * themes in. The format is PATH-like: directories are separated by - * colons. - * - * The memory block returned by this function is allocated on the heap - * and must be freed by the caller. - */ -static char * -xcursor_library_path(void) +static const char * +XcursorLibraryPath (void) { - const char *env_var, *suffix; - char *path; - size_t path_size; + static const char *path; - env_var = getenv("XCURSOR_PATH"); - if (env_var) - return strdup(env_var); - - env_var = getenv("XDG_DATA_HOME"); - if (!env_var || env_var[0] != '/') - env_var = XDG_DATA_HOME_FALLBACK; - - suffix = CURSORDIR ":" XCURSORPATH; - path_size = strlen(env_var) + strlen(suffix) + 1; - path = malloc(path_size); + if (!path) + { + path = getenv ("XCURSOR_PATH"); if (!path) - return NULL; - snprintf(path, path_size, "%s%s", env_var, suffix); - return path; + path = XCURSORPATH; + } + return path; +} + +static void +_XcursorAddPathElt (char *path, const char *elt, int len) +{ + int pathlen = strlen (path); + + /* append / if the path doesn't currently have one */ + if (path[0] == '\0' || path[pathlen - 1] != '/') + { + strcat (path, "/"); + pathlen++; + } + if (len == -1) + len = strlen (elt); + /* strip leading slashes */ + while (len && elt[0] == '/') + { + elt++; + len--; + } + strncpy (path + pathlen, elt, len); + path[pathlen + len] = '\0'; } static char * -xcursor_build_theme_dir(const char *dir, const char *theme) +_XcursorBuildThemeDir (const char *dir, const char *theme) { - const char *colon; - const char *tcolon; - char *full; - const char *home, *homesep; - int dirlen; - int homelen; - int themelen; - size_t full_size; + const char *colon; + const char *tcolon; + char *full; + char *home; + int dirlen; + int homelen; + int themelen; + int len; - if (!dir || !theme) - return NULL; + if (!dir || !theme) + return NULL; - colon = strchr(dir, ':'); - if (!colon) - colon = dir + strlen(dir); + colon = strchr (dir, ':'); + if (!colon) + colon = dir + strlen (dir); - dirlen = colon - dir; + dirlen = colon - dir; - tcolon = strchr(theme, ':'); - if (!tcolon) - tcolon = theme + strlen(theme); + tcolon = strchr (theme, ':'); + if (!tcolon) + tcolon = theme + strlen (theme); - themelen = tcolon - theme; + themelen = tcolon - theme; - home = ""; - homelen = 0; - homesep = ""; - if (*dir == '~') { - home = getenv("HOME"); - if (!home) - return NULL; - homelen = strlen(home); - homesep = "/"; - dir++; - dirlen--; - } + home = NULL; + homelen = 0; + if (*dir == '~') + { + home = getenv ("HOME"); + if (!home) + return NULL; + homelen = strlen (home); + dir++; + dirlen--; + } - /* - * add space for any needed directory separators, one per component, - * and one for the trailing null - */ - full_size = (size_t) 1 + homelen + 1 + dirlen + 1 + themelen + 1; - full = malloc(full_size); - if (!full) - return NULL; - snprintf(full, full_size, "%s%s%.*s/%.*s", home, homesep, - dirlen, dir, themelen, theme); - return full; + /* + * add space for any needed directory separators, one per component, + * and one for the trailing null + */ + len = 1 + homelen + 1 + dirlen + 1 + themelen + 1; + + full = malloc (len); + if (!full) + return NULL; + full[0] = '\0'; + + if (home) + _XcursorAddPathElt (full, home, -1); + _XcursorAddPathElt (full, dir, dirlen); + _XcursorAddPathElt (full, theme, themelen); + return full; } static char * -xcursor_build_fullname(const char *dir, const char *subdir, const char *file) +_XcursorBuildFullname (const char *dir, const char *subdir, const char *file) { - char *full; - size_t full_size; - int ret; + char *full; - if (!dir || !subdir || !file) - return NULL; + if (!dir || !subdir || !file) + return NULL; - full_size = strlen(dir) + 1 + strlen(subdir) + 1 + strlen(file) + 1; - full = malloc(full_size); - if (!full) - return NULL; - ret = snprintf(full, full_size, "%s/%s/%s", dir, subdir, file); - if (ret < 0) { - free(full); - return NULL; - } - return full; + full = malloc (strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1); + if (!full) + return NULL; + full[0] = '\0'; + _XcursorAddPathElt (full, dir, -1); + _XcursorAddPathElt (full, subdir, -1); + _XcursorAddPathElt (full, file, -1); + return full; } static const char * -xcursor_next_path(const char *path) +_XcursorNextPath (const char *path) { - const char *colon = strchr(path, ':'); + char *colon = strchr (path, ':'); - if (!colon) - return NULL; - return colon + 1; + if (!colon) + return NULL; + return colon + 1; } -static bool -xcursor_white(char c) -{ - return c == ' ' || c == '\t' || c == '\n'; -} - -static bool -xcursor_sep(char c) -{ - return c == ';' || c == ','; -} +#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define XcursorSep(c) ((c) == ';' || (c) == ',') static char * -xcursor_theme_inherits(const char *full) +_XcursorThemeInherits (const char *full) { - char *line = NULL; - size_t line_size = 0; - char *result = NULL; - FILE *f; + char line[8192]; + char *result = NULL; + FILE *f; - if (!full) - return NULL; + if (!full) + return NULL; - f = fopen(full, "r"); - if (!f) - return NULL; - - while (getline(&line, &line_size, f) >= 0) { - const char *l; - char *r; - - if (strncmp(line, "Inherits", 8)) - continue; - - l = line + 8; - while (*l == ' ') - l++; - if (*l != '=') - continue; + f = fopen (full, "r"); + if (f) + { + while (fgets (line, sizeof (line), f)) + { + if (!strncmp (line, "Inherits", 8)) + { + char *l = line + 8; + char *r; + while (*l == ' ') l++; + if (*l != '=') continue; l++; - while (*l == ' ') - l++; - result = malloc(strlen(l) + 1); - if (!result) - break; - - r = result; - while (*l) { - while (xcursor_sep(*l) || xcursor_white(*l)) - l++; + while (*l == ' ') l++; + result = malloc (strlen (l) + 1); + if (result) + { + r = result; + while (*l) + { + while (XcursorSep(*l) || XcursorWhite (*l)) l++; if (!*l) - break; + break; if (r != result) - *r++ = ':'; - while (*l && !xcursor_white(*l) && !xcursor_sep(*l)) - *r++ = *l++; + *r++ = ':'; + while (*l && !XcursorWhite(*l) && + !XcursorSep(*l)) + *r++ = *l++; + } + *r++ = '\0'; } - *r++ = '\0'; - break; + } } + fclose (f); + } + return result; +} - fclose(f); - free(line); +static FILE * +XcursorScanTheme (const char *theme, const char *name) +{ + FILE *f = NULL; + char *full; + char *dir; + const char *path; + char *inherits = NULL; + const char *i; - return result; + if (!theme || !name) + return NULL; + + /* + * Scan this theme + */ + for (path = XcursorLibraryPath (); + path && f == NULL; + path = _XcursorNextPath (path)) + { + dir = _XcursorBuildThemeDir (path, theme); + if (dir) + { + full = _XcursorBuildFullname (dir, "cursors", name); + if (full) + { + f = fopen (full, "r"); + free (full); + } + if (!f && !inherits) + { + full = _XcursorBuildFullname (dir, "", "index.theme"); + if (full) + { + inherits = _XcursorThemeInherits (full); + free (full); + } + } + free (dir); + } + } + /* + * Recurse to scan inherited themes + */ + for (i = inherits; i && f == NULL; i = _XcursorNextPath (i)) + f = XcursorScanTheme (i, name); + if (inherits != NULL) + free (inherits); + return f; +} + +XcursorImages * +XcursorLibraryLoadImages (const char *file, const char *theme, int size) +{ + FILE *f = NULL; + XcursorImages *images = NULL; + + if (!file) + return NULL; + + if (theme) + f = XcursorScanTheme (theme, file); + if (!f) + f = XcursorScanTheme ("default", file); + if (f) + { + images = XcursorFileLoadImages (f, size); + if (images) + XcursorImagesSetName (images, file); + fclose (f); + } + return images; } static void load_all_cursors_from_dir(const char *path, int size, - void (*load_callback)(struct xcursor_images *, void *), + void (*load_callback)(XcursorImages *, void *), void *user_data) { FILE *f; - DIR *dir; + DIR *dir = opendir(path); struct dirent *ent; char *full; - struct xcursor_images *images; + XcursorImages *images; - if (!path) - return; - - dir = opendir(path); if (!dir) return; - for (ent = readdir(dir); ent; ent = readdir(dir)) { + for(ent = readdir(dir); ent; ent = readdir(dir)) { #ifdef _DIRENT_HAVE_D_TYPE if (ent->d_type != DT_UNKNOWN && - ent->d_type != DT_REG && - ent->d_type != DT_LNK) + (ent->d_type != DT_REG && ent->d_type != DT_LNK)) continue; #endif - full = xcursor_build_fullname(path, "", ent->d_name); + full = _XcursorBuildFullname(path, "", ent->d_name); if (!full) continue; @@ -718,119 +889,80 @@ load_all_cursors_from_dir(const char *path, int size, continue; } - images = xcursor_xc_file_load_images(f, size); + images = XcursorFileLoadImages(f, size); if (images) { - images->name = strdup(ent->d_name); + XcursorImagesSetName(images, ent->d_name); load_callback(images, user_data); } - fclose(f); + fclose (f); free(full); } closedir(dir); } -struct xcursor_nodelist { - size_t nodelen; - const char *node; - struct xcursor_nodelist *next; -}; - -static bool -nodelist_contains(struct xcursor_nodelist *nodelist, const char *s, size_t ss) -{ - struct xcursor_nodelist *vi; - - for (vi = nodelist; vi && vi->node; vi = vi->next) { - if (vi->nodelen == ss && !strncmp(s, vi->node, vi->nodelen)) - return true; - } - return false; -} - -static void -xcursor_load_theme_protected(const char *theme, int size, - void (*load_callback)(struct xcursor_images *, void *), - void *user_data, - struct xcursor_nodelist *visited_nodes) -{ - char *full, *dir; - char *inherits = NULL; - const char *path, *i; - char *xcursor_path; - size_t si; - struct xcursor_nodelist current_node; - - if (!theme) - theme = "default"; - - current_node.next = visited_nodes; - current_node.node = theme; - current_node.nodelen = strlen(theme); - visited_nodes = ¤t_node; - - xcursor_path = xcursor_library_path(); - for (path = xcursor_path; - path; - path = xcursor_next_path(path)) { - dir = xcursor_build_theme_dir(path, theme); - if (!dir) - continue; - - full = xcursor_build_fullname(dir, "cursors", ""); - load_all_cursors_from_dir(full, size, load_callback, - user_data); - free(full); - - if (!inherits) { - full = xcursor_build_fullname(dir, "", "index.theme"); - inherits = xcursor_theme_inherits(full); - free(full); - } - - free(dir); - } - - for (i = inherits; i; i = xcursor_next_path(i)) { - si = strlen(i); - if (nodelist_contains(visited_nodes, i, si)) - continue; - xcursor_load_theme_protected(i, size, load_callback, user_data, visited_nodes); - } - - free(inherits); - free(xcursor_path); -} - -/** Load all the cursors of a theme +/** Load all the cursor of a theme * * This function loads all the cursor images of a given theme and its - * inherited themes. Each cursor is loaded into a struct xcursor_images object + * inherited themes. Each cursor is loaded into an XcursorImages object * which is passed to the caller's load callback. If a cursor appears * more than once across all the inherited themes, the load callback - * will be called multiple times, with possibly different struct xcursor_images - * objects which have the same name. The user is expected to destroy the - * struct xcursor_images objects passed to the callback with - * xcursor_images_destroy(). + * will be called multiple times, with possibly different XcursorImages + * object which have the same name. The user is expected to destroy the + * XcursorImages objects passed to the callback with + * XcursorImagesDestroy(). * * \param theme The name of theme that should be loaded * \param size The desired size of the cursor images * \param load_callback A callback function that will be called - * for each cursor loaded. The first parameter is the struct xcursor_images + * for each cursor loaded. The first parameter is the XcursorImages * object representing the loaded cursor and the second is a pointer * to data provided by the user. * \param user_data The data that should be passed to the load callback */ void xcursor_load_theme(const char *theme, int size, - void (*load_callback)(struct xcursor_images *, void *), - void *user_data) + void (*load_callback)(XcursorImages *, void *), + void *user_data) { - xcursor_load_theme_protected(theme, - size, - load_callback, - user_data, - NULL); + char *full, *dir; + char *inherits = NULL; + const char *path, *i; + + if (!theme) + theme = "default"; + + for (path = XcursorLibraryPath(); + path; + path = _XcursorNextPath(path)) { + dir = _XcursorBuildThemeDir(path, theme); + if (!dir) + continue; + + full = _XcursorBuildFullname(dir, "cursors", ""); + + if (full) { + load_all_cursors_from_dir(full, size, load_callback, + user_data); + free(full); + } + + if (!inherits) { + full = _XcursorBuildFullname(dir, "", "index.theme"); + if (full) { + inherits = _XcursorThemeInherits(full); + free(full); + } + } + + free(dir); + } + + for (i = inherits; i; i = _XcursorNextPath(i)) + xcursor_load_theme(i, size, load_callback, user_data); + + if (inherits) + free(inherits); } diff --git a/cursor/xcursor.h b/cursor/xcursor.h index 459f8166..f518767a 100644 --- a/cursor/xcursor.h +++ b/cursor/xcursor.h @@ -1,58 +1,62 @@ /* * Copyright © 2002 Keith Packard * - * 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: + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes 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 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. + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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 XCURSOR_H #define XCURSOR_H -#include +typedef int XcursorBool; +typedef unsigned int XcursorUInt; -struct xcursor_image { - uint32_t version; /* version of the image data */ - uint32_t size; /* nominal size for matching */ - uint32_t width; /* actual width */ - uint32_t height; /* actual height */ - uint32_t xhot; /* hot spot x (must be inside image) */ - uint32_t yhot; /* hot spot y (must be inside image) */ - uint32_t delay; /* animation delay to next frame (ms) */ - uint32_t *pixels; /* pointer to pixels */ -}; +typedef XcursorUInt XcursorDim; +typedef XcursorUInt XcursorPixel; + +typedef struct _XcursorImage { + XcursorUInt version; /* version of the image data */ + XcursorDim size; /* nominal size for matching */ + XcursorDim width; /* actual width */ + XcursorDim height; /* actual height */ + XcursorDim xhot; /* hot spot x (must be inside image) */ + XcursorDim yhot; /* hot spot y (must be inside image) */ + XcursorUInt delay; /* animation delay to next frame (ms) */ + XcursorPixel *pixels; /* pointer to pixels */ +} XcursorImage; /* * Other data structures exposed by the library API */ -struct xcursor_images { - int nimage; /* number of images */ - struct xcursor_image **images; /* array of XcursorImage pointers */ - char *name; /* name used to load images */ -}; +typedef struct _XcursorImages { + int nimage; /* number of images */ + XcursorImage **images; /* array of XcursorImage pointers */ + char *name; /* name used to load images */ +} XcursorImages; + +XcursorImages * +XcursorLibraryLoadImages (const char *file, const char *theme, int size); void -xcursor_images_destroy(struct xcursor_images *images); +XcursorImagesDestroy (XcursorImages *images); void xcursor_load_theme(const char *theme, int size, - void (*load_callback)(struct xcursor_images *, void *), - void *user_data); + void (*load_callback)(XcursorImages *, void *), + void *user_data); #endif diff --git a/doc/Contributing b/doc/Contributing new file mode 100644 index 00000000..c51b7e80 --- /dev/null +++ b/doc/Contributing @@ -0,0 +1,83 @@ += Contributing to Wayland = + +== Sending patches == + +Patches should be sent to wayland-devel@lists.freedesktop.org, using +git send-email. See git's documentation for help [1]. + +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: + + protocol: Support scaled outputs and surfaces + +and + + doc: generate server documentation from XML too + +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 [2] for a recommend reading on writing commit messages. + +== Coding style == + +You should follow the style of the file you're editing. In general, we +try to follow the rules below. + +- 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 codition has braces, than the + other branch should also have braces; +- there is always an empty line between variable declarations and the + code; + +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 parenthesis; +- 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; + + long_variable_name = + function_with_a_really_long_name(parameter1, parameter2, + parameter3, parameter4); + + x = function_with_a_really_long_name(parameter1, parameter2, + parameter3, parameter4); + +== References == + + [1] http://git-scm.com/documentation + + [2] http://who-t.blogspot.de/2009/12/on-commit-messages.html + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..14637af6 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = doxygen publican man + +EXTRA_DIST = Contributing diff --git a/doc/book/.gitignore b/doc/book/.gitignore deleted file mode 100644 index 5a0bf031..00000000 --- a/doc/book/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/book diff --git a/doc/book/book.toml b/doc/book/book.toml deleted file mode 100644 index 48f699ce..00000000 --- a/doc/book/book.toml +++ /dev/null @@ -1,9 +0,0 @@ -[book] -title = "Wayland" -authors = ["Kristian Høgsberg"] -language = "en" - -[output.html] -git-repository-url = "https://gitlab.freedesktop.org/wayland/wayland" -edit-url-template = "https://gitlab.freedesktop.org/wayland/wayland/-/edit/main/doc/book/{path}" -site-url = "/docs/book/" diff --git a/doc/book/images/content-updates/content-updates.drawio b/doc/book/images/content-updates/content-updates.drawio deleted file mode 100644 index 5d780213..00000000 --- a/doc/book/images/content-updates/content-updates.drawio +++ /dev/null @@ -1,1528 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/content-updates/simple-desynchronized.drawio b/doc/book/images/content-updates/simple-desynchronized.drawio deleted file mode 100644 index c1adfd60..00000000 --- a/doc/book/images/content-updates/simple-desynchronized.drawio +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/content-updates/simple-synchronized.drawio b/doc/book/images/content-updates/simple-synchronized.drawio deleted file mode 100644 index a478ae02..00000000 --- a/doc/book/images/content-updates/simple-synchronized.drawio +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/content-updates/sync-subsurf-case1.drawio b/doc/book/images/content-updates/sync-subsurf-case1.drawio deleted file mode 100644 index 385c6fd7..00000000 --- a/doc/book/images/content-updates/sync-subsurf-case1.drawio +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/content-updates/sync-subsurf-case2.drawio b/doc/book/images/content-updates/sync-subsurf-case2.drawio deleted file mode 100644 index c1eaff66..00000000 --- a/doc/book/images/content-updates/sync-subsurf-case2.drawio +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/content-updates/sync-to-desync-subsurf.drawio b/doc/book/images/content-updates/sync-to-desync-subsurf.drawio deleted file mode 100644 index 7a72e0f6..00000000 --- a/doc/book/images/content-updates/sync-to-desync-subsurf.drawio +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/content-updates/sync-to-desync-transition.drawio b/doc/book/images/content-updates/sync-to-desync-transition.drawio deleted file mode 100644 index 9843acb6..00000000 --- a/doc/book/images/content-updates/sync-to-desync-transition.drawio +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/book/images/wayland-architecture.gv b/doc/book/images/wayland-architecture.gv deleted file mode 100644 index f2c35075..00000000 --- a/doc/book/images/wayland-architecture.gv +++ /dev/null @@ -1,36 +0,0 @@ -digraph arch_wayland { - edge[ - fontname="DejaVu Sans", - dir="both", - arrowtail="dot", - arrowsize=.5, - fontname="DejaVu Sans", - fontsize="18", - ] - - node[ - color=none, - margin=0, - fontname="DejaVu Sans", - fontsize="18", - ] - - c1 [label=<
Wayland Client
>, URL="#c1"] - c2 [label=<
Wayland Client
>, URL="#c2"] - - comp [tooltip="Wayland Compositor", label=<

Wayland
Compositor

>, URL="#comp"] - - impl [tooltip="KMS evdev Kernel", label=<
KMSevdev
Kernel
>, URL="#impl"] - - c1 -> comp [taillabel="③", labeldistance=2.5, URL="#step_3"]; - c2 -> comp; - - comp -> c1 [label="②", URL="#step_2"]; - comp -> c2; - - comp -> impl [xlabel = "④", URL="#step_4"]; - comp -> impl [style = invis, label=" "]; - impl -> comp [xlabel = "①", URL="#step_1"]; - - c1 -> c2 [style=invis]; -} diff --git a/doc/book/images/x-architecture.gv b/doc/book/images/x-architecture.gv deleted file mode 100644 index b223d1dc..00000000 --- a/doc/book/images/x-architecture.gv +++ /dev/null @@ -1,53 +0,0 @@ -digraph arch_x { - edge[ - fontname="DejaVu Sans", - dir="both", - arrowtail="dot", - arrowsize=.5, - fontname="DejaVu Sans", - fontsize="18", - ] - - node[ - shape="none", - color=none, - margin=0, - fontname="DejaVu Sans", - fontsize="18", - ] - - { - rank=same; - c1 [label=<
X Client
>, URL="#c1"] - c3 [label=<
X Client
>, URL="#c3"] - } - c2 [label=<
X Client
>, URL="#c2"] - - { - rank=same; - xserver [tooltip="X Server", label=<

X Server

>, URL="#xserver"] - comp [tooltip="Compositor", label=<

Compositor

>, URL="#comp"] - } - - impl [tooltip="KMS evdev Kernel", label=<
KMSevdev
Kernel
>, URL="#impl"] - - c1 -> xserver [taillabel="③", labeldistance=2, URL="#step_3"]; - c2 -> xserver; - c3 -> xserver; - - xserver -> c1 [taillabel="②", labeldistance=2, URL="#step_2"]; - xserver -> c2; - xserver -> c3; - - xserver -> impl [taillabel="⑥", labeldistance=1.75, URL="#step_6"]; - xserver -> impl [style=invis, label=" "]; - impl -> xserver [taillabel="①", labeldistance=1.75, URL="#step_1"]; - - xserver -> comp [style=invis]; - xserver -> comp [taillabel="④", labeldistance=1.75, labelangle=-45, URL="#step_4"]; - comp -> xserver [taillabel="⑤", URL="#step_5"]; - comp -> xserver [style=invis] - - c1 -> c2 [style=invis]; - c3 -> c2 [style=invis]; - } diff --git a/doc/book/meson.build b/doc/book/meson.build deleted file mode 100644 index fa8f1dbb..00000000 --- a/doc/book/meson.build +++ /dev/null @@ -1,58 +0,0 @@ -srcs = files( - 'src/Protocol.md', - 'src/Foreword.md', - 'src/Xwayland.md', - 'src/SUMMARY.md', - 'src/Content_Updates.md', - 'src/Color.md', - 'src/Message_XML.md', - 'src/Architecture.md', - 'src/Introduction.md', - 'src/images/content-updates/sync-to-desync-subsurf-3.png', - 'src/images/content-updates/sync-subsurf-case2-2.png', - 'src/images/content-updates/simple-synchronized-state-4.png', - 'src/images/content-updates/sync-subsurf-case2-3.png', - 'src/images/content-updates/sync-to-desync-transition-2.png', - 'src/images/content-updates/simple-desynchronized-state-4.png', - 'src/images/content-updates/simple-synchronized-state-3.png', - 'src/images/content-updates/simple-synchronized-state-1.png', - 'src/images/content-updates/sync-subsurf-case1-4.png', - 'src/images/content-updates/sync-to-desync-subsurf-1.png', - 'src/images/content-updates/simple-desynchronized-state-1.png', - 'src/images/content-updates/simple-desynchronized-state-3.png', - 'src/images/content-updates/simple-desynchronized-state-6.png', - 'src/images/content-updates/sync-subsurf-case1-2.png', - 'src/images/content-updates/sync-subsurf-case1-1.png', - 'src/images/content-updates/simple-synchronized-state-5.png', - 'src/images/content-updates/simple-synchronized-state-2.png', - 'src/images/content-updates/simple-desynchronized-state-2.png', - 'src/images/content-updates/content-update-legend.png', - 'src/images/content-updates/sync-to-desync-subsurf-2.png', - 'src/images/content-updates/sync-to-desync-transition-3.png', - 'src/images/content-updates/sync-subsurf-case2-1.png', - 'src/images/content-updates/sync-subsurf-case1-5.png', - 'src/images/content-updates/sync-subsurf-case1-3.png', - 'src/images/content-updates/simple-desynchronized-state-5.png', - 'src/images/content-updates/sync-to-desync-transition-1.png', - 'src/images/icon.svg', - 'src/images/x-architecture.png', - 'src/images/wayland.png', - 'src/images/wayland-architecture.png', - 'src/images/xwayland-architecture.png', - 'src/Compositors.md', -) - -custom_target( - 'Wayland-book', - command: [ - mdbook, - 'build', - '-d', meson.current_build_dir() / 'book', - meson.current_source_dir(), - ], - depend_files: srcs, - output: 'book', - build_by_default: true, - install: true, - install_dir: publican_install_prefix, -) diff --git a/doc/book/src/Architecture.md b/doc/book/src/Architecture.md deleted file mode 100644 index 2ecf38ac..00000000 --- a/doc/book/src/Architecture.md +++ /dev/null @@ -1,215 +0,0 @@ -# Wayland Architecture - -## X vs. Wayland Architecture - -A good way to understand the Wayland architecture and how it is different from X -is to follow an event from the input device to the point where the change it -affects appears on screen. - -This is where we are now with X: - -**X architecture diagram** - -![](images/x-architecture.png) - -1. The kernel gets an event from an input device and sends it to X through the - evdev input driver. The kernel does all the hard work here by driving the - device and translating the different device specific event protocols to the - linux evdev input event standard. - -2. The X server determines which window the event affects and sends it to the - clients that have selected for the event in question on that window. The X - server doesn't actually know how to do this right, since the window location - on screen is controlled by the compositor and may be transformed in a number - of ways that the X server doesn't understand (scaled down, rotated, wobbling, - etc). - -3. The client looks at the event and decides what to do. Often the UI will have - to change in response to the event - perhaps a check box was clicked or the - pointer entered a button that must be highlighted. Thus the client sends a - rendering request back to the X server. - -4. When the X server receives the rendering request, it sends it to the driver - to let it program the hardware to do the rendering. The X server also - calculates the bounding region of the rendering, and sends that to the - compositor as a damage event. - -5. The damage event tells the compositor that something changed in the window - and that it has to recomposite the part of the screen where that window is - visible. The compositor is responsible for rendering the entire screen - contents based on its scenegraph and the contents of the X windows. Yet, it - has to go through the X server to render this. - -6. The X server receives the rendering requests from the compositor and either - copies the compositor back buffer to the front buffer or does a pageflip. In - the general case, the X server has to do this step so it can account for - overlapping windows, which may require clipping and determine whether or not - it can page flip. However, for a compositor, which is always fullscreen, this - is another unnecessary context switch. - -As suggested above, there are a few problems with this approach. The X server -doesn't have the information to decide which window should receive the event, -nor can it transform the screen coordinates to window-local coordinates. And -even though X has handed responsibility for the final painting of the screen to -the compositing manager, X still controls the front buffer and modesetting. Most -of the complexity that the X server used to handle is now available in the -kernel or self contained libraries (KMS, evdev, mesa, fontconfig, freetype, -cairo, Qt etc). In general, the X server is now just a middle man that -introduces an extra step between applications and the compositor and an extra -step between the compositor and the hardware. - -In Wayland the compositor is the display server. We transfer the control of KMS -and evdev to the compositor. The Wayland protocol lets the compositor send the -input events directly to the clients and lets the client send the damage event -directly to the compositor: - -**Wayland architecture diagram** - -![](images/wayland-architecture.png) - -1. The kernel gets an event and sends it to the compositor. This is similar to - the X case, which is great, since we get to reuse all the input drivers in - the kernel. - -2. The compositor looks through its scenegraph to determine which window should - receive the event. The scenegraph corresponds to what's on screen and the - compositor understands the transformations that it may have applied to the - elements in the scenegraph. Thus, the compositor can pick the right window - and transform the screen coordinates to window-local coordinates, by applying - the inverse transformations. The types of transformation that can be applied - to a window is only restricted to what the compositor can do, as long as it - can compute the inverse transformation for the input events. - -3. As in the X case, when the client receives the event, it updates the UI in - response. But in the Wayland case, the rendering happens in the client, and - the client just sends a request to the compositor to indicate the region that - was updated. - -4. The compositor collects damage requests from its clients and then - recomposites the screen. The compositor can then directly issue an ioctl to - schedule a pageflip with KMS. - -## Wayland Rendering - -One of the details I left out in the above overview is how clients actually -render under Wayland. By removing the X server from the picture we also removed -the mechanism by which X clients typically render. But there's another mechanism -that we're already using with DRI2 under X: direct rendering. With direct -rendering, the client and the server share a video memory buffer. The client -links to a rendering library such as OpenGL that knows how to program the -hardware and renders directly into the buffer. The compositor in turn can take -the buffer and use it as a texture when it composites the desktop. After the -initial setup, the client only needs to tell the compositor which buffer to use -and when and where it has rendered new content into it. - -This leaves an application with two ways to update its window contents: - -1. Render the new content into a new buffer and tell the compositor to use that - instead of the old buffer. The application can allocate a new buffer every - time it needs to update the window contents or it can keep two (or more) - buffers around and cycle between them. The buffer management is entirely - under application control. - -2. Render the new content into the buffer that it previously told the compositor - to to use. While it's possible to just render directly into the buffer shared - with the compositor, this might race with the compositor. What can happen is - that repainting the window contents could be interrupted by the compositor - repainting the desktop. If the application gets interrupted just after - clearing the window but before rendering the contents, the compositor will - texture from a blank buffer. The result is that the application window will - flicker between a blank window or half-rendered content. The traditional way - to avoid this is to render the new content into a back buffer and then copy - from there into the compositor surface. The back buffer can be allocated on - the fly and just big enough to hold the new content, or the application can - keep a buffer around. Again, this is under application control. - -In either case, the application must tell the compositor which area of the -surface holds new contents. When the application renders directly to the shared -buffer, the compositor needs to be noticed that there is new content. But also -when exchanging buffers, the compositor doesn't assume anything changed, and -needs a request from the application before it will repaint the desktop. The -idea that even if an application passes a new buffer to the compositor, only a -small part of the buffer may be different, like a blinking cursor or a spinner. - -## Accelerated GPU Buffer Exchange - -Clients -[exchange](https://docs.kernel.org/userspace-api/dma-buf-alloc-exchange.html) -GPU buffers with the compositor as dma-buf file descriptors, which are universal -handles that are independent of any particular rendering API or memory -allocator. The -[linux-dmabuf-v1](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/stable/linux-dmabuf/linux-dmabuf-v1.xml) -protocol is used to turn one or more dma-buf FDs into a -[wl_buffer](https://wayland.app/protocols/wayland#wl_buffer). - -If the client uses the -[Vulkan](https://docs.vulkan.org/spec/latest/chapters/VK_KHR_surface/wsi.html) -or -[EGL](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_platform_wayland.txt) -(via -[wayland-egl](https://gitlab.freedesktop.org/wayland/wayland/-/tree/main/egl)) -window-system integration (WSI), this is done transparently by the WSI. - -Clients can alternatively allocate and import dma-bufs themselves using the GBM -library, Vulkan, udmabuf, or dma-buf heaps. - -- Using GBM, the client can allocate a gbm_bo and export one or more dma-buf FDs - from it. - -- Using Vulkan, the client can create a VkDeviceMemory object and use - [VK_EXT_external_memory_dma_buf](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html) - and - [VK_EXT_image_drm_format_modifier](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html) - to export a dma-buf FD from it. - -- [udmabuf](https://lwn.net/Articles/749206/) can be used to create dma-buf FDs - from linear host memory. - -- [Dma-buf heaps](https://docs.kernel.org/userspace-api/dma-buf-heaps.html) can - be used by privileged applications to create dma-buf FDs on embedded devices. - -Compositors use -[VK_EXT_external_memory_dma_buf](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_external_memory_dma_buf.html) -and -[VK_EXT_image_drm_format_modifier](https://docs.vulkan.org/refpages/latest/refpages/source/VK_EXT_image_drm_format_modifier.html) -or -[EGL_EXT_image_dma_buf_import](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt) -and -[EGL_EXT_image_dma_buf_import_modifiers](https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt) -to import the dma-bufs provided by the client into their own Vulkan or EGL -renderers. - -Clients do not need to wait for the GPU to finish rendering before submitting -dma-bufs to the compositor. Clients can use the -[linux-drm-syncobj-v1](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml) -protocol to exchange DRM synchronization objects with the compositor. These -objects are used to asynchronously signal ownership transfer of buffers from -clients to the compositor and vice versa. The WSIs do this transparently. - -If the linux-drm-syncobj-v1 protocol is not supported by the compositor, clients -and compositors can use the -[DMA_BUF_IOCTL_EXPORT_SYNC_FILE](https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_export_sync_file) -and -[DMA_BUF_IOCTL_IMPORT_SYNC_FILE](https://docs.kernel.org/driver-api/dma-buf.html#c.dma_buf_import_sync_file) -ioctls to access and create implicit synchronization barriers. - -## Display Programming - -Compositors enumerate DRM KMS devices using -[udev](https://en.wikipedia.org/wiki/Udev). Udev also notifies compositors of -KMS device and display hotplug events. - -Access to DRM KMS device ioctls is privileged. Since compositors usually run as -unprivileged applications, they typically gain access to a privileged file -descriptor using the -[TakeDevice](https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html#Session%20Objects) -method provided by logind. - -Using the file descriptor, compositors use KMS -[ioctls](https://docs.kernel.org/gpu/drm-kms.html) to enumerate the available -displays. - -Compositors use [atomic mode -setting](https://docs.kernel.org/gpu/drm-kms.html#atomic-mode-setting) to change -the buffer shown by the display, to change the display's resolution, to enable -or disable HDR, and so on. diff --git a/doc/book/src/Color.md b/doc/book/src/Color.md deleted file mode 100644 index 3787108b..00000000 --- a/doc/book/src/Color.md +++ /dev/null @@ -1,100 +0,0 @@ -# Color management - -## Overview - -Color management in Wayland considers only displays. All pictures in Wayland are -always display-referred, meaning that the pixel values are intended as-is for -some specific display where they would produce the light emissions -([stimuli](https://cie.co.at/eilvterm/17-23-002)) the picture's author desired. -Wayland does not support displaying "raw" camera or scanner images as they are -not display-referred, nor are they even pictures without complex and subjective -processing. - -Stimuli — the picture itself — are only half of the picture reproduction. The -other half is the environment where a display is viewed. A striking example is -comparing a brightly lit office to a dark movie theater, the stimuli required to -produce a good reading of the picture is greatly different. Therefore -display-referred does not include only the display but the viewing environment -as well. - -Window systems have been very well capable of operating without any explicit -consideration to color management. This is because there used to be the implicit -assumption of the standard display, the sRGB display, which all computer -monitors implemented, more or less. The viewing environment was and still is -accounted by adjusting the display and/or the room to produce a workable -experience. Pictures are authored on a computer system by drawing, painting and -adjusting the picture until it looks right on the author's monitor. This -implicitly builds the standard display and environment assumption into the -picture data. Deviations from the sRGB specification were minor enough that they -often did not matter if not in a professional context like the printing -industry. Displaying video material required some more attention to the details, -because video and television standards differ enough from the sRGB display. What -really made explicit color management a hard requirement for entertainment is -the coming of wide color gamut (WCG) and high dynamic range (HDR) materials and -displays. - -The color management design in Wayland follows the general Wayland design -principles: compositors tell clients what would be the optimal thing to do, -clients tell the compositors what kind of pictures they are actually producing, -and then compositors display those pictures the best they can. - -## Protocol Interfaces - -Color management interfaces in Wayland and divided into two protocols: -[color-management](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-management?ref_type=heads) -and -[color-representation](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-representation?ref_type=heads). -They are designed to work together, but they can also be used independently when -the other one is not needed. - -### Color-management - -Color management protocol has two main purposes. First, it puts the -responsibility of color management on the compositor. This means that clients do -not necessarily need to care about color management at all, and can display just -fine by using the traditional standard display assumption even when the actual -display is wildly different. Clients can also choose to target some other -assumed display and let the compositor handle it, or they can explicitly render -for the actual display at hand. Second, when the window system has multiple -different monitors, and a wl_surface happens to span more than one monitor, the -compositor can display the surface content correctly on all spanned monitors -simultaneously, as much as physically possible. - -Color-management protocol concentrates on colorimetry: when you have a pixel -with RGB values, what stimulus do those values represent. The stimulus -definition follows the CIE 1931 two-degree observer model. Some core concepts -here are color primaries, white point, transfer function, and dynamic range. The -viewing environment is represented in an extremely simplified way as the -reference white luminance. The connection between pixel RGB values and stimulus -plus viewing environment is recorded in an _image description_ object. Clients -can create image description objects and tag `wl_surface`s with them, to -indicate what kind of surface content there will be. Clients can also ask what -image description the compositor would prefer to have on the `wl_surface`, and -that preference can change over time, e.g. when the `wl_surface` is moved from -one `wl_output` to another. Following the compositor's preference may provide -advantages in image quality and power consumption. - -Image description objects can come in two flavors: parametric and ICC-based. The -above was written with parametric image descriptions in mind, and they have -first-class support for HDR. ICC-based image descriptions are wrapping an ICC -profile and have no other data. ICC profiles are the standard tool for standard -dynamic range (SDR) display color management. This means the capabilities -between the two flavors differ, and one cannot always be replaced by the other. -Compositor support for each flavor is optional. - -### Color-representation - -Color-representation protocol deals with (potentially sub-sampled) YCbCr-RGB -conversion, quantization range, and the inclusion of alpha in the RGB color -channels, a.k.a. pre-multiplication. There are several different specifications -on how an YCbCr-like (including ICtCp) signal, with chroma sub-sampling or not, -is created from a full-resolution RGB image. Again, a client can tag a -`wl_surface` with color-representation metadata to tell the compositor what kind -of pixel data will be displayed through the wl_surface. - -The main purpose of color-representation is to correctly off-load the YCbCr-RGB -conversion to the compositor, which can then opportunistically off-load it -further to very power-efficient fixed-function circuitry in a display -controller. This can significantly reduce power consumption when watching videos -compared to using a GPU for the same, and on some embedded hardware platforms it -is a hard requirement for processing high resolution video. diff --git a/doc/book/src/Compositors.md b/doc/book/src/Compositors.md deleted file mode 100644 index 61d1bdbd..00000000 --- a/doc/book/src/Compositors.md +++ /dev/null @@ -1,76 +0,0 @@ -# Types of Compositors - -Compositors come in different types, depending on which role they play in the -overall architecture of the OS. For instance, a [system -compositor](#system-compositor) can be used for booting the system, handling -multiple user switching, a possible console terminal emulator and so forth. A -different compositor, a [session compositor](#session-compositor) would provide -the actual desktop environment. There are many ways for different types of -compositors to co-exist. - -In this section, we introduce three types of Wayland compositors relying on -[libwayland-server](https://gitlab.freedesktop.org/wayland/wayland). - -## System Compositor - -A system compositor can run from early boot until shutdown. It effectively -replaces the kernel vt system, and can tie in with the systems graphical boot -setup and multiseat support. - -A system compositor can host different types of session compositors, and let us -switch between multiple sessions (fast user switching, or secure/personal -desktop switching). - -A linux implementation of a system compositor will typically use libudev, egl, -kms, evdev and cairo. - -For fullscreen clients, the system compositor can reprogram the video scanout -address to read directly from the client provided buffer. - -## Session Compositor - -A session compositor is responsible for a single user session. If a system -compositor is present, the session compositor will run nested under the system -compositor. Nesting is feasible because the protocol is asynchronous; roundtrips -would be too expensive when nesting is involved. If no system compositor is -present, a session compositor can run directly on the hardware. - -X applications can continue working under a session compositor by means of a -root-less X server that is activated on demand. - -Possible examples for session compositors include - -- gnome-shell - -- moblin - -- kwin - -- kmscon - -- rdp session - -- Weston with X11 or Wayland backend is a session compositor nested in another - session compositor. - -- fullscreen X session under Wayland - -## Embedding Compositor - -X11 lets clients embed windows from other clients, or lets clients copy pixmap -contents rendered by another client into their window. This is often used for -applets in a panel, browser plugins and similar. Wayland doesn't directly allow -this, but clients can communicate GEM buffer names out-of-band, for example, -using D-Bus, or command line arguments when the panel launches the applet. -Another option is to use a nested Wayland instance. For this, the Wayland server -will have to be a library that the host application links to. The host -application will then pass the Wayland server socket name to the embedded -application, and will need to implement the Wayland compositor interface. The -host application composites the client surfaces as part of its window, that is, -in the web page or in the panel. The benefit of nesting the Wayland server is -that it provides the requests the embedded client needs to inform the host about -buffer updates and a mechanism for forwarding input events from the host -application. - -An example for this kind of setup is firefox embedding the flash player as a -kind of special-purpose compositor. diff --git a/doc/book/src/Content_Updates.md b/doc/book/src/Content_Updates.md deleted file mode 100644 index 5b55bab0..00000000 --- a/doc/book/src/Content_Updates.md +++ /dev/null @@ -1,214 +0,0 @@ -# Content Updates - -## Overview - -In the Wayland protocol, requests are asynchronous but take effect immediately -when the compositor receives them. However, some requests on surfaces are not -applied immediately but are instead double-buffered to allow atomic changes. -These double-buffered changes are committed through the wl_surface.commit -request, which creates a Content Update. - -Content Updates encapsulate all double-buffered state changes and can be applied -by the compositor. The complexity arises when considering subsurfaces, which can -operate in synchronized mode. When a subsurface is synchronized, its Content -Updates must be applied atomically together with the parent surface's state. -This synchronization can extend through an entire tree of subsurfaces, where -child subsurfaces inherit the synchronized behavior from their parents. - -Historically, Content Updates from synchronized subsurfaces were merged into the -pending state of the parent surface on commit. However, the introduction of -constraints—which can defer the application of Content Updates—necessitated a -more sophisticated model. This led to the implementation of per-surface queues -of Content Updates, with dependencies between Content Updates across different -queues. This queuing model maintains backwards compatibility with the earlier -approach of merging Content Updates into the parent's pending state on commit. - -The core protocol defines the semantics of Content Updates using per-surface -queues, but compositors that do not need to support constraints may implement -the simpler legacy model where synchronized subsurface states are merged -directly into the parent's pending state. - -## Rules - -The core protocol specifies the behavior in wl_subsurface and wl_surface.commit. -The behavior can be summarized by the following rules: - -1. Content Updates (CU) contain all double-buffered state of the surface and - selected state from their direct children. - -2. Surfaces which are effectively synchronized create Synchronized Content - Updates (SCU), otherwise they create Desync Content Updates (DCU). - -3. When a CU is created, it gets a dependency on the previous CU of the same - queues (if it exists). - -4. When a CU is created, it gets a dependency on the last SCU of direct child - surfaces that are not reachable (if they exists). - -5. The CUs and their dependencies form a DAG, where CUs are nodes and - dependencies are edges. - -6. All DCUs starting from the front of the queues until the first SCU or the - back of the queue is reached are candidates. - -7. If the maximal DAG that's reachable from a candidate (candidate DAG) does not - have any constraints, then this DAG can be applied. - -8. A DAG is applied atomically by recursively applying a content update without - dependencies and removing it from the DAG. - -9. Surfaces transition from effectively sync to effectively desync after their - parents. - -10. When a surface transitions to effectively desync, all SCUs in its queue - which are not reachable by a DCU become DCUs. - -## Examples - -These examples should help to build an intuition for how content updates -actually behave. They cover the interesting edge cases, such as subsurfaces with -constraints, and transitioning from a sync subsurface to a desync one. - -In all the examples below, the surface T1 refers to a toplevel surface, SS1 -refers to a sub-surface which is a child of T1, and SS2 refers to a sub-surface -which is a child of SS1. - -### Legend - -![](images/content-updates/content-update-legend.png) - -### Simple Desynchronized Case - -1. SS2 is effectively desynchronized and commits. This results in the - desynchronized content update (DCU) _1_. - - ![](images/content-updates/simple-desynchronized-state-1.png) - -2. DCU _1_ is a candidate, and the candidate DAG reachable from DCU _1_ is only DCU - _1_ itself. DCU _1_ and thus the candidate DAG does not have any constraints and - can be applied. - - ![](images/content-updates/simple-desynchronized-state-2.png) - -3. The content updates of the candidate DAG get applied to the surface atomically. - - ![](images/content-updates/simple-desynchronized-state-3.png) - -4. T1 commits a DCU with a _buffer-sync_ constraint. It is a candidate but its DAG - can't be applied because it contains a constraint. - - ![](images/content-updates/simple-desynchronized-state-4.png) - -5. T1 commits another CU (DCU _3_) which is added at the end of the queue, with a - dependency to the previous CU (DCU _2_). Both DCU _2_ and DCU _3_ are - candidates, but both DAGs contain DCU _2_ with a constraint, and can't be - applied. - - ![](images/content-updates/simple-desynchronized-state-5.png) - -6. When the constraint gets cleared, both DAGs can be applied to the surface - atomitcally (either only _2_, or _2_ and _3_). - - ![](images/content-updates/simple-desynchronized-state-6.png) - -### Simple Synchronized Case - -1. SS1 and SS2 are effectively synchronized. SS2 commits SCU _1_. - - ![](images/content-updates/simple-synchronized-state-1.png) - -2. SS1 commits SCU _2_. The direct child surfaces SS2 has the last SCU _1_ in its - queue, which is not reachable. This creates a dependency from SCU _2_ to SCU - _1_. - - ![](images/content-updates/simple-synchronized-state-2.png) - -3. SS1 commits SCU _3_. The direct child surfaces SS2 has the last SCU _1_ in its - queue, which is already reachable by SCU _2_. No dependency to SCU _1_ is - created. A dependency to the previous CU of the same queue (SCU _2_) is created. - - ![](images/content-updates/simple-synchronized-state-3.png) - -4. T1 commit DCU _4_. It is a candidate, its DAG does not contain any constraint - and it can be applied. - - ![](images/content-updates/simple-synchronized-state-4.png) - -5. The DAG gets applied to the surfaces atomically. - - ![](images/content-updates/simple-synchronized-state-5.png) - -### Complex Synchronized Subsurface Case 1 - -1. Every DCU (_1_ and _6_) contain CUs with constraints in their candidate DAG - - ![](images/content-updates/sync-subsurf-case1-1.png) - -2. Waiting until the _buffer-sync_ constrain on CU _1_ is cleared, the candidate - DAG of CU _1_ does not contain constraints and can be applied - - ![](images/content-updates/sync-subsurf-case1-2.png) - -3. That leaves the candidate DAG of CU _6_ which still contains another CU with a - _buffer-sync_ constrain - - ![](images/content-updates/sync-subsurf-case1-3.png) - -4. Waiting until the _buffer-sync_ constrain on CU _6_ is cleared, the candidate - DAG of _6_ does not contain CUs with constraints and can be applied. - - ![](images/content-updates/sync-subsurf-case1-4.png) - -5. There is no DCU left and no constraint remaining. Nothing more can be applied - without a new CU. - - ![](images/content-updates/sync-subsurf-case1-5.png) - -### Complex Synchronized Subsurface Case 2 - -1. Both DCUs (_1_ and _6_) have a reachable DAG containing CU _1_ with a constraint - - ![](images/content-updates/sync-subsurf-case2-1.png) - -2. Waiting until the _buffer-sync_ constrain on _1_ is cleared, both DAGs contain - no CU with constraints and can be applied in any order - - ![](images/content-updates/sync-subsurf-case2-2.png) - -3. That leaves the same state as in the previous case - - ![](images/content-updates/sync-subsurf-case2-3.png) - -### Synchronized to Desynchronized Subsurface - -1. There is one DCU (_4_) with its reachable DAG that cannot be applied because CU - _4_ contains a constraint - - ![](images/content-updates/sync-to-desync-subsurf-1.png) - -2. Surface _SS1_ transitions from effectively synchronized to effectively - desynchronized. SCU _2_ is reachable by DCU _4_ so nothing changes. - - ![](images/content-updates/sync-to-desync-subsurf-2.png) - -3. Surface _SS1_ provides a new DCU (_5_) but because the CU before (_2_) is a - Synchronized CU, it is not a candidate - - ![](images/content-updates/sync-to-desync-subsurf-3.png) - -### Synchronized to Desynchronized Transition - -1. There are four SCUs and all surfaces are effectively synchronized. - - ![](images/content-updates/sync-to-desync-transition-1.png) - -2. Surface _SS1_ transitions to effectively desynchronized and SCU _2_ becomes a - DCU because it is not reachable from a DCU - - ![](images/content-updates/sync-to-desync-transition-2.png) - -3. Surface _SS2_ transitions to effectively desynchronized. SCUs _3_ and _4_ become - DCUs because they are not reachable from a DCU. SCU _1_ does not change because - it is reachable by DCU _2_. - - ![](images/content-updates/sync-to-desync-transition-3.png) diff --git a/doc/book/src/Foreword.md b/doc/book/src/Foreword.md deleted file mode 100644 index f1b06625..00000000 --- a/doc/book/src/Foreword.md +++ /dev/null @@ -1,86 +0,0 @@ - - -# Preface - -This document describes the Wayland architecture and Wayland model of operation. -This document is aimed primarily at Wayland developers and those looking to -program with it; it does not cover application development. - -There have been many contributors to this document and since this is only the -first edition many errors are expected to be found. We appreciate corrections. - -Yours, the Wayland open-source community November 2012 - -## Protocol Documentation - -This document does not describe the semantics of individual messages sent -between compositors and clients. Consult the following documents to learn about -concrete Wayland interfaces, requests, and events. - -- [wayland.xml] - The official documentation of the core protocol. -- [wayland-protocols] - Standardized Wayland extension protocols. -- [wayland.app] - A community-maintained website that renders these protocols, - and many more, as easily accessible HTML pages. - -[wayland.xml]: https://gitlab.freedesktop.org/wayland/wayland/-/blob/main/protocol/wayland.xml -[wayland-protocols]: https://gitlab.freedesktop.org/wayland/wayland-protocols -[wayland.app]: https://wayland.app - -## About the Book - -This book is written in markdown and converted to HTML using -[mdbook](https://rust-lang.github.io/mdBook). - -It supports the [CommonMark](https://commonmark.org/) dialect of markdown plus a number of -widely supported extensions: - -- `~~strikethrough~~` -- ```markdown - footnotes[^note] - - [^note]: text - ``` -- ```markdown - | Tables | Header2 | - |--------|---------| - | abc | def | - ``` -- ```markdown - - [x] Task lists - - [ ] Incomplete task - ``` -- ```markdown - definition lists - : This is the definition of a - definition list - ``` -- ```markdown - > [!NOTE] - > Admonitions - ``` - -The full list of extensions is documented -[here](https://rust-lang.github.io/mdBook/format/markdown.html#extensions). - -## Copyright - -Copyright © 2012 Kristian Høgsberg - -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. diff --git a/doc/book/src/Introduction.md b/doc/book/src/Introduction.md deleted file mode 100644 index 51ef7a01..00000000 --- a/doc/book/src/Introduction.md +++ /dev/null @@ -1,73 +0,0 @@ -# Introduction - -## Motivation - -Most Linux and Unix-based systems rely on the X Window System (or simply _X_) as -the low-level protocol for building bitmap graphics interfaces. On these -systems, the X stack has grown to encompass functionality arguably belonging in -client libraries, helper libraries, or the host operating system kernel. Support -for things like PCI resource management, display configuration management, -direct rendering, and memory management has been integrated into the X stack, -imposing limitations like limited support for standalone applications, -duplication in other projects (e.g. the Linux fb layer or the DirectFB project), -and high levels of complexity for systems combining multiple elements (for -example radeon memory map handling between the fb driver and X driver, or VT -switching). - -Moreover, X has grown to incorporate modern features like offscreen rendering -and scene composition, but subject to the limitations of the X architecture. For -example, the X implementation of composition adds additional context switches -and makes things like input redirection difficult. - -![](images/x-architecture.png) - -The diagram above illustrates the central role of the X server and compositor in -operations, and the steps required to get contents on to the screen. - -Over time, X developers came to understand the shortcomings of this approach and -worked to split things up. Over the past several years, a lot of functionality -has moved out of the X server and into client-side libraries or kernel drivers. -One of the first components to move out was font rendering, with freetype and -fontconfig providing an alternative to the core X fonts. Direct rendering OpenGL -as a graphics driver in a client side library went through some iterations, -ending up as DRI2, which abstracted most of the direct rendering buffer -management from client code. Then cairo came along and provided a modern 2D -rendering library independent of X, and compositing managers took over control -of the rendering of the desktop as toolkits like GTK+ and Qt moved away from -using X APIs for rendering. Recently, memory and display management have moved -to the Linux kernel, further reducing the scope of X and its driver stack. The -end result is a highly modular graphics stack. - -## The compositing manager as the display server - -Wayland is a new display server and compositing protocol, and Weston is the -implementation of this protocol which builds on top of all the components above. -We are trying to distill out the functionality in the X server that is still -used by the modern Linux desktop. This turns out to be not a whole lot. -Applications can allocate their own off-screen buffers and render their window -contents directly, using hardware accelerated libraries like libGL, or high -quality software implementations like those found in Cairo. In the end, what’s -needed is a way to present the resulting window surface for display, and a way -to receive and arbitrate input among multiple clients. This is what Wayland -provides, by piecing together the components already in the eco-system in a -slightly different way. - -X will always be relevant, in the same way Fortran compilers and VRML browsers -are, but it’s time that we think about moving it out of the critical path and -provide it as an optional component for legacy applications. - -Overall, the philosophy of Wayland is to provide clients with a way to manage -windows and how their contents are displayed. Rendering is left to clients, and -system wide memory management interfaces are used to pass buffer handles between -clients and the compositing manager. - -![](images/wayland-architecture.png) - -The figure above illustrates how Wayland clients interact with a Wayland server. -Note that window management and composition are handled entirely in the server, -significantly reducing complexity while marginally improving performance through -reduced context switching. The resulting system is easier to build and extend -than a similar X system, because often changes need only be made in one place. -Or in the case of protocol extensions, two (rather than 3 or 4 in the X case -where window management and/or composition handling may also need to be -updated). diff --git a/doc/book/src/Message_XML.md b/doc/book/src/Message_XML.md deleted file mode 100644 index 2a3c5f3f..00000000 --- a/doc/book/src/Message_XML.md +++ /dev/null @@ -1,515 +0,0 @@ -# Message Definition Language - -## Overview - -The fundamentals of the Wayland protocol are explained in [Wayland Protocol and -Model of Operation](Protocol.md). This chapter formally defines the language -used to define Wayland protocols. - -Wayland is an object-oriented protocol. Each object follows exactly one -interface. An interface is a collection of message and enumeration definitions. -A message can be either a request (sent by a client) or an event (sent by a -server). A message can have arguments. All arguments are typed. - -## XML Elements - -### protocol - -``` -protocol ::= (copyright?, description? interface+) -``` - -`protocol` is the root element in a Wayland protocol XML file. Code generation -tools may optionally use the protocol `name` in API symbol names. The XML file -name should be similar to the protocol name. - -The description element should be used to document the intended purpose of the -protocol, give an overview, and give any development stage notices if -applicable. - -The copyright element should be used to indicate the copyrights and the license -of the XML file. - -**Required attributes** - -`name`="`cname`" - : The name of the protocol (a.k.a protocol extension). The name must start - with one of the ASCII characters a-z, A-Z, or underscore, and the following - characters may additionally include numbers 0-9. - - The name should be globally unique. Protocols to be included in - [wayland-protocols](https://gitlab.freedesktop.org/wayland/wayland-protocols) - must follow the naming rules set there. Other protocols should use a unique - prefix for the name, e.g. referring to the owning project's name. - -### copyright - -Parent elements: protocol - -``` -copyright ::= #PCDATA -``` - -Contains free-form, pre-formatted text for copyright and license notices. - -### description - -Parent elements: protocol, interface, request, event, arg, enum, entry - -``` -description ::= #PCDATA -``` - -Contains human-readable documentation for its parent element. May contain -formatted text, including paragraphs and bulleted lists. - -**Optional attributes** - -`summary`="`summary`" - : A short (half a line at most) description of the documented element. - - When a description element is used, it is recommended to not use the - `summary` attribute of the parent element. - -### interface - -Parent elements: protocol - -``` -interface ::= (description?, (request|event|enum)+) -``` - -An interface element contains the requests and events that form the interface. -Enumerations can also be defined with enum elements. These all belong into the -namespace of the interface. Code generation tools may use the interface `name` -in API symbol names. - -Interfaces form an ancestry tree. Aside from -[wl_display](https://wayland.app/protocols/wayland#wl_display), new protocol -objects are always created through an existing protocol object that may be -referred to as _the factory object_. This can happen in one of two ways: the -factory object's interface either defines or does not define the new object's -interface. - -When the factory interface defines the new object's interface, the new object -also inherits the factory object's interface version number. This number defines -the interface version of the new object. The factory object is referred to as -_the parent object_ and the factory interface is referred to as _the parent -interface_. This forms the ancestry tree of interfaces. - -When the factory interface does not define the new object's interface, both the -interface name and the version must be communicated explicitly. The foremost -example of this is -[wl_registry.bind](https://wayland.app/protocols/wayland#wl_registry:request:bind). -In this case the terms "parent" or "ancestor" are not used. Interfaces that are -advertised through -[wl_registry](https://wayland.app/protocols/wayland#wl_registry) are called -_global interfaces_, or globals for short. - -If objects having the interface can cause protocol errors, the protocol error -codes must be defined within the interface with an enum element with its `name` -set to `"error"`. Protocol error codes are always specific to the interface of -the object referred to in -[wl_display.error](https://wayland.app/protocols/wayland#wl_display:event:error). - -The description element should be used to describe the purpose and the general -usage of the interface. - -**Required attributes** - -`name`="`cname`" - : The name of the interface. The name must start with one of the ASCII - characters a-z, A-Z, or underscore, and the following characters may - additionally include numbers 0-9. The name must be unique in the - protocol, and preferably it should also be globally unique to avoid API - conflicts in language bindings of multiple protocols. - - Protocols to be included in - [wayland-protocols](https://gitlab.freedesktop.org/wayland/wayland-protocols) - must follow the interface naming rules set there. Other protocols should use - a unique prefix for the name, e.g. referring to the owning project's name. - -`version`="`V`" - : The interface's latest version number `V` must be an integer greater than - zero. An interface element defines all versions of the interface from 1 to - `V` inclusive. The contents of each interface version are defined in each of - the request, event, enum and entry elements using the attributes `since` and - `deprecated-since`, and in the specification text. - - When an interface is extended, the version number must be incremented on all - the interfaces part of the same interface ancestry tree. The exception to - this rule are interfaces which are forever stuck to version 1, which is - usually caused by having multiple parent interfaces with independent - ancestor global interfaces. In this case, the `frozen="true"` attribute - described below should be used. - - A protocol object may have any defined version of the interface. The version - of the object is determined at runtime either by inheritance from another - protocol object or explicitly. - - It is possible for a protocol object to have a version higher than defined - by its interface. This may happen when the interface is stuck at version 1 - as per above. It may also happen when a protocol XML file has not been - thoroughly updated as required. In such cases the object shall function as - with the highest defined interface version. - -**Optional attributes** - -`frozen`="`true`" - : The interface is frozen and forever stuck at version 1. - - This attribute should be applied to interfaces that have multiple parent - interfaces with independent ancestor global interfaces, for example - `wl_buffer` and `wl_callback`. - -### request - -Parent elements: interface - -``` -request ::= (description?, arg*) -``` - -Defines a request, a message from a client to a server. Requests are always -associated with a specific protocol object. - -Requests are automatically assigned opcodes in the order they appear inside the -interface element. Therefore the only backwards-compatible way to add requests -to an interface is to add them to the end. Any event elements do not interfere -with request opcode assignments. - -The arg elements declare the request's arguments. There can be 0 to 20 arguments -for a request. The order of arg inside the request element defines the order of -the arguments on the wire. All declared arguments are mandatory, and extra -arguments are not allowed on the wire. - -The description element should be used to document the request. - -**Required attributes** - -`name`="`cname`" - : The name of the request. The name must start with one of the ASCII - characters a-z, A-Z, or underscore, and the following characters may - additionally include numbers 0-9. The name must be unique within - all requests and events in the containing interface. - - Code and language binding generators may use the name in the API they - create. The `name` of the containing interface provides the namespace for - requests. - -**Optional attributes** - -`type`="`destructor`" - : When this attribute is present, the request is a destructor: it shall - destroy the protocol object it is sent on. Protocol IPC libraries may use - this for bookkeeping protocol object lifetimes. - - Libwayland-client uses this information to ignore incoming events for - destroyed protocol objects. Such events may occur due to a natural race - condition between the client destroying a protocol object and the server - sending events before processing the destroy request. - -`since`="`S`" - : `S` must be an integer greater than zero. If `since` is not specified, - `since="1"` is assumed. - - This request was added in interface `version` `S`. The request does not - exist if the protocol object has a bound version smaller than `S`. Attempts - to use it in such a case shall raise the protocol error - `wl_display.error.invalid_method`. - -`deprecated-since`="`D`" - : `D` must be an integer greater than the value of `since`. If - `deprecated-since` is not specified, then the request is not deprecated in - any version of the containing interface. - - This request was deprecated in interface `version` `D` and above, and should - not be sent on protocol objects of such version. This is informational. - Compositors must still be prepared to handle the request unless specified - otherwise. - -### event - -Parent elements: interface - -``` -event ::= (description?, arg*) -``` - -Defines an event, a message from a server to a client. Events are always -associated with a specific protocol object. - -Events are automatically assigned opcodes in the order they appear inside the -interface element. Therefore the only backwards-compatible way to add events to -an interface is to add them to the end. Any request elements do not interfere -with event opcode assignments. - -The arg elements declare the event's arguments. There can be 0 to 20 arguments -for an event. The order of arg inside the event element defines the order of the -arguments on the wire. All declared arguments are mandatory, and extra arguments -are not allowed on the wire. - -The description element should be used to document the event. - -**Required attributes** - -`name`="`cname`" - : The name of the event. The name must start with one of the ASCII characters - a-z, A-Z, or underscore, and the following characters may additionally - include numbers 0-9. The name must be unique within all requests and events - in the containing interface. - - Code and language binding generators may use the name in the API they - create. The `name` of the containing interface provides the namespace for - events. - -**Optional attributes** - -`type`="`destructor`" - : When this attribute is present, the event is a destructor: it shall destroy - the protocol object it is sent on. Protocol IPC libraries may use this for - bookkeeping protocol object lifetimes. - - > [!WARNING] - > Destructor events are an underdeveloped feature in Wayland. They can be - > used only on client-created protocol objects, and it is the protocol - > designer's responsibility to design such a message exchange that race - > conditions cannot occur. The main problem would be a client sending a - > request at the same time as the server is sending a destructor event. The - > server will consider the protocol object to be already invalid or even - > recycled when it proceeds to process the request. This often results in - > protocol errors, but under specific conditions it might also result in - > silently incorrect behavior. - > - > Destructor events should not be used in new protocols. If a destructor - > event is necessary, the simplest way to avoid these problems is to have - > the interface not contain any requests. - -`since`="`S`" - : `S` must be an integer greater than zero. If `since` is not specified, - `since="1"` is assumed. - - This event was added in interface `version` `S`. The event does not exist if - the protocol object has a bound version smaller than `S`. - -`deprecated-since`="`D`" - : `D` must be an integer greater than the value of `since`. If - `deprecated-since` is not specified, then the event is not deprecated in any - version of the containing interface. - - This event was deprecated in interface `version` `D` and above, and should - not be sent on protocol objects of such version. This is informational. - Clients must still be prepared to receive this event unless otherwise - specified. - -### arg - -Parent elements: request, event - -``` -arg ::= description? -``` - -This element declares one argument for the request or the event. - -**Required attributes** - -`name`="`cname`" - : The name of the argument. The name must start with one of the ASCII - characters a-z, A-Z, or underscore, and the following characters may - additionally include numbers 0-9. The name must be unique within - all the arguments of the parent element. - -`type`="`T`" - : The type `T` of the argument datum must be one of: - - `int` - : 32-bit signed integer. - - `uint` - : 32-bit unsigned integer. - - `fixed` - : Signed 24.8-bit fixed-point value. - - `string` - : UTF-8 encoded string value, NUL byte terminated. Interior NUL bytes are - not allowed. - - `array` - : A byte array of arbitrary data. - - `fd` - : A file descriptor. - - The file descriptor must be open and valid on send. It is not possible - to pass a null value. - - `new_id` - : Creates a new protocol object. A request or an event may have at most - one `new_id` argument. - - If `interface` is specified, the new protocol object shall have the - specified interface, and the new object's (interface) version shall be - the version of the object on which the request or event is being sent. - - If `interface` is not specified, the request shall implicitly have two - additional arguments: A `string` for an interface name, and a `uint` for - the new object's version. Leaving the interface unspecified is reserved - for special use, - [wl_registry.bind](https://wayland.app/protocols/wayland#wl_registry:request:bind) - for example. - - > [!NOTE] - > An event argument must always specify the `new_id` `interface`. - - `object` - : Reference to an existing protocol object. - - The attribute `interface` should be specified. Otherwise IPC libraries - cannot enforce the interface, and checking the interface falls on user - code and specification text. - -**Optional attributes** - -`summary`="`summary`" - : A short (half a line at most) description. This attribute should not be used - if a description is used. - -`interface`="`iface`" - : If given, `iface` must be the `name` of some interface, and `type` of this - argument must be either `"object"` or `"new_id"`. This indicates that the - existing or new object must have the interface `iface`. Use for other - argument types is forbidden. - - > [!NOTE] - > If an interface from another protocol is used, then this creates a - > dependency between the protocols. If an application generates code for one - > protocol, then it must also generate code for all dependencies. Therefore - > this would not be a backwards compatible change. - -`allow-null`="`true`" | "`false`" - : Whether the argument value can be null on send. Defaults to `"false"`, - meaning it is illegal to send a null value. Can be used only when `type` is - `"string"` or `"object"`. - - > [!NOTE] - > Even though this attribute can be used to forbid a compositor from sending - > a null object as an event argument, an IPC library implementation may not - > protect the client from receiving a null object. This can happen with - > libwayland-client when the client has destroyed the protocol object before - > dispatching an event that referred to it in an argument. - -`enum`="`enum-cname-suffix`" - : If specified, indicates that the argument value should come from the enum - named `enum-cname-suffix`. If the enumeration is a bitfield, then `type` - must be `"uint"`. Otherwise `type` must be either `"uint"` or `"int"`. - - The name `enum-cname-suffix` refers to an enum in the same interface by - default. If it is necessary to refer to an enumeration from another - interface, the interface name can be given with a period: - - ``` - `enum`="`iface`.`enum-cname-suffix`" - ``` - - > [!NOTE] - > This attribute alone does not automatically restrict the legal values for - > this argument. If values from outside of the enumeration need to be - > forbidden, that must be specified explicitly in the documentation. - > - > A common design pattern is to have the server advertise the supported - > enumeration or bit values with events and explicitly forbid clients from - > using any other values in requests. This also requires a protocol error - > code to be specified with the error enum to be raised if a client uses an - > illegal value, see [interface](#interface). - -### enum - -Parent elements: protocol - -``` -enum ::= (description?, entry*) -``` - -This tag defines an enumeration of integer values. Enumerations are merely a -syntactic construct to give names to arbitrary integer constants. Each constant -is listed as an entry with its name. There are two types of enumerations: -regular enumerations and bitfields. - -Regular enumerations do not use `bitfield` attribute, or they set it to -`"false"`. The set of pre-defined values that belong to a regular enumeration is -exactly the set of values listed as entry elements after the protocol object -version is taken into account. See the entry attributes `since` and -`deprecated-since`. - -Bitfields set `bitfield` to `"true"`. The set of values that belong to a -bitfield enumeration are all the values that can be formed by the bitwise-or -operator from the set of values listed as entry elements like in the regular -enumeration. Usually also zero is implicitly included. - -All the values in a regular enumeration must be either signed or unsigned 32-bit -integers. All the values in a bitfield enumeration must be unsigned 32-bit -integers. - -**Required attributes** - -`name`="`cname-suffix`" - : The name of the enumeration. The name must contain only the ASCII characters - a-z, A-Z, 0-9, or underscore. The name cannot be empty. The name must be - unique within all enumerations in the containing interface. The name is used - as the namespace for all the contained entry elements. - -**Optional attributes** - -`since`="`S`" - : `S` must be an integer greater than zero. If `since` is not specified, - `since="1"` is assumed. - - This enumeration was added in interface `version` `S`. The enumeration does - not exist if the protocol object has a bound version smaller than `S`. - -`bitfield`="`true`" | "`false`" - : Specifies if this enumeration is a bitfield. Defaults to `"false"`. - -### entry - -Parent elements: enum - -``` -entry ::= description? -``` - -Defines a name for an integer constant and makes it part of the set of values of -the containing enumeration. - -**Required attributes** - -`name`="`cname-suffix`" - : The name of a value in an enumeration. The name must contain only the ASCII - characters a-z, A-Z, 0-9, or underscore. The name cannot be empty. The name - must be unique within all entry elements in the containing enum. - -`value`="`V`" - : An integer value. The value can be given in decimal, hexadecimal, or octal - representation. - -**Optional attributes** - -`summary`="`summary`" - : A short (half a line at most) description. This attribute should not be used - if a description is used. - -`since`="`S`" - : `S` must be an integer greater than zero. If `since` is not specified, - `since="1"` is assumed. - - This value was added in interface `version` `S`. - -`deprecated-since`="`D`" - : `D` must be an integer greater than the value of `since`. If - `deprecated-since` is not specified, then the value is not deprecated in any - version of the containing interface. - - This value was removed in interface `version` `D`. This does not make the - value automatically illegal to use, see [arg](#arg) attribute `enum`. diff --git a/doc/book/src/Protocol.md b/doc/book/src/Protocol.md deleted file mode 100644 index f195707e..00000000 --- a/doc/book/src/Protocol.md +++ /dev/null @@ -1,371 +0,0 @@ -# Wayland Protocol and Model of Operation - -## Basic Principles - -The Wayland protocol is an asynchronous object oriented protocol. All requests -are method invocations on some object. The requests include an object ID that -uniquely identifies an object on the server. Each object implements an interface -and the requests include an opcode that identifies which method in the interface -to invoke. - -The protocol is message-based. A message sent by a client to the server is -called request. A message from the server to a client is called event. A message -has a number of arguments, each of which has a certain type (see [Wire -Format](#wire-format) for a list of argument types). - -Additionally, the protocol can specify `enum`s which associate names to specific -numeric enumeration values. These are primarily just descriptive in nature: at -the wire format level enums are just integers. But they also serve a secondary -purpose to enhance type safety or otherwise add context for use in language -bindings or other such code. This latter usage is only supported so long as code -written before these attributes were introduced still works after; in other -words, adding an enum should not break API, otherwise it puts backwards -compatibility at risk. - -`enum`s can be defined as just a set of integers, or as bitfields. This is -specified via the `bitfield` boolean attribute in the `enum` definition. If this -attribute is true, the enum is intended to be accessed primarily using bitwise -operations, for example when arbitrarily many choices of the enum can be ORed -together; if it is false, or the attribute is omitted, then the enum arguments -are a just a sequence of numerical values. - -The `enum` attribute can be used on either `uint` or `int` arguments, however if -the `enum` is defined as a `bitfield`, it can only be used on `uint` args. - -The server sends back events to the client, each event is emitted from an -object. Events can be error conditions. The event includes the object ID and the -event opcode, from which the client can determine the type of event. Events are -generated both in response to requests (in which case the request and the event -constitutes a round trip) or spontaneously when the server state changes. - -- State is broadcast on connect, events are sent out when state changes. Clients - must listen for these changes and cache the state. There is no need (or - mechanism) to query server state. - -- The server will broadcast the presence of a number of global objects, which in - turn will broadcast their current state. - -## Code Generation - -The interfaces, requests and events are defined in -[protocol/wayland.xml](https://gitlab.freedesktop.org/wayland/wayland/-/blob/main/protocol/wayland.xml). -This xml is used to generate the function prototypes that can be used by clients -and compositors. - -The protocol entry points are generated as inline functions which just wrap the -`wl_proxy_*` functions. The inline functions aren't part of the library ABI and -language bindings should generate their own stubs for the protocol entry points -from the xml. - -## Wire Format - -The protocol is sent over a UNIX domain stream socket, where the endpoint -usually is named `wayland-0` (although it can be changed via _WAYLAND_DISPLAY_ -in the environment). Beginning in Wayland 1.15, implementations can optionally -support server socket endpoints located at arbitrary locations in the filesystem -by setting _WAYLAND_DISPLAY_ to the absolute path at which the server endpoint -listens. The socket may also be provided through file descriptor inheritance, in -which case _WAYLAND_SOCKET_ is set. - -Every message is structured as 32-bit words; values are represented in the -host's byte-order. The message header has 2 words in it: - -- The first word is the sender's object ID (32-bit). - -- The second has 2 parts of 16-bit. The upper 16-bits are the message size in - bytes, starting at the header (i.e. it has a minimum value of 8).The lower is - the request/event opcode. - -The payload describes the request/event arguments. Every argument is always -aligned to 32-bits. Where padding is required, the value of padding bytes is -undefined. There is no prefix that describes the type, but it is inferred -implicitly from the xml specification. - -The representation of argument types are as follows: - -int -uint - : The value is the 32-bit value of the signed/unsigned int. - -fixed - : Signed 24.8 decimal numbers. It is a signed decimal type which offers a sign - bit, 23 bits of integer precision and 8 bits of decimal precision. This is - exposed as an opaque struct with conversion helpers to and from double and - int on the C API side. - -string - : Starts with an unsigned 32-bit length (including null terminator), followed - by the UTF-8 encoded string contents, including terminating null byte, then - padding to a 32-bit boundary. A null value is represented with a length of - 0. Interior null bytes are not permitted. - -object - : 32-bit object ID. A null value is represented with an ID of 0. - -new_id - : The 32-bit object ID. Generally, the interface used for the new object is - inferred from the xml, but in the case where it's not specified, a new_id is - preceded by a `string` specifying the interface name, and a `uint` - specifying the version. - -array - : Starts with 32-bit array size in bytes, followed by the array contents - verbatim, and finally padding to a 32-bit boundary. - -fd - : The file descriptor is not stored in the message buffer, but in the - ancillary data of the UNIX domain socket message (msg_control). - -The protocol does not specify the exact position of the ancillary data in the -stream, except that the order of file descriptors is the same as the order of -messages and `fd` arguments within messages on the wire. - -In particular, it means that any byte of the stream, even the message header, -may carry the ancillary data with file descriptors. - -Clients and compositors should queue incoming data until they have whole -messages to process, as file descriptors may arrive earlier or later than the -corresponding data bytes. - -## Versioning - -Every interface is versioned and every protocol object implements a particular -version of its interface. For global objects, the maximum version supported by -the server is advertised with the global and the actual version of the created -protocol object is determined by the version argument passed to -wl_registry.bind(). For objects that are not globals, their version is inferred -from the object that created them. - -In order to keep things sane, this has a few implications for interface -versions: - -- The object creation hierarchy must be a tree. Otherwise, inferring object - versions from the parent object becomes a much more difficult to properly - track. - -- When the version of an interface increases, so does the version of its parent - (recursively until you get to a global interface) - -- A global interface's version number acts like a counter for all of its child - interfaces. Whenever a child interface gets modified, the global parent's - interface version number also increases (see above). The child interface then - takes on the same version number as the new version of its parent global - interface. - -To illustrate the above, consider the wl_compositor interface. It has two -children, wl_surface and wl_region. As of wayland version 1.2, wl_surface and -wl_compositor are both at version 3. If something is added to the wl_region -interface, both wl_region and wl_compositor will get bumpped to version 4. If, -afterwards, wl_surface is changed, both wl_compositor and wl_surface will be at -version 5. In this way the global interface version is used as a sort of -"counter" for all of its child interfaces. This makes it very simple to know the -version of the child given the version of its parent. The child is at the -highest possible interface version that is less than or equal to its parent's -version. - -It is worth noting a particular exception to the above versioning scheme. The -wl_display (and, by extension, wl_registry) interface cannot change because it -is the core protocol object and its version is never advertised nor is there a -mechanism to request a different version. - -## Connect Time - -There is no fixed connection setup information, the server emits multiple events -at connect time, to indicate the presence and properties of global objects: -outputs, compositor, input devices. - -## Security and Authentication - -- mostly about access to underlying buffers, need new drm auth mechanism (the - grant-to ioctl idea), need to check the cmd stream? - -- getting the server socket depends on the compositor type, could be a system - wide name, through fd passing on the session dbus. or the client is forked by - the compositor and the fd is already opened. - -## Creating Objects - -Each object has a unique ID. The IDs are allocated by the entity creating the -object (either client or server). IDs allocated by the client are in the range -[1, 0xfeffffff] while IDs allocated by the server are in the range [0xff000000, -0xffffffff]. The 0 ID is reserved to represent a null or non-existent object. -For efficiency purposes, the IDs are densely packed in the sense that the ID N -will not be used until N-1 has been used. This ordering is not merely a -guideline, but a strict requirement, and there are implementations of the -protocol that rigorously enforce this rule, including the ubiquitous libwayland. - -## Compositor - -The compositor is a global object, advertised at connect time. - -See [wl_compositor](https://wayland.app/protocols/wayland#wl_compositor) for the -protocol description. - -## Surfaces - -A surface manages a rectangular grid of pixels that clients create for -displaying their content to the screen. Clients don't know the global position -of their surfaces, and cannot access other clients' surfaces. - -Once the client has finished writing pixels, it 'commits' the buffer; this -permits the compositor to access the buffer and read the pixels. When the -compositor is finished, it releases the buffer back to the client. - -See [wl_surface](https://wayland.app/protocols/wayland#wl_surface) for the -protocol description. - -## Input - -A seat represents a group of input devices including mice, keyboards and -touchscreens. It has a keyboard and pointer focus. Seats are global objects. -Pointer events are delivered in surface-local coordinates. - -The compositor maintains an implicit grab when a button is pressed, to ensure -that the corresponding button release event gets delivered to the same surface. -But there is no way for clients to take an explicit grab. Instead, surfaces can -be mapped as 'popup', which combines transient window semantics with a pointer -grab. - -To avoid race conditions, input events that are likely to trigger further -requests (such as button presses, key events, pointer motions) carry serial -numbers, and requests such as wl_surface.set_popup require that the serial -number of the triggering event is specified. The server maintains a -monotonically increasing counter for these serial numbers. - -Input events also carry timestamps with millisecond granularity. Their base is -undefined, so they can't be compared against system time (as obtained with -clock_gettime or gettimeofday). They can be compared with each other though, and -for instance be used to identify sequences of button presses as double or triple -clicks. - -See [wl_seat](https://wayland.app/protocols/wayland#wl_seat) for the protocol -description. - -Talk about: - -- keyboard map, change events - -- xkb on Wayland - -- multi pointer Wayland - -A surface can change the pointer image when the surface is the pointer focus of -the input device. Wayland doesn't automatically change the pointer image when a -pointer enters a surface, but expects the application to set the cursor it wants -in response to the pointer focus and motion events. The rationale is that a -client has to manage changing pointer images for UI elements within the surface -in response to motion events anyway, so we'll make that the only mechanism for -setting or changing the pointer image. If the server receives a request to set -the pointer image after the surface loses pointer focus, the request is ignored. -To the client this will look like it successfully set the pointer image. - -Setting the pointer image to NULL causes the cursor to be hidden. - -The compositor will revert the pointer image back to a default image when no -surface has the pointer focus for that device. - -What if the pointer moves from one window which has set a special pointer image -to a surface that doesn't set an image in response to the motion event? The new -surface will be stuck with the special pointer image. We can't just revert the -pointer image on leaving a surface, since if we immediately enter a surface that -sets a different image, the image will flicker. If a client does not set a -pointer image when the pointer enters a surface, the pointer stays with the -image set by the last surface that changed it, possibly even hidden. Such a -client is likely just broken. - -## Output - -An output is a global object, advertised at connect time or as it comes and -goes. - -See [wl_output](https://wayland.app/protocols/wayland#wl_output) for the -protocol description. - -- laid out in a big (compositor) coordinate system - -- basically xrandr over Wayland - -- geometry needs position in compositor coordinate system - -- events to advertise available modes, requests to move and change modes - -## Data sharing between clients - -The Wayland protocol provides clients a mechanism for sharing data that allows -the implementation of copy-paste and drag-and-drop. The client providing the -data creates a `wl_data_source` object and the clients obtaining the data will -see it as `wl_data_offer` object. This interface allows the clients to agree on -a mutually supported mime type and transfer the data via a file descriptor that -is passed through the protocol. - -The next section explains the negotiation between data source and data offer -objects. [Data devices](#data-devices) explains how these objects are created -and passed to different clients using the `wl_data_device` interface that -implements copy-paste and drag-and-drop support. - -See [wl_data_offer](https://wayland.app/protocols/wayland#wl_data_offer), -[wl_data_source](https://wayland.app/protocols/wayland#wl_data_source), -[wl_data_device](https://wayland.app/protocols/wayland#wl_data_device) and -[wl_data_device_manager](https://wayland.app/protocols/wayland#wl_data_device_manager) -for protocol descriptions. - -MIME is defined in RFC's 2045-2049. A [registry of MIME -types](https://www.iana.org/assignments/media-types/media-types.xhtml) is -maintained by the Internet Assigned Numbers Authority (IANA). - -### Data negotiation - -A client providing data to other clients will create a `wl_data_source` object -and advertise the mime types for the formats it supports for that data through -the `wl_data_source.offer` request. On the receiving end, the data offer object -will generate one `wl_data_offer.offer` event for each supported mime type. - -The actual data transfer happens when the receiving client sends a -`wl_data_offer.receive` request. This request takes a mime type and a file -descriptor as arguments. This request will generate a `wl_data_source.send` -event on the sending client with the same arguments, and the latter client is -expected to write its data to the given file descriptor using the chosen mime -type. - -### Data devices - -Data devices glue data sources and offers together. A data device is associated -with a `wl_seat` and is obtained by the clients using the -`wl_data_device_manager` factory object, which is also responsible for creating -data sources. - -Clients are informed of new data offers through the `wl_data_device.data_offer` -event. After this event is generated the data offer will advertise the available -mime types. New data offers are introduced prior to their use for copy-paste or -drag-and-drop. - -#### Selection - -Each data device has a selection data source. Clients create a data source -object using the device manager and may set it as the current selection for a -given data device. Whenever the current selection changes, the client with -keyboard focus receives a `wl_data_device.selection` event. This event is also -generated on a client immediately before it receives keyboard focus. - -The data offer is introduced with `wl_data_device.data_offer` event before the -selection event. - -#### Drag and Drop - -A drag-and-drop operation is started using the `wl_data_device.start_drag` -request. This requests causes a pointer grab that will generate enter, motion -and leave events on the data device. A data source is supplied as argument to -start_drag, and data offers associated with it are supplied to clients surfaces -under the pointer in the `wl_data_device.enter` event. The data offer is -introduced to the client prior to the enter event with the -`wl_data_device.data_offer` event. - -Clients are expected to provide feedback to the data sending client by calling -the `wl_data_offer.accept` request with a mime type it accepts. If none of the -advertised mime types is supported by the receiving client, it should supply -NULL to the accept request. The accept request causes the sending client to -receive a `wl_data_source.target` event with the chosen mime type. - -When the drag ends, the receiving client receives a `wl_data_device.drop` event -at which it is expected to transfer the data using the `wl_data_offer.receive` -request. diff --git a/doc/book/src/SUMMARY.md b/doc/book/src/SUMMARY.md deleted file mode 100644 index 713b4e02..00000000 --- a/doc/book/src/SUMMARY.md +++ /dev/null @@ -1,12 +0,0 @@ -# Summary - -[Foreword](Foreword.md) - -- [Introduction](./Introduction.md) -- [Types of Compositors](./Compositors.md) -- [Wayland Architecture](./Architecture.md) -- [Wayland Protocol and Model of Operation](./Protocol.md) -- [Message Definition Language](./Message_XML.md) -- [X11 Application Support](./Xwayland.md) -- [Content Updates](./Content_Updates.md) -- [Color management](./Color.md) diff --git a/doc/book/src/Xwayland.md b/doc/book/src/Xwayland.md deleted file mode 100644 index dd7f9f77..00000000 --- a/doc/book/src/Xwayland.md +++ /dev/null @@ -1,120 +0,0 @@ -# X11 Application Support - -## Introduction - -Being able to run existing X11 applications is crucial for the adoption of -Wayland, especially on desktops, as there will always be X11 applications that -have not been or cannot be converted into Wayland applications, and throwing -them all away would be prohibitive. Therefore a Wayland compositor often needs -to support running X11 applications. - -X11 and Wayland are different enough that there is no "simple" way to translate -between them. Most of X11 is uninteresting to a Wayland compositor. That, -combined with the gigantic implementation effort needed to support X11, makes it -intractable to just write X11 support directly in a Wayland compositor. The -implementation would be nothing short of a real X11 server. - -Therefore, Wayland compositors should use Xwayland, the X11 server that lives in -the Xorg server source code repository and shares most of the implementation -with the Xorg server. Xwayland is a complete X11 server, just like Xorg is, but -instead of driving the displays and opening input devices, it acts as a Wayland -client. The rest of this chapter talks about how Xwayland works. - -For integration and architecture reasons, while Xwayland is a Wayland client of -the Wayland compositor, the Wayland compositor is an X11 client of Xwayland. -This circular dependency requires special care from the Wayland compositor. - -## Two Modes for Foreign Windows - -In general, windows from a foreign window system can be presented in one of two -ways: rootless and rootful (not rootless). - -In rootful mode, the foreign window system as a whole is represented as a window -(or more) of its own. You have a native window, inside which all the foreign -windows are. The advantage of this approach in Xwayland's case is that you can -run your favourite X11 window manager to manage your X11 applications. The -disadvantage is that the foreign windows do not integrate with the native -desktop. Therefore this mode is not usually used. - -In rootless mode, each foreign window is a first-class resident among the native -windows. Foreign windows are not confined inside a native window but act as if -they were native windows. The advantage is that one can freely stack and mix -native and foreign windows, which is not possible in rootful mode. The -disadvantage is that this mode is harder to implement and fundamental -differences in window systems may prevent some things from working. With -rootless Xwayland, the Wayland compositor must take the role as the X11 window -manager, and one cannot use any other X11 window manager in its place. - -This chapter concentrates on the rootless mode, and ignores the rootful mode. - -## Architecture - -A Wayland compositor usually takes care of launching Xwayland. Xwayland works in -cooperation with a Wayland compositor as follows: - -**Xwayland architecture diagram** - -![](images/xwayland-architecture.png) - -An X11 application connects to Xwayland just like it would connect to any X -server. Xwayland processes all the X11 requests. On the other end, Xwayland is a -Wayland client that connects to the Wayland compositor. - -The X11 window manager (XWM) is an integral part of the Wayland compositor. XWM -uses the usual X11 window management protocol to manage all X11 windows in -Xwayland. Most importantly, XWM acts as a bridge between Xwayland window state -and the Wayland compositor's window manager (WWM). This way WWM can manage all -windows, both native Wayland and X11 (Xwayland) windows. This is very important -for a coherent user experience. - -Since Xwayland uses Wayland for input and output, it does not have any use for -the device drivers that Xorg uses. None of the xf86-video-* or xf86-input-* -modules are used. There also is no configuration file for the Xwayland server. -For optional hardware accelerated rendering, Xwayland uses GLAMOR. - -A Wayland compositor usually spawns only one Xwayland instance. This is because -many X11 applications assume they can communicate with other X11 applications -through the X server, and this requires a shared X server instance. This also -means that Xwayland does not protect nor isolate X11 clients from each other, -unless the Wayland compositor specifically chooses to break the X11 client -intercommunications by spawning application specific Xwayland instances. X11 -clients are naturally isolated from Wayland clients. - -Xwayland compatibility compared to a native X server will probably never reach -100%. Desktop environment (DE) components, specifically X11 window managers, are -practically never supported. An X11 window manager would not know about native -Wayland windows, so it could manage only X11 windows. On the other hand, there -must be an XWM that reserves the exclusive window manager role so that the -Wayland compositor could show the X11 windows appropriately. For other DE -components, like pagers and panels, adding the necessary interfaces to support -them in WWM through XWM is often considered not worthwhile. - -## X Window Manager (XWM) - -From the X11 point of view, the X window manager (XWM) living inside a Wayland -compositor is just like any other window manager. The difference is mostly in -which process it resides in, and the few extra conventions in the X11 protocol -to support Wayland window management (WWM) specifically. - -There are two separate asynchronous communication channels between Xwayland and -a Wayland compositor: one uses the Wayland protocol, and the other one, solely -for XWM, uses X11 protocol. This setting demands great care from the XWM -implementation to avoid (random) deadlocks with Xwayland. It is often nearly -impossible to prove that synchronous or blocking X11 calls from XWM cannot cause -a deadlock, and therefore it is strongly recommended to make all X11 -communications asynchronous. All Wayland communications are already asynchronous -by design. - -### Window identification - -In Xwayland, an X11 window may have a corresponding wl_surface object in -Wayland. The wl_surface object is used for input and output: it is referenced by -input events and used to provide the X11 window content to the Wayland -compositor. The X11 window and the wl_surface live in different protocol -streams, and they need to be matched for XWM to do its job. - -When Xwayland creates a wl_surface on Wayland, it will also send an X11 -ClientMessage of type atom "WL_SURFACE_ID" to the X11 window carrying the -wl_surface Wayland object ID as the first 32-bit data element. This is how XWM -can associate a wl_surface with an X11 window. Note that the request to create a -wl_surface and the ID message may arrive in any order in the Wayland compositor. diff --git a/doc/book/src/images/content-updates/content-update-legend.png b/doc/book/src/images/content-updates/content-update-legend.png deleted file mode 100644 index 84f12e76..00000000 Binary files a/doc/book/src/images/content-updates/content-update-legend.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-desynchronized-state-1.png b/doc/book/src/images/content-updates/simple-desynchronized-state-1.png deleted file mode 100644 index d319ac25..00000000 Binary files a/doc/book/src/images/content-updates/simple-desynchronized-state-1.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-desynchronized-state-2.png b/doc/book/src/images/content-updates/simple-desynchronized-state-2.png deleted file mode 100644 index ecd284cd..00000000 Binary files a/doc/book/src/images/content-updates/simple-desynchronized-state-2.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-desynchronized-state-3.png b/doc/book/src/images/content-updates/simple-desynchronized-state-3.png deleted file mode 100644 index 73da57f8..00000000 Binary files a/doc/book/src/images/content-updates/simple-desynchronized-state-3.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-desynchronized-state-4.png b/doc/book/src/images/content-updates/simple-desynchronized-state-4.png deleted file mode 100644 index 83dcc063..00000000 Binary files a/doc/book/src/images/content-updates/simple-desynchronized-state-4.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-desynchronized-state-5.png b/doc/book/src/images/content-updates/simple-desynchronized-state-5.png deleted file mode 100644 index d4e42d8f..00000000 Binary files a/doc/book/src/images/content-updates/simple-desynchronized-state-5.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-desynchronized-state-6.png b/doc/book/src/images/content-updates/simple-desynchronized-state-6.png deleted file mode 100644 index ebb88d81..00000000 Binary files a/doc/book/src/images/content-updates/simple-desynchronized-state-6.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-synchronized-state-1.png b/doc/book/src/images/content-updates/simple-synchronized-state-1.png deleted file mode 100644 index be101446..00000000 Binary files a/doc/book/src/images/content-updates/simple-synchronized-state-1.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-synchronized-state-2.png b/doc/book/src/images/content-updates/simple-synchronized-state-2.png deleted file mode 100644 index af6c64ff..00000000 Binary files a/doc/book/src/images/content-updates/simple-synchronized-state-2.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-synchronized-state-3.png b/doc/book/src/images/content-updates/simple-synchronized-state-3.png deleted file mode 100644 index 7ca9ae69..00000000 Binary files a/doc/book/src/images/content-updates/simple-synchronized-state-3.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-synchronized-state-4.png b/doc/book/src/images/content-updates/simple-synchronized-state-4.png deleted file mode 100644 index e8b9b3db..00000000 Binary files a/doc/book/src/images/content-updates/simple-synchronized-state-4.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/simple-synchronized-state-5.png b/doc/book/src/images/content-updates/simple-synchronized-state-5.png deleted file mode 100644 index 21c3414a..00000000 Binary files a/doc/book/src/images/content-updates/simple-synchronized-state-5.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case1-1.png b/doc/book/src/images/content-updates/sync-subsurf-case1-1.png deleted file mode 100644 index 1f7ff8e4..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case1-1.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case1-2.png b/doc/book/src/images/content-updates/sync-subsurf-case1-2.png deleted file mode 100644 index 6839b679..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case1-2.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case1-3.png b/doc/book/src/images/content-updates/sync-subsurf-case1-3.png deleted file mode 100644 index 9810a028..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case1-3.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case1-4.png b/doc/book/src/images/content-updates/sync-subsurf-case1-4.png deleted file mode 100644 index bf3c04bc..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case1-4.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case1-5.png b/doc/book/src/images/content-updates/sync-subsurf-case1-5.png deleted file mode 100644 index 1b2ebc3b..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case1-5.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case2-1.png b/doc/book/src/images/content-updates/sync-subsurf-case2-1.png deleted file mode 100644 index 25408cfc..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case2-1.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case2-2.png b/doc/book/src/images/content-updates/sync-subsurf-case2-2.png deleted file mode 100644 index 63ea066c..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case2-2.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-subsurf-case2-3.png b/doc/book/src/images/content-updates/sync-subsurf-case2-3.png deleted file mode 100644 index 3948988d..00000000 Binary files a/doc/book/src/images/content-updates/sync-subsurf-case2-3.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-to-desync-subsurf-1.png b/doc/book/src/images/content-updates/sync-to-desync-subsurf-1.png deleted file mode 100644 index 3a56f260..00000000 Binary files a/doc/book/src/images/content-updates/sync-to-desync-subsurf-1.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-to-desync-subsurf-2.png b/doc/book/src/images/content-updates/sync-to-desync-subsurf-2.png deleted file mode 100644 index 9cb6210c..00000000 Binary files a/doc/book/src/images/content-updates/sync-to-desync-subsurf-2.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-to-desync-subsurf-3.png b/doc/book/src/images/content-updates/sync-to-desync-subsurf-3.png deleted file mode 100644 index 34bf7475..00000000 Binary files a/doc/book/src/images/content-updates/sync-to-desync-subsurf-3.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-to-desync-transition-1.png b/doc/book/src/images/content-updates/sync-to-desync-transition-1.png deleted file mode 100644 index cd69f3c3..00000000 Binary files a/doc/book/src/images/content-updates/sync-to-desync-transition-1.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-to-desync-transition-2.png b/doc/book/src/images/content-updates/sync-to-desync-transition-2.png deleted file mode 100644 index 677a0cdb..00000000 Binary files a/doc/book/src/images/content-updates/sync-to-desync-transition-2.png and /dev/null differ diff --git a/doc/book/src/images/content-updates/sync-to-desync-transition-3.png b/doc/book/src/images/content-updates/sync-to-desync-transition-3.png deleted file mode 100644 index bdfdb8eb..00000000 Binary files a/doc/book/src/images/content-updates/sync-to-desync-transition-3.png and /dev/null differ diff --git a/doc/book/src/images/wayland-architecture.png b/doc/book/src/images/wayland-architecture.png deleted file mode 100644 index 2be7da00..00000000 Binary files a/doc/book/src/images/wayland-architecture.png and /dev/null differ diff --git a/doc/book/src/images/x-architecture.png b/doc/book/src/images/x-architecture.png deleted file mode 100644 index 549e262d..00000000 Binary files a/doc/book/src/images/x-architecture.png and /dev/null differ diff --git a/doc/book/src/images/xwayland-architecture.png b/doc/book/src/images/xwayland-architecture.png deleted file mode 100644 index f24dc183..00000000 Binary files a/doc/book/src/images/xwayland-architecture.png and /dev/null differ diff --git a/doc/doxygen/.gitignore b/doc/doxygen/.gitignore index d68d6fce..5f825986 100644 --- a/doc/doxygen/.gitignore +++ b/doc/doxygen/.gitignore @@ -1,3 +1,2 @@ -doxygen_sqlite3.db -html/ wayland.doxygen +xml/ diff --git a/doc/doxygen/Makefile.am b/doc/doxygen/Makefile.am new file mode 100644 index 00000000..83622af6 --- /dev/null +++ b/doc/doxygen/Makefile.am @@ -0,0 +1,53 @@ + +noinst_DATA = xml/client/index.xml xml/server/index.xml +dist_noinst_DATA = wayland.doxygen.in + +scanned_src_files_shared = \ + $(top_srcdir)/src/wayland-util.c \ + $(top_srcdir)/src/wayland-util.h + +scanned_src_files_client = \ + $(scanned_src_files_shared) \ + $(top_srcdir)/src/wayland-client.c \ + $(top_srcdir)/src/wayland-client.h + +scanned_src_files_server = \ + $(scanned_src_files_shared) \ + $(top_srcdir)/src/wayland-server.c \ + $(top_srcdir)/src/wayland-server.h \ + $(top_srcdir)/src/wayland-shm.c + +# find all man/man3/wl_foo.3 pages +# for this to work, we need to create them before the man target (hence +# all-local below) +dist_man3_MANS = $(shell test -d man && find man/man3 -name "wl_*.3" -printf "man/man3/%P\n") + +xml/client/index.xml: $(scanned_src_files_client) wayland.doxygen + $(AM_V_GEN)$(MKDIR_P) xml/client && \ + (cat wayland.doxygen; \ + echo "GENERATE_XML=YES"; \ + echo "XML_OUTPUT=xml/client"; \ + echo "INPUT= $(scanned_src_files_client)"; \ + ) | doxygen - +xml/server/index.xml: $(scanned_src_files_server) wayland.doxygen + $(AM_V_GEN)$(MKDIR_P) xml/server && \ + (cat wayland.doxygen; \ + echo "GENERATE_XML=YES"; \ + echo "XML_OUTPUT=xml/server"; \ + echo "INPUT= $(scanned_src_files_server)"; \ + ) | doxygen - + +man/man3/wl_display.3: $(scanned_src_files_client) $(scanned_src_files_server) + $(AM_V_GEN)(cat wayland.doxygen; \ + echo "GENERATE_MAN=YES"; \ + echo "MAN_OUTPUT=man"; \ + echo "JAVADOC_AUTOBRIEF=NO"; \ + echo "INPUT= $^"; \ + ) | doxygen - + +# there is no man-local +all-local: man/man3/wl_display.3 + +clean-local: + rm -rf xml/ + rm -rf man/ diff --git a/doc/doxygen/gen-doxygen.py b/doc/doxygen/gen-doxygen.py deleted file mode 100755 index 1bb07e57..00000000 --- a/doc/doxygen/gen-doxygen.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import datetime -import errno -import os -import subprocess -import sys - -# Custom configuration for each documentation format -doxygen_templates = { - 'xml': [ - 'GENERATE_XML=YES\n', - 'XML_OUTPUT={format}/{section}\n', - 'INPUT= {files}\n', - ], - 'html': [ - 'GENERATE_HTML=YES\n', - 'HTML_OUTPUT={format}/{section}\n', - 'PROJECT_NAME=\"Wayland {section} API\"\n', - 'INPUT= {files}\n', - ], - 'man': [ - 'GENERATE_MAN=YES\n', - 'MAN_OUTPUT={format}\n', - 'MAN_SUBDIR=.\n', - 'JAVADOC_AUTOBRIEF=NO\n', - 'INPUT= {files}\n', - ], -} - -def load_doxygen_file(doxyfile): - with open(doxyfile, 'r') as f: - res = f.readlines() - return res - -def get_template(outformat): - for (k,v) in doxygen_templates.items(): - if outformat.startswith(k): - return v - -def gen_doxygen_file(data, outformat, section, files): - for l in get_template(outformat): - data.append(l.format(format=outformat, section=section, files=' '.join(files))) - return data - -parser = argparse.ArgumentParser(description='Generate docs with Doxygen') -parser.add_argument('doxygen_file', - help='The doxygen file to use') -parser.add_argument('files', - help='The list of files to parse', - metavar='FILES', - nargs='+') -parser.add_argument('--builddir', - help='The build directory', - metavar='DIR', - default='.') -parser.add_argument('--section', - help='The section to build', - metavar='NAME', - default='Client') -parser.add_argument('--output-format', - help='The output format: xml, html, man', - metavar='FORMAT', - default='xml') -parser.add_argument('--stamp', - help='Stamp file to output', - metavar='STAMP_FILE', - nargs='?', - type=argparse.FileType('w')) - -args = parser.parse_args() - -# Merge the doxyfile with our custom templates -conf = load_doxygen_file(args.doxygen_file) -conf = gen_doxygen_file(conf, args.output_format, args.section, args.files) - -# Doxygen is not clever enough to create the directories it -# needs beforehand -try: - os.makedirs(os.path.join(args.builddir, args.output_format)) -except OSError as e: - if e.errno != errno.EEXIST: - raise e - -# Run Doxygen with the generated doxyfile -cmd = subprocess.Popen(['doxygen', '-'], stdin=subprocess.PIPE) -cmd.stdin.write(''.join(conf).encode('utf-8')) -cmd.stdin.close() -if cmd.wait() != 0: - sys.exit(1) - -# This is a bit of a hack; Doxygen will generate way more files than we -# want to install, but there's no way to know how many at configuration -# time. Since we want to install only the wl_* man pages anyway, we can -# delete the other files and let Meson install the whole man3 subdirectory -if args.output_format.startswith('man'): - manpath = os.path.join(args.builddir, args.output_format) - for filename in os.listdir(manpath): - full_path = os.path.join(manpath, filename) - if not filename.startswith('wl_'): - os.remove(full_path) - -if args.stamp: - args.stamp.write(str(datetime.datetime.now())) diff --git a/doc/doxygen/mainpage.dox b/doc/doxygen/mainpage.dox deleted file mode 100644 index 44332cd8..00000000 --- a/doc/doxygen/mainpage.dox +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @mainpage - * Wayland protocol API documentation. - * - * This documentation is available for the Server- and the Client-side APIs. - * - * - Server-side API - * - Client-side API - * - Cursor helper library API - * - * Further documentation about the architecture and principles of Wayland is - * available on the - * website. - * - * @section ifaces Interfaces - * For the list of available interfaces, please see the - * modules list. - * - * @section protocols Protocols - * For the list of protocols, please see the - * Related Pages. - * - */ diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build deleted file mode 100644 index 551bd4b4..00000000 --- a/doc/doxygen/meson.build +++ /dev/null @@ -1,105 +0,0 @@ -# Here be dragons - -doxygen_conf = configuration_data() -doxygen_conf.set('VERSION', meson.project_version()) -doxygen_conf.set('top_builddir', meson.project_build_root()) -wayland_doxygen = configure_file( - input: 'wayland.doxygen.in', - output: 'wayland.doxygen', - configuration: doxygen_conf, -) - -shared_files = files([ - '../../src/wayland-util.h', -]) - -client_files = files([ - '../../src/wayland-client.c', - '../../src/wayland-client.h', - '../../src/wayland-client-core.h', -]) - -server_files = files([ - '../../src/event-loop.c', - '../../src/wayland-server.c', - '../../src/wayland-server.h', - '../../src/wayland-server-core.h', - '../../src/wayland-shm.c', -]) - -cursor_files = files([ - '../../cursor/wayland-cursor.c', - '../../cursor/wayland-cursor.h', -]) - -extra_client_files = [ - 'mainpage.dox', - wayland_client_protocol_h, -] - -extra_server_files = [ - 'mainpage.dox', - wayland_server_protocol_h, -] - -extra_cursor_files = [ - 'mainpage.dox', -] - -gen_doxygen = find_program('gen-doxygen.py') - -subdir('xml') - -formats = { - 'html': { - 'Client': shared_files + client_files + extra_client_files, - 'Server': shared_files + server_files + extra_server_files, - 'Cursor': shared_files + cursor_files + extra_cursor_files, - }, -} - -foreach f_name, sections: formats - foreach s_name, s_files: sections - t_name = '@0@-@1@-doc'.format(f_name, s_name) - - # We do not really need an output file, but Meson - # will complain if one is not set, so we use a - # dummy 'stamp' file - stamp = join_paths(meson.current_build_dir(), '@0@.stamp'.format(t_name)) - custom_target( - t_name, - command: [ - gen_doxygen, - # XXX pass doxygen path as argument - '--builddir=@OUTDIR@', - '--section=@0@'.format(s_name), - '--output-format=@0@'.format(f_name), - '--stamp=@0@'.format(stamp), - wayland_doxygen, - '@INPUT@', - ], - input: s_files, - output: '@0@.stamp'.format(t_name), - build_by_default: true, - ) - endforeach -endforeach - -man_files = shared_files + server_files + client_files + cursor_files -stamp = join_paths(meson.current_build_dir(), 'man3.stamp') -custom_target( - 'man-pages-3', - command: [ - gen_doxygen, - '--builddir=@OUTDIR@', - '--output-format=man3', - '--stamp=@0@'.format(stamp), - wayland_doxygen, - '@INPUT@', - ], - input: man_files, - output: 'man3', - build_by_default: true, - install: true, - install_dir: join_paths(get_option('prefix'), get_option('mandir')), -) diff --git a/doc/doxygen/wayland.doxygen.in b/doc/doxygen/wayland.doxygen.in index ac4207d4..e64512f5 100644 --- a/doc/doxygen/wayland.doxygen.in +++ b/doc/doxygen/wayland.doxygen.in @@ -1,22 +1,1736 @@ -# Wayland-specific overrides +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + PROJECT_NAME = "Wayland" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + PROJECT_NUMBER = @VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + OUTPUT_DIRECTORY = @top_builddir@/doc/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + TAB_SIZE = 8 -QUIET = YES -GENERATE_LATEX = NO -MAN_LINKS = NO -PREDEFINED = WL_EXPORT= \ - WL_PRINTF(x,y)= -MACRO_EXPANSION = YES -EXPAND_ONLY_PREDEF = YES -DOT_MULTI_TARGETS = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + ALIASES += comment{1}="/* \1 */" -OPTIMIZE_OUTPUT_FOR_C = YES -EXTRACT_ALL = YES -EXTRACT_STATIC = YES -# These must be set in the Makefile + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + GENERATE_HTML = NO -GENERATE_XML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = WL_EXPORT= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/doc/doxygen/xml/Client/meson.build b/doc/doxygen/xml/Client/meson.build deleted file mode 100644 index e51fccb6..00000000 --- a/doc/doxygen/xml/Client/meson.build +++ /dev/null @@ -1,17 +0,0 @@ -tgt = custom_target( - 'xml-Client-doc', - command: [ - gen_doxygen, - # XXX pass doxygen path as argument - '--builddir=@OUTDIR@', - '--section=Client', - '--output-format=xml', - wayland_doxygen, - '@INPUT@', - ], - input: [ shared_files, client_files ], - output: [ 'combine.xslt', 'index.xml' ], -) - -doxygen_Client_combine_xslt = tgt[0] -doxygen_Client_index_xml = tgt[1] diff --git a/doc/doxygen/xml/Server/meson.build b/doc/doxygen/xml/Server/meson.build deleted file mode 100644 index 5df97440..00000000 --- a/doc/doxygen/xml/Server/meson.build +++ /dev/null @@ -1,17 +0,0 @@ -tgt = custom_target( - 'xml-Server-doc', - command: [ - gen_doxygen, - # XXX pass doxygen path as argument - '--builddir=@OUTDIR@', - '--section=Server', - '--output-format=xml', - wayland_doxygen, - '@INPUT@', - ], - input: [ shared_files, server_files ], - output: [ 'combine.xslt', 'index.xml' ], -) - -doxygen_Server_combine_xslt = tgt[0] -doxygen_Server_index_xml = tgt[1] diff --git a/doc/doxygen/xml/meson.build b/doc/doxygen/xml/meson.build deleted file mode 100644 index 479af8e7..00000000 --- a/doc/doxygen/xml/meson.build +++ /dev/null @@ -1,2 +0,0 @@ -subdir('Client') -subdir('Server') diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am new file mode 100644 index 00000000..41665eb2 --- /dev/null +++ b/doc/man/Makefile.am @@ -0,0 +1,51 @@ +# +# This generates man-pages out of the Docbook XML files. Simply add your files +# to the $MANPAGES array. If aliases are created, please add them to the +# MANPAGES_ALIASES array so they get installed correctly. +# + +MANPAGES = \ + wl_display_connect.3 +MANPAGES_ALIASES = \ + wl_display_connect_to_fd.3 + +XML_FILES = \ + ${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubst %.7,%.xml,$(MANPAGES)}}}} +CLEANFILES = +EXTRA_DIST = $(XML_FILES) + +if HAVE_XSLTPROC +if HAVE_MANPAGES_STYLESHEET + +CLEANFILES += $(MANPAGES) $(MANPAGES_ALIASES) +EXTRA_DIST += $(MANPAGES) $(MANPAGES_ALIASES) +dist_man_MANS = $(MANPAGES) $(MANPAGES_ALIASES) + +XSLTPROC_FLAGS = \ + --stringparam man.authors.section.enabled 0 \ + --stringparam man.copyright.section.enabled 0 \ + --stringparam funcsynopsis.style ansi \ + --stringparam man.output.quietly 1 \ + --nonet + +XSLTPROC_PROCESS_MAN = \ + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ + $(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(MANPAGES_STYLESHEET) $< && \ + $(SED) -i -e 's/^\.so \(.*\)\.\(.\)$$/\.so man\2\/\1\.\2/' $(MANPAGES_ALIASES) + +%.1: %.xml + $(XSLTPROC_PROCESS_MAN) + +%.3: %.xml + $(XSLTPROC_PROCESS_MAN) + +%.5: %.xml + $(XSLTPROC_PROCESS_MAN) + +%.7: %.xml + $(XSLTPROC_PROCESS_MAN) + +wl_display_connect_to_fd.3: wl_display_connect.3 + +endif # HAVE_MANPAGES_STYLESHEET +endif # HAVE_XSLTPROC diff --git a/doc/man/wl_display_connect.xml b/doc/man/wl_display_connect.xml new file mode 100644 index 00000000..7e6e05c6 --- /dev/null +++ b/doc/man/wl_display_connect.xml @@ -0,0 +1,88 @@ + + + + + + + + wl_display_connect + wayland-client + September 2012 + + + Developer + David + Herrmann + dh.herrmann@googlemail.com + + + + + + wl_display_connect + 3 + + + + wl_display_connect + wl_display_connect_to_fd + Connect to a Wayland socket + + + + + + #include <wayland-client.h> + + + struct wl_display *wl_display_connect + const char *name + + + + struct wl_display *wl_display_connect_to_fd + int fd + + + + + + + Description + wl_display_connect connects to a Wayland socket + that was previously opened by a Wayland server. The server socket must + be placed in XDG_RUNTIME_DIR for this function to + find it. The name argument specifies the name of + the socket or NULL to use the default (which is + "wayland-0"). The environment variable + WAYLAND_DISPLAY replaces the default value. If + WAYLAND_SOCKET is set, this function behaves like + wl_display_connect_to_fd with the file-descriptor + number taken from the environment variable. + + wl_display_connect_to_fd connects to a Wayland + socket with an explicit file-descriptor. The file-descriptor is passed + as argument fd. + + + + Return Value + wl_display_connect and + wl_display_connect_to_fd return a new display + context object or NULL on failure. errno is set + correspondingly. + + + + See Also + + wayland-client7, + wl_display_disconnect3, + wl_display_iterate3 + + + diff --git a/doc/meson.build b/doc/meson.build deleted file mode 100644 index b9f6fcba..00000000 --- a/doc/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -if not get_option('libraries') - error('-Ddocumentation=true requires -Dlibraries=true') -endif - -dot = find_program('dot') -doxygen = find_program('doxygen') -xsltproc = find_program('xsltproc') -xmlto = find_program('xmlto') -mdbook = find_program('mdbook') - -cmd = run_command(doxygen, '--version', check: true) -message('doxygen: ' + cmd.stdout().strip()) -vers = cmd.stdout().strip() -if vers.version_compare('< 1.6.0') - error('Doxygen 1.6 or later is required for building documentation, found @0@.'.format(vers)) -endif - -cmd = run_command(dot, '-V', check: true) -message('dot: ' + cmd.stderr().strip()) -vers = cmd.stderr().split('version')[1].strip().split(' ')[0] -if vers.version_compare('< 2.26.0') - error('Dot (Graphviz) 2.26 or later is required for building documentation, found @0@.'.format(vers)) -endif - -manpage_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl' -cmd = run_command(xsltproc, '--nonet', manpage_xsl, check: false) -if cmd.returncode() != 0 - error('The style sheet for man pages providing "@0@" was not found.'.format(manpage_xsl)) -endif - -publican_install_prefix = join_paths( - get_option('prefix'), - get_option('datadir'), - 'doc', - meson.project_name(), - 'Wayland', 'en-US' -) - -publican_html_dir = 'html' - -subdir('doxygen') -subdir('publican') -subdir('book') diff --git a/doc/publican/Client.xml b/doc/publican/Client.xml deleted file mode 100644 index cb21598f..00000000 --- a/doc/publican/Client.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - -%BOOK_ENTITIES; -]> - - Client API -
Introduction - - The open-source reference implementation of Wayland protocol is - split in two C libraries, libwayland-client and libwayland-server. Their main - responsibility is to handle the Inter-process communication - (IPC) with each other, therefore guaranteeing - the protocol objects marshaling and messages synchronization. - - - A client uses libwayland-client to communicate with one or more - wayland servers. A wl_display object is - created and manages each open connection to a server. At least one - wl_event_queue - object is created for each wl_display, this holds events as they - are received from the server until they can be - processed. Multi-threading is supported by creating an additional - wl_event_queue for each additional thread, each object can have - its events placed in a particular queue, so potentially a - different thread could be made to handle the events for each - object created. - - - Though some convenience functions are provided, libwayland-client - is designed to allow the calling code to wait for events, so that - different polling mechanisms can be used. A file descriptor is - provided, when it becomes ready for reading the calling code can - ask libwayland-client to read the available events from it into - the wl_event_queue objects. - - - The library only provides low-level access to the wayland objects. - Each object created by the client is represented by a wl_proxy object that this - library creates. This includes the id that is actually - communicated over the socket to the server, a void* data pointer - that is intended to point at a client's representation of the - object, and a pointer to a static wl_interface object, - which is generated from the xml and identifies the object's class - and can be used for introspection into the messages and events. - - - Messages are sent by calling wl_proxy_marshal. This will write a - message to the socket, by using the message id and the - wl_interface to identify the types of each argument and convert - them into stream format. Most software will call type-safe - wrappers generated from the xml description of the Wayland protocols. For - instance the C header file generated from the xml defines the - following inline function to transmit the wl_surface::attach - message: - - static inline void -wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y) -{ - wl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_ATTACH, buffer, x, y); -} - - Events (messages from the server) are handled by calling a - "dispatcher" callback the client stores in the wl_proxy for each - event. A language binding for a string-based interpreter, such as - CPython, might have a dispatcher that uses the event name from the - wl_interface to identify the function to call. The default - dispatcher uses the message id number to index an array of - functions pointers, called a wl_listener, and the wl_interface to - convert data from the stream into arguments to the function. The - C header file generated from the xml defines a per-class structure - that forces the function pointers to be of the correct type, for - instance the wl_surface::enter - event defines this pointer in the wl_surface_listener object: - - struct wl_surface_listener { - void (*enter)(void *data, struct wl_surface *, struct wl_output *); - ... -} - - -
- &doxygen; -
diff --git a/doc/publican/Makefile.am b/doc/publican/Makefile.am new file mode 100644 index 00000000..47fc66d2 --- /dev/null +++ b/doc/publican/Makefile.am @@ -0,0 +1,135 @@ +# Documentation is built with publican +# https://fedorahosted.org/publican/ +# Publican takes docbook-style input files and compiles them to various +# output formats. +# +# How this build works: +# * the main target is Wayland, documentation ends up in $(builddir)/Wayland/ +# * hand-written chapters are located in sources +# Publican does not take a source path, so to support out-of-tree builds +# these are copied to $(builddir)/en-US which is the actual directory +# Publican uses. +# * ProtocolSpec.xml is generated from $(top_srcdir)/protocol/wayland.xml, +# changed into docbook via XSLT and saved in $(builddir)/en-US/ +# * ProtocolInterfaces.xml, same as above, uses a different XSLT +# * WaylandClientAPI.xml is generated from the doxygen output and saved in +# $(builddir)/en-US +# * WaylandServerAPI.xml is generated from the doxygen output and saved in +# $(builddir)/en-US +# * run Publican on en-US +publican_sources = \ + $(srcdir)/sources/Wayland.ent \ + $(srcdir)/sources/Wayland.xml \ + $(srcdir)/sources/Book_Info.xml \ + $(srcdir)/sources/Author_Group.xml \ + $(srcdir)/sources/Foreword.xml \ + $(srcdir)/sources/Preface.xml \ + $(srcdir)/sources/Revision_History.xml \ + $(srcdir)/sources/Introduction.xml \ + $(srcdir)/sources/Architecture.xml \ + $(srcdir)/sources/Protocol.xml \ + $(srcdir)/sources/Library.xml \ + $(srcdir)/sources/Compositors.xml \ + $(srcdir)/sources/images/icon.svg \ + $(srcdir)/sources/images/wayland-architecture.png \ + $(srcdir)/sources/images/wayland.png \ + $(srcdir)/sources/images/x-architecture.png + +if HAVE_PUBLICAN +if HAVE_XSLTPROC +noinst_DATA = Wayland $(publican_targets) +pubdir = $(docdir)/Wayland/en-US + +publican_targets = $(publican_sources:$(srcdir)/sources%=$(builddir)/en-US%) \ + en-US/ProtocolSpec.xml en-US/ProtocolInterfaces.xml \ + en-US/WaylandClientAPI.xml en-US/WaylandServerAPI.xml + +# The Protocol.xml is purely generated and required before running publican +en-US/ProtocolSpec.xml: $(top_srcdir)/protocol/wayland.xml $(srcdir)/protocol-to-docbook.xsl + $(AM_V_GEN)$(MKDIR_P) en-US/images + $(AM_V_GEN)$(XSLTPROC) $(srcdir)/protocol-to-docbook.xsl \ + $(top_srcdir)/protocol/wayland.xml > en-US/ProtocolSpec.xml + +en-US/ProtocolInterfaces.xml: $(top_srcdir)/protocol/wayland.xml $(srcdir)/protocol-interfaces-to-docbook.xsl + $(AM_V_GEN)$(MKDIR_P) en-US/images + $(AM_V_GEN)$(XSLTPROC) $(srcdir)/protocol-interfaces-to-docbook.xsl \ + $(top_srcdir)/protocol/wayland.xml > en-US/ProtocolInterfaces.xml + +# * we don't want wayland-{server|client}_8h.xml to avoid duplicating output methods, +# move it out of the way first. +# * use doxygen's combine.xslt to merge the xml files into one single file +# * move wayland-_8h.xml back to its original location +en-US/%API.xml.tmp: + $(AM_V_GEN)mv $(top_builddir)/doc/doxygen/xml/$*/wayland-$*_8h.xml \ + $(top_builddir)/doc/doxygen/xml/ + $(AM_V_GEN)$(XSLTPROC) $(top_builddir)/doc/doxygen/xml/$*/combine.xslt \ + $(top_builddir)/doc/doxygen/xml/$*/index.xml > $@ + $(AM_V_GEN)mv $(top_builddir)/doc/doxygen/xml/wayland-$*_8h.xml \ + $(top_builddir)/doc/doxygen/xml/$* + +# WaylandClientAPI.xml: +# merge doxygen xml files into one single file, then transform the combined XML file into docbook format +en-US/WaylandClientAPI.xml: en-US/clientAPI.xml.tmp $(top_builddir)/doc/doxygen/xml/client/index.xml $(srcdir)/doxygen-to-publican.xsl + $(AM_V_GEN)$(XSLTPROC) --stringparam which Client $(srcdir)/doxygen-to-publican.xsl \ + $(builddir)/en-US/clientAPI.xml.tmp > en-US/WaylandClientAPI.xml + +# WaylandServerAPI.xml: see WaylandClientAPI.xml +en-US/WaylandServerAPI.xml: en-US/serverAPI.xml.tmp $(top_builddir)/doc/doxygen/xml/client/index.xml $(srcdir)/doxygen-to-publican.xsl + $(AM_V_GEN)$(XSLTPROC) --stringparam which Server $(srcdir)/doxygen-to-publican.xsl \ + $(builddir)/en-US/serverAPI.xml.tmp > en-US/WaylandServerAPI.xml + +# Copy the sources source files into en-US destination +# This is required for out-of-source-tree build as publican does not allow us +# to specify the location of the source code. +$(builddir)/en-US/%: $(srcdir)/sources/% en-US/ProtocolSpec.xml en-US/ProtocolInterfaces.xml en-US/WaylandClientAPI.xml $(publican_sources) + $(AM_V_GEN)cp -f $< $@ + $(AM_V_GEN)chmod a+w $@ + +# Run publican for the builddir on the generated (or copied) source +# The output formats are generated in the Wayland sub directory. Also, we need +# to use a tmp publican.cfg cause 'publican rename' modifies the original. +Wayland: $(publican_targets) + $(AM_V_GEN)cp -f $(srcdir)/publican.cfg $(builddir)/publican-copy.cfg + $(AM_V_GEN)$(PUBLICAN) rename --name Wayland \ + --version "$(WAYLAND_VERSION_MAJOR).$(WAYLAND_VERSION_MINOR)" \ + --config $(builddir)/publican-copy.cfg + $(AM_V_GEN)$(PUBLICAN) build --quiet --langs en-US --pdftool fop --formats html,pdf \ + --config $(builddir)/publican-copy.cfg + @touch Wayland + +CLEANFILES = en-US/ProtocolSpec.xml en-US/ProtocolInterfaces.xml en-US/WaylandClientAPI.xml $(publican_targets) + +clean-local: + $(AM_V_at)rm -fr $(builddir)/en-US + $(AM_V_at)rm -fr $(builddir)/Wayland + $(AM_V_at)rm -fr $(builddir)/publican-copy.cfg + +install-data-local: + test -z "$(pubdir)/html/Common_Content/css" || $(mkdir_p) "$(DESTDIR)$(pubdir)/html/Common_Content/css" + test -z "$(pubdir)/html/Common_Content/images" || $(mkdir_p) "$(DESTDIR)$(pubdir)/html/Common_Content/images" + test -z "$(pubdir)/html/images" || $(mkdir_p) "$(DESTDIR)$(pubdir)/html/images" + test -z "$(pubdir)/html-pdf/Common_Content/css" || $(mkdir_p) "$(DESTDIR)$(pubdir)/html-pdf/Common_Content/css" + test -z "$(pubdir)/html-pdf/Common_Content/images" || $(mkdir_p) "$(DESTDIR)$(pubdir)/html-pdf/Common_Content/images" + test -z "$(pubdir)/html-pdf/images" || $(mkdir_p) "$(DESTDIR)$(pubdir)/html-pdf/images" + test -z "$(pubdir)/pdf" || $(mkdir_p) "$(DESTDIR)$(pubdir)/pdf" + test -z "$(pubdir)/xml/Common_Content/css" || $(mkdir_p) "$(DESTDIR)$(pubdir)/xml/Common_Content/css" + test -z "$(pubdir)/xml/Common_Content/images" || $(mkdir_p) "$(DESTDIR)$(pubdir)/xml/Common_Content/images" + test -z "$(pubdir)/xml/images" || $(mkdir_p) "$(DESTDIR)$(pubdir)/xml/images" + list=`find $(builddir)/Wayland/en-US -type f -not -path '$(builddir)/Wayland/en-US/xml_tmp*'`; \ + for p in $$list; do \ + echo " $(INSTALL_DATA) '$$p' '$(DESTDIR)$(docdir)/$$p'"; \ + $(INSTALL_DATA) "$$p" "$(DESTDIR)$(docdir)/$$p"; \ + done; + +uninstall-local: + @if test -n $(DESTDIR)$(docdir); then \ + if test -d $(DESTDIR)$(docdir); then \ + echo " rm -fr $(DESTDIR)$(docdir)/Wayland;"; \ + rm -fr $(DESTDIR)$(docdir)/Wayland; \ + fi; \ + fi; + +endif +endif + +EXTRA_DIST = $(publican_sources) publican.cfg protocol-to-docbook.xsl protocol-interfaces-to-docbook.xsl doxygen-to-publican.xsl diff --git a/doc/publican/Server.xml b/doc/publican/Server.xml deleted file mode 100644 index 2333b1a4..00000000 --- a/doc/publican/Server.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - -%BOOK_ENTITIES; -]> - - Server API -
Introduction - - The open-source reference implementation of Wayland protocol is - split in two C libraries, libwayland-client and - libwayland-server. Their main responsibility is to handle the - Inter-process communication (IPC) with each - other, therefore guaranteeing the protocol objects marshaling and - messages synchronization. - - - The server library is designed to work much like libwayland-client, - although it is considerably complicated due to the server needing - to support multiple versions of the protocol. It is best to learn - libwayland-client first. - - - Each open socket to a client is represented by a wl_client. The equivalent - of the wl_proxy that - libwayland-client uses to represent an object is wl_resource for - client-created objects, and wl_global for objects - created by the server. - - - Often a server is also a client for another Wayland server, and - thus must link with both libwayland-client and libwayland-server. - This produces some type name conflicts (such as the client wl_display and - server wl_display, - but the duplicate-but-not-the-same types are opaque, and accessed - only inside the correct library where it came from. Naturally that - means that the program writer needs to always know if a pointer to - a wl_display is for the server or client side and use the - corresponding functions. - -
- &doxygen; -
diff --git a/doc/publican/Wayland.xml b/doc/publican/Wayland.xml deleted file mode 100644 index 4c3695de..00000000 --- a/doc/publican/Wayland.xml +++ /dev/null @@ -1,12 +0,0 @@ - - -%BOOK_ENTITIES; -]> - - - - - - - diff --git a/doc/publican/doxygen-to-publican.xsl b/doc/publican/doxygen-to-publican.xsl new file mode 100644 index 00000000..2bd677e7 --- /dev/null +++ b/doc/publican/doxygen-to-publican.xsl @@ -0,0 +1,166 @@ + + + + + + + + +%BOOK_ENTITIES; +]> +]]> + +
+ sect-Library- + <xsl:value-of select="$which"/> API + Following is the Wayland library classes for the + (libwayland-). + Note that most of the procedures are related with IPC, which is the main responsibility of + the library. + + + + + + + + + + + Methods for the respective classes. + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Returns: + + + + + + + + + + + + + + See also: + + + + + + + + + + + + + Since: + + + + + + + Note: + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + +
diff --git a/doc/publican/html/css/common.css b/doc/publican/html/css/common.css deleted file mode 100644 index 40b5c4ec..00000000 --- a/doc/publican/html/css/common.css +++ /dev/null @@ -1,1750 +0,0 @@ -* { - widows: 4 !important; - orphans: 4 !important; -} - -body, h1, h2, h3, h4, h5, h6, pre, li, div { - line-height: 1.29em; -} - -body { - background-color: white; - margin:0 auto; - font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif; - font-size: 14px; - max-width: 770px; - color: black; -} - -body.toc_embeded { - /*for web hosting system only*/ - margin-left: 300px; -} - -object.toc, iframe.toc { - /*for web hosting system only*/ - border-style: none; - position: fixed; - width: 290px; - height: 99.99%; - top: 0; - left: 0; - z-index: 100; - border-style: none; - border-right:1px solid #999; -} - -/* Hide web menu */ - -body.notoc { - margin-left: 3em; -} - -iframe.notoc { - border-style:none; - border: none; - padding: 0px; - position:fixed; - width: 21px; - height: 29px; - top: 0px; - left:0; - overflow: hidden; - margin: 0px; - margin-left: -3px; -} -/* End hide web menu */ - -/* desktop styles */ -body.desktop { - margin-left: 26em; -} - -body.desktop .book > .toc { - display:block; - width:24em; - height:99.99%; - position:fixed; - overflow:auto; - top:0px; - left:0px; -/* padding-left:1em; */ - background-color:#EEEEEE; - font-size: 12px; -} - -body.pdf { - max-width: 100%; -} - -.toc { - line-height:1.35em; -} - -.toc .glossary, -.toc .chapter, .toc .appendix { - margin-top:1em; -} - -.toc .part { - margin-top:1em; - display:block; -} - -span.glossary, -span.appendix { - display:block; - margin-top:0.5em; -} - -div { - padding-top:0px; -} - -div.section { - page-break-inside: avoid; -} - -p, div.para { - padding-top: 0px; - margin-top: 1em; - padding-bottom: 0px; - margin-bottom: 1em; -} - -div.formalpara { - padding-top: 0px; - margin-top: 1em; - padding-bottom: 0px; - margin-bottom: 1em; -} - -.varlistentry div.para { - page-break-before: avoid; - -} - -/*Links*/ -a { - outline: none; -} - -a:link { - text-decoration: none; - border-bottom: 1px dotted ; - color:#3366cc; -} - -body.pdf a:link { - word-wrap: break-word; -} - -a:visited { - text-decoration:none; - border-bottom: 1px dotted ; - color:#003366; -} - -div.longdesc-link { - float:right; - color:#999; -} - -.toc a, .qandaset a { - font-weight:normal; - border:none; -} - -.toc a:hover, .qandaset a:hover -{ - border-bottom: 1px dotted; -} - -/*headings*/ -h1, h2, h3, h4, h5, h6 { - color: #336699; - margin-top: 0px; - margin-bottom: 0px; - background-color: transparent; - margin-bottom: 0px; - margin-top: 20px; - page-break-inside: avoid; - page-break-after: avoid; - word-wrap: break-word; -} - -h1 { - font-size: 22px; -} - -.titlepage h1.title { - text-align:left; -} - -.book > .titlepage h1.title { - text-align: center; -} - -.article > .titlepage h1.title, -.article > .titlepage h2.title { - text-align: center; -} - -.set .titlepage > div > div > h1.title { - text-align: center; -} - -.part > .titlepage h1.title { - text-align: center; - font-size: 24px; -} - -div.producttitle { - margin-top: 0px; - margin-bottom: 20px; - font-size: 48px; - font-weight: bold; - color: #336699; - text-align: center; - padding-top: 12px; -} - -.titlepage .corpauthor { - margin-top: 1em; - text-align: center; -} - -.section h1.title { - font-size: 18px; - padding: 0px; - color: #336699; - text-align: left; - background: white; -} - -h2 { - font-size: 20px; - margin-top: 30px; -} - - -.book div.subtitle, .book h2.subtitle, .book h3.subtitle { - margin-top: 1em; - margin-bottom: 1em; - font-size: 18px; - text-align: center; -} - -div.subtitle { - color: #336699; - font-weight: bold; -} - -h1.legalnotice { - font-size: 24px; -} - -.preface > div > div > div > h2.title, -.preface > div > div > div > h1.title { - margin-top: 1em; - font-size: 24px; -} - -.appendix h2 { - font-size: 24px; -} - - - -h3 { - font-size: 14px; - padding-top:0px; - padding-bottom: 0px; - margin-bottom: 0px; -} -h4 { - font-size: 14px; - padding-top:0px; - padding-bottom:0px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 14px; - margin-bottom: 0px; -} - -.abstract h6 { - margin-top:1em; - margin-bottom:.5em; - font-size: 24px; -} - -.index > div > div > div > h2.title { - font-size: 24px; -} - -.chapter > div > div > div > h2.title { - font-size: 24px; -} - -.section > div > div > div > h2.title { - font-size: 21px; - page-break-inside: avoid; - page-break-before: avoid; - page-break-after: avoid; -} - -.section > div > div > div > h3.title { - font-size: 17px; -} - -/*element rules*/ -hr { - border-collapse: collapse; - border-style:none; - border-top: 1px dotted #ccc; - width:100%; -} - -/* web site rules */ -ul.languages, .languages li { - display:inline; - padding:0px; -} - -.languages li a { - padding:0px .5em; - text-decoration: none; -} - -.languages li p, .languages li div.para { - display:inline; -} - -.languages li a:link, .languages li a:visited { - color:#444; -} - -.languages li a:hover, .languages li a:focus, .languages li a:active { - color:black; -} - -ul.languages { - display:block; - background-color:#eee; - padding:.5em; -} - -/*supporting stylesheets*/ - -/*unique to the webpage only*/ -.books { - position:relative; -} - -.versions li { - width:100%; - clear:both; - display:block; -} - -a.version { - font-size: 20px; - text-decoration:none; - width:100%; - display:block; - padding:1em 0px .2em 0px; - clear:both; -} - -a.version:before { - content:"Version"; - font-size: smaller; -} - -a.version:visited, a.version:link { - color:#666; -} - -a.version:focus, a.version:hover { - color:black; -} - -.books { - display:block; - position:relative; - clear:both; - width:100%; -} - -.books li { - display:block; - width:200px; - float:left; - position:relative; - clear: none ; -} - -.books .html { - width:170px; - display:block; -} - -.books .pdf { - position:absolute; - left:170px; - top:0px; - font-size: smaller; -} - -.books .pdf:link, .books .pdf:visited { - color:#555; -} - -.books .pdf:hover, .books .pdf:focus { - color:#000; -} - -.books li a { - text-decoration:none; -} - -.books li a:hover { - color:black; -} - -/*products*/ -.products li { - display: block; - width:300px; - float:left; -} - -.products li a { - width:300px; - padding:.5em 0px; -} - -.products ul { - clear:both; -} - -/*revision history*/ -.revhistory { - display:block; -} - -.revhistory table { - background-color:transparent; - border-color:#fff; - padding:0px; - margin: 0; - border-collapse:collapse; - border-style:none; -} - -.revhistory td { - text-align :left; - padding:0px; - border: none; - border-top: 1px solid #fff; - font-weight: bold; -} - -.revhistory .simplelist td { - font-weight: normal; -} - -.revhistory .simplelist { - margin-bottom: 1.5em; - margin-left: 1em; -} - -.revhistory table th { - display: none; -} - - -/*credits*/ -.authorgroup div { - clear:both; - text-align: center; -} - -div.author div.author, -div.translator div.translator, -div.othercredit div.othercredit, -div.editor div.editor, -div.contrib div.contrib { - margin: 0px; - padding: 0px; - margin-top: 12px; - font-size: 14px; - font-weight: bold; - color: #336699; -} - -div.editedby { - margin-top: 15px; - margin-bottom: -0.8em; -} - -div.authorgroup .author, -div.authorgroup.editor, -div.authorgroup.translator, -div.authorgroup.othercredit, -div.authorgroup.contrib { - display: block; - font-size: 14px; - page-break-inside: avoid; -} - -.revhistory .author { - display: inline; -} - -.othercredit h3 { - padding-top: 1em; -} - - -.othercredit { - margin:0px; - padding:0px; -} - -.releaseinfo { - clear: both; -} - -.copyright { - margin-top: 1em; -} - -/* qanda sets */ -.answer { - margin-bottom:1em; - border-bottom:1px dotted #ccc; -} - -.qandaset .toc { - border-bottom:1px dotted #ccc; -} - -.question { - font-weight:bold; -} - -.answer .data, .question .data { - padding-left: 2.6em; -} - -.answer .label, .question .label { - float:left; - font-weight:bold; -} - -/* inline syntax highlighting */ -.perl_Alert { - color: #0000ff; -} - -.perl_BaseN { - color: #007f00; -} - -.perl_BString { - color: #5C3566; -} - -.perl_Char { - color: #ff00ff; -} - -.perl_Comment { - color: #888888; -} - - -.perl_DataType { - color: #0000ff; -} - - -.perl_DecVal { - color: #00007f; -} - - -.perl_Error { - color: #ff0000; -} - - -.perl_Float { - color: #00007f; -} - - -.perl_Function { - color: #007f00; -} - - -.perl_IString { - color: #5C3566; -} - - -.perl_Keyword { - color: #002F5D; -} - - -.perl_Operator { - color: #ffa500; -} - - -.perl_Others { - color: #b03060; -} - - -.perl_RegionMarker { - color: #96b9ff; -} - - -.perl_Reserved { - color: #9b30ff; -} - - -.perl_String { - color: #5C3566; -} - - -.perl_Variable { - color: #0000ff; -} - - -.perl_Warning { - color: #0000ff; -} - -/*Lists*/ -ul { - list-style-type: circle; - padding-left: 1.6em; -} - -ul ul { - list-style-type: circle; -} - -ol.1 { - list-style-type: decimal; -} - -ol.a, -ol ol { - list-style-type: lower-alpha; -} - -ol.i { - list-style-type: lower-roman; -} -ol.A { - list-style-type: upper-alpha; -} - -ol.I { - list-style-type: upper-roman; -} - -dt { - font-weight:bold; - margin-bottom:0px; - padding-bottom:0px; -} - -dd { - margin:0px; - margin-left:2em; - padding-top:0px; -} - -li { - padding-top: 0px; - margin-top: 0px; - padding-bottom: 0px; -/* margin-bottom: 16px; */ -} - -/*images*/ -img { - display:block; - margin: 2em 0; - max-width: 100%; -} - -.inlinemediaobject, -.inlinemediaobject img, -.inlinemediaobject object { - display:inline; - margin:0px; - overflow: hidden; -} - -.figure { - margin-top: 1em; - width: 100%; -} - -.figure img, -.mediaobject img { - display:block; - margin: 0em; - page-break-inside: avoid; -} - -.figure .title { - margin-bottom:2em; - padding:0px; -} - -/*document modes*/ -.confidential { - background-color:#900; - color:White; - padding:.5em .5em; - text-transform:uppercase; - text-align:center; -} - -.longdesc-link { - display:none; -} - -.longdesc { - display:none; -} - -.prompt { - padding:0px .3em; -} - -/*user interface styles*/ -.screen .replaceable { -} - -.guibutton, .guilabel { - font-family: "liberation mono", "bitstream vera mono", "dejavu mono", monospace; - font-weight: bold; -} - -.example { - background-color: #ffffff; - border-left: 3px solid #aaaaaa; - padding-top: 1px; - padding-bottom: 0.1em; - padding-left: 1em; -} - -.equation { - border-left: 3px solid #aaaaaa; - background-color: #ffffff; - padding-top: 1px; - padding-bottom: 0.1em; - padding-left: 1em; -} - -.equation-contents { - margin-left: 4em; -} - -div.title { - margin-bottom: 1em; - font-weight: 14px; - font-weight: bold; - color: #336699; - page-break-inside: avoid; - page-break-after: avoid; - word-wrap: break-word; -} - -.example-contents { - background-color: #ffffff; -} - -.example-contents .para { -/* padding: 10px;*/ -} - -/*terminal/console text*/ -.computeroutput, -.option { - font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; - font-weight:bold; -} - -.replaceable { - font-style: italic; -} - -.command, .filename, .keycap, .classname, .literal { - font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; - font-weight:bold; -} - -/* no bold in toc */ -.toc * { - font-weight: inherit; -} - -.toc H1 { - font-weight: bold; -} - - -div.programlisting { - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ -} - -pre { - font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; - display:block; - background-color: #f5f5f5; - color: #000000; -/* border: 1px solid #aaaaaa; */ - margin-bottom: 1em; - padding:.5em 1em; - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - font-size: 0.9em; - border-style:none; - box-shadow: 0 2px 5px #AAAAAA inset; - -moz-box-shadow: 0 2px 5px #AAAAAA inset; - -webkit-box-shadow: 0 2px 5px #AAAAAA inset; - -o-box-shadow: 0 2px 5px #AAAAAA inset; -} - -body.pdf pre { - border: 1px solid #AAAAAA; - box-shadow: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - -o-box-shadow: none; -} - - -pre .replaceable, -pre .keycap { -} - -code { - font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; - white-space: pre-wrap; - word-wrap: break-word; - font-weight: normal; -} - -.parameter code { - display: inline; - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ -} - -code.email { - font-weight: normal; - font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif; - -} - -.synopsis { - font-weight: normal; -} - -.userinput { - font-style: italic; -} - -/*Notifications*/ -div.warning, div.note, div.important { - color: black; - margin: 0px; - padding: 0px; - background: none; - background-color: white; - margin-bottom: 1em; - border-bottom: 1px solid #aaaaaa; - page-break-inside: avoid; -} - -div.admonition_header p { - margin: 0px; - padding: 0px; - color: #eeeeec; - padding-top: 0px; - padding-bottom: 0px; - height: 1.4em; - line-height: 1.4em; - font-size: 17px; - display:inline; -} - -div.admonition_header { - background-origin:content-box; - clear: both; - margin: 0px; - padding: 0px; - margin-top: -40px; - padding-left: 58px; - line-height: 1.0px; - font-size: 1.0px; -} - -div.warning div.admonition_header { - background-color: #590000; - background: -webkit-linear-gradient(#a40000,#590000); - background: linear-gradient(#a40000,#590000); -} - -div.note div.admonition_header { - background-color: #597800; - background: -webkit-linear-gradient(#769f00,#597800); - background: linear-gradient(#769f00,#597800); -} - -div.important div.admonition_header { - background-color: #a6710f; - background: -webkit-linear-gradient(#d08e13,#a6710f); - background: linear-gradient(#d08e13,#a6710f); -} - -div.warning p:first-child, -div.warning div.para:first-child, -div.note p:first-child, -div.note div.para:first-child, -div.important p:first-child, -div.important div.para:first-child { - padding: 0px; - margin: 0px; -} - -div.admonition { - border: none; - border-left: 1px solid #aaaaaa; - border-right: 1px solid #aaaaaa; - padding:0px; - margin:0px; - padding-top: 1.5em; - padding-bottom: 1em; - padding-left: 2em; - padding-right: 1em; - background-color: #eeeeec; - -moz-border-radius: 0px; - -webkit-border-radius: 0px; - border-radius: 0px; -} - -/*Page Title*/ -#title { - display:block; - height:45px; - padding-bottom:1em; - margin:0px; -} - -#title a.left{ - display:inline; - border:none; -} - -#title a.left img{ - border:none; - float:left; - margin:0px; - margin-top:.7em; -} - -#title a.right { - padding-bottom:1em; -} - -#title a.right img { - border:none; - float:right; - margin:0px; - margin-top:.7em; -} - -/*Table*/ -div.table { -/* page-break-inside: avoid; */ -} - -table { - border: 1px solid #444; - width:100%; - border-collapse:collapse; - table-layout: fixed; - word-wrap: break-word; -} - -table.blockquote, -table.simplelist, -.calloutlist table { - border-style: none; -} - -table th { - text-align:left; - background-color:#6699cc; - padding:.3em .5em; - color:white; -} - -table td { - padding:.15em .5em; -} - -table tr.even td { - background-color:#f5f5f5; -} - -tr:nth-child(even) { - background-color: #eeeeee; - -} - - -table th p:first-child, table td p:first-child, table li p:first-child, -table th div.para:first-child, table td div.para:first-child, table li div.para:first-child { - margin-top:0px; - padding-top:0px; - display:inline; -} - -th, td { - border-style:none; - vertical-align: top; -/* border: 1px solid #000; */ -} - -.blockquote td, -.simplelist th, -.simplelist td { - border: none; -} - -table table td { - border-bottom:1px dotted #aaa; - background-color:white; - padding:.6em 0px; -} - -table table { - border:1px solid white; -} - -td.remarkval { - color:#444; -} - -td.fieldval { - font-weight:bold; -} - -.lbname, .lbtype, .lbdescr, .lbdriver, .lbhost { - color:white; - font-weight:bold; - background-color:#999; - width:120px; -} - -td.remarkval { - width:230px; -} - -td.tname { - font-weight:bold; -} - -th.dbfield { - width:120px; -} - -th.dbtype { - width:70px; -} - -th.dbdefault { - width:70px; -} - -th.dbnul { - width:70px; -} - -th.dbkey { - width:70px; -} - -span.book { - margin-top:4em; - display:block; - font-size: 11pt; -} - -span.book a{ - font-weight:bold; -} -span.chapter { - display:block; -} - -table.simplelist td, .calloutlist table td { - border-style: none; -} - - -table.lt-4-cols.lt-7-rows td { - border: none; -} -/*to simplify layout*/ - - -table.lt-4-cols.gt-14-rows tr:nth-child(odd) { - background-color: #fafafa; -} -/* to keep simple but stripe rows */ - - -.gt-8-cols td { - border-left: 1px solid #ccc; -} - -.gt-8-cols td:first-child { - border-left: 0; -} -/* to apply vertical lines to differentiate columns*/ - -/*Breadcrumbs*/ -#breadcrumbs ul li.first:before { - content:" "; -} - -#breadcrumbs { - color:#900; - padding:3px; - margin-bottom:25px; -} - -#breadcrumbs ul { - margin-left:0; - padding-left:0; - display:inline; - border:none; -} - -#breadcrumbs ul li { - margin-left:0; - padding-left:2px; - border:none; - list-style:none; - display:inline; -} - -#breadcrumbs ul li:before { - content:"\0020 \0020 \0020 \00BB \0020"; - color:#333; -} - -dl { - margin-top: 0px; - margin-left: 28px; -} - -.toc dl { - margin-left: 10px; -} - -/*index*/ -.glossary h3, -.index h3 { - font-size: 20px; - color:#aaa; - margin:0px; -} - -.indexdiv { - margin-bottom:1em; -} - -.glossary dt, -.index dt { - color:#444; - padding-top:.5em; -} - -.glossary dl dl dt, -.index dl dl dt { - color:#777; - font-weight:normal; - padding-top:0px; -} - -.index dl dl dt:before { - content:"- "; - color:#ccc; -} - -/*changes*/ -.footnote { - font-size: 10px; - margin: 0px; - color: #222; -} - -.footnotes { - margin-bottom: 60px; -} - -table .footnote { -} - -sup { - margin:0px; - padding:0px; - font-size: 10px; - padding-left:0px; -} - -.footnote { - position:relative; -} - -.footnote sup { - color: black; - left: .4em; -} - -.footnote a:link, -.footnote a:visited { - text-decoration:none; - border: none; -} - -.footnote .para sup { -/* position:absolute; */ - vertical-align:text-bottom; -} - -a.footnote { - padding-right: 0.5em; - text-decoration:none; - border: none; -} - -.footnote sup a:link, -.footnote sup a:visited { - color:#92917d; - text-decoration:none; -} - -.footnote:hover sup a { - text-decoration:none; -} - -.footnote p,.footnote div.para { - padding-left:1em; -} - -.footnote a:link, -.footnote a:visited before{ - color:#00537c; -} - -.footnote a:hover { -} - -/**/ -.pdf-break { - page-break-before: always; -} - -div.legalnotice { - page-break-before: always; -} - -div.abstract { - page-break-before: always; -/* page-break-after: always;*/ -} - -div.chapter { - page-break-before: always; -} - - -div.titlepage, div.titlepage > div, div.titlepage > div > div { - page-break-inside: avoid; - page-break-after: avoid; -} - -div.preface, div.part { - page-break-before: always; -} - -div.appendix { - page-break-before: always; -} - -div.section { - page-break-inside: auto; - page-break-before: auto; - page-break-after: auto; -} - - -dt.varlistentry { - page-break-inside: avoid; - page-break-after: avoid; -} - -dd { - page-break-before: avoid; -} - -div.note .replaceable, -div.important .replaceable, -div.warning .replaceable, -div.note .keycap, -div.important .keycap, -div.warning .keycap -{ -} - -ul li p:last-child, ul li para:last-child { - margin-bottom:0px; - padding-bottom:0px; -} - -/*document navigation*/ -.docnav a, .docnav strong { - border:none; - text-decoration:none; - font-weight:normal; -} - -.docnav { - list-style:none; - margin:0px; - padding:0px; - position:relative; - width:100%; - padding-bottom:2em; - padding-top:1em; - height:2.5em; - line-height:2.5em; -/* - border-top:1px dotted #ccc; - background-color: rgba(240, 240, 240, 0.9); --webkitbox-shadow: 0px .15em .5em rgba(0,0,0,0.2); - -moz-box-shadow: 0px .15em .5em rgba(0,0,0,0.2); - box-shadow: 0px .15em .5em rgba(0,0,0,0.2); -*/ -} - -.docnav li { - list-style:none; - margin:0px; - padding:0px; - display:inline; - font-size: 14px; -} - -.docnav li:before { - content:" "; -} - -.docnav li.previous, .docnav li.next { - position:absolute; - top:1.5em; -} - -.docnav li.up, .docnav li.home { - margin:0px 1.5em; -} - -.docnav.top li.home { - color: #336699; - font-size: 22pt; - font-weight: bold; -} - - -.docnav li.previous { - left:0px; - text-align:left; -} - -.docnav li.next { - right:0px; - text-align:right; -} - -.docnav li.previous strong, .docnav li.next strong { - height: 17px; - display: block; -} - -.docnav { - margin:0 auto; - text-align:center; -} - -.docnav li.next a strong { - padding-top:3px; - padding-bottom:4px; - padding-right:28px; -} - -.docnav li.previous a strong { - padding-top:3px; - padding-bottom:4px; - padding-left:28px; - padding-right:0.5em; -} - -.docnav li.home a strong { - padding:5px; - padding-left:28px; -} - -.docnav li.up a strong { - padding:5px; - padding-left:28px; -} - -.docnav a:link, .docnav a:visited { - color:#666; -} - -.docnav a:hover, .docnav a:focus, .docnav a:active { - color:black; -} - -.docnav a { - max-width: 10px; - overflow:hidden; -} - -.docnav a:link strong { - text-decoration:none; -} - -.docnav { - margin:0 auto; - text-align:center; -} - -ul.docnav { - margin-bottom: 1em; -} -/* Reports */ -.reports ul { - list-style:none; - margin:0px; - padding:0px; -} - -.reports li{ - margin:0px; - padding:0px; -} - -.reports li.odd { - background-color: #eeeeee; - margin:0px; - padding:0px; -} - -.reports dl { - display:inline; - margin:0px; - padding:0px; - float:right; - margin-right: 17em; - margin-top:-1.3em; -} - -.reports dt { - display:inline; - margin:0px; - padding:0px; -} - -.reports dd { - display:inline; - margin:0px; - padding:0px; - padding-right:.5em; -} - -.reports h2, .reports h3{ - display:inline; - padding-right:.5em; - font-size: 14px; - font-weight:normal; -} - -.reports div.progress { - display:inline; - float:right; - width:16em; - margin:0px; - margin-top:-1.3em; - padding:0px; - border:none; -} - -/*uniform*/ -body.results, body.reports { - max-width:57em ; - padding:0px; -} - -/*Progress Bar*/ -div.progress { - display:block; - float:left; - width:16em; - height:1em; -} - -div.progress span { - height:1em; - float:left; -} - -div.progress span.translated { - background:#6c3; -} - -div.progress span.fuzzy { - background:#ff9f00; -} - - -/*Results*/ - -.results ul { - list-style:none; - margin:0px; - padding:0px; -} - -.results li{ - margin:0px; - padding:0px; -} - -.results li.odd { - background-color: #eeeeee; - margin:0px; - padding:0px; -} - -.results dl { - display:inline; - margin:0px; - padding:0px; - float:right; - margin-right: 17em; - margin-top:-1.3em; -} - -.results dt { - display:inline; - margin:0px; - padding:0px; -} - -.results dd { - display:inline; - margin:0px; - padding:0px; - padding-right:.5em; -} - -.results h2, .results h3 { - display:inline; - padding-right:.5em; - font-size: 14px; - font-weight:normal; -} - -.results div.progress { - display:inline; - float:right; - width:16em; - background:#c00; - margin:0px; - margin-top:-1.3em; - padding:0px; - border:none; -} - -/* Dirty EVIL Mozilla hack for round corners */ -pre { - -moz-border-radius:11px; - -webkit-border-radius:11px; - border-radius: 11px; -/* page-break-inside: avoid; */ -} - -.example { - -moz-border-radius:0px; - -webkit-border-radius:0px; - border-radius: 0px; - page-break-inside: avoid; -} - -/* move these invisible fields out of the flow */ -.example > a:first-child, -.table > a:first-child { - float: left; -} - -.package, .citetitle { - font-style: italic; -} - -.titlepage .edition, -.titlepage .releaseinfo { - color: #336699; - background-color: transparent; - margin-top: 1em; - margin-bottom: 1em; - font-size: 20px; - font-weight: bold; - text-align: center; -} - -span.remark { - background-color: #ff00ff; -} - -.draft { - background-color: #aaa; - background-repeat: repeat-y; - background-position: center; -} - -.foreignphrase { - font-style: inherit; -} - -dt { - clear:both; - page-break-inside: avoid; - page-break-after: avoid; -} - -dt img { - border-style: none; - max-width: 112px; -} - -dt object { - max-width: 112px; -} - -dt .inlinemediaobject, dt object { - display: inline; - float: left; - margin-bottom: 1em; - padding-right: 1em; - width: 112px; -} - -dl:after { - display: block; - clear: both; - content: ""; -} - -.toc dd { - padding-bottom: 0px; - margin-bottom: 1em; - padding-left: 1.3em; - margin-left: 0px; -} - -div.toc > dl > dt { - padding-bottom: 0px; - margin-bottom: 0px; - margin-top: 1em; -} - - -.strikethrough { - text-decoration: line-through; -} - -.underline { - text-decoration: underline; -} - -.calloutlist img, .callout { - padding: 0px; - margin: 0px; - width: 12pt; - display: inline; - vertical-align: middle; -} - -li.step > a:first-child { - display: block; -} - -.stepalternatives { - list-style-image: none; - list-style-type: upper-alpha; -} -.task { -/* page-break-inside: avoid; */ -} - - -.added { - background-color: #99ff99; -} - -.changed { - background-color: #ffff77; -} - -.deleted { - background-color: #ff4455; - text-decoration: line-through; -} diff --git a/doc/publican/html/css/default.css b/doc/publican/html/css/default.css deleted file mode 100644 index bf38ebb5..00000000 --- a/doc/publican/html/css/default.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("common.css"); -@import url("overrides.css"); -@import url("lang.css"); diff --git a/doc/publican/html/css/meson.build b/doc/publican/html/css/meson.build deleted file mode 100644 index ddfbfe27..00000000 --- a/doc/publican/html/css/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -foreach src : files([ - 'common.css', - 'default.css', -]) - name = fs.name(src) - publican_inputs += fs.copyfile( - name, - install: true, - install_dir: publican_install_prefix + '/html/css', - ) -endforeach diff --git a/doc/publican/html/images/icon.svg b/doc/publican/html/images/icon.svg deleted file mode 100644 index b2f16d0f..00000000 --- a/doc/publican/html/images/icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/doc/publican/html/images/meson.build b/doc/publican/html/images/meson.build deleted file mode 100644 index cb80da66..00000000 --- a/doc/publican/html/images/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -foreach src : files([ - 'icon.svg', - 'wayland.png', -]) - name = fs.name(src) - publican_inputs += fs.copyfile( - name, - install: true, - install_dir: publican_install_prefix + '/html/images', - ) -endforeach diff --git a/doc/publican/html/images/wayland.png b/doc/publican/html/images/wayland.png deleted file mode 100644 index c9937928..00000000 Binary files a/doc/publican/html/images/wayland.png and /dev/null differ diff --git a/doc/publican/meson.build b/doc/publican/meson.build deleted file mode 100644 index c0a42155..00000000 --- a/doc/publican/meson.build +++ /dev/null @@ -1,95 +0,0 @@ -proto_to_docboox_xsl = files('xsl/protocol-to-docbook.xsl') -proto_iface_to_docboox_xsl = files('xsl/protocol-interfaces-to-docbook.xsl') -merge_mapcoords_xsl = files('xsl/merge-mapcoords.xsl') -to_publican_xsl = files('xsl/doxygen-to-publican.xsl') - -publican_inputs = [] -publican_image_maps = [] - -foreach src : files([ - 'Wayland.xml', # must be first in publican_inputs - 'Wayland.ent', - 'Book_Info.xml', - 'Author_Group.xml', - 'Foreword.xml', - 'Client.xml', - 'Server.xml', -]) - name = fs.name(src) - publican_inputs += fs.copyfile(name) -endforeach - -publican_inputs += custom_target( - 'ProtocolSpec.xml', - command: [ xsltproc, '-o', '@OUTPUT@', proto_to_docboox_xsl, '@INPUT@' ], - input: wayland_protocol_xml, - output: 'ProtocolSpec.xml' -) - -publican_inputs += custom_target( - 'ProtocolInterfaces.xml', - command: [ xsltproc, '-o', '@OUTPUT@', proto_iface_to_docboox_xsl, '@INPUT@' ], - input: wayland_protocol_xml, - output: 'ProtocolInterfaces.xml' -) - -# Doxygen generates a myriad of files, and offers an XSLT -# to combine them all into one. This does the combining. -# The result is still Doxygen XML. -ClientAPI_combined = custom_target( - 'ClientAPI-combine-doxygen-files', - command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ], - input: [ doxygen_Client_combine_xslt, doxygen_Client_index_xml ], - output: 'ClientAPI-combined.xml' -) - -# This converts Doxygen XML to DocBook XML. -publican_inputs += custom_target( - 'ClientAPI-doxygen-to-docbook', - command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Client', to_publican_xsl, '@INPUT@' ], - input: ClientAPI_combined, - output: 'ClientAPI.xml' -) - -ServerAPI_combined = custom_target( - 'ServerAPI-combine-doxygen-files', - command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ], - input: [ doxygen_Server_combine_xslt, doxygen_Server_index_xml ], - output: 'ServerAPI-combined.xml' -) - -publican_inputs += custom_target( - 'ServerAPI-doxygen-to-docbook', - command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Server', to_publican_xsl, '@INPUT@' ], - input: ServerAPI_combined, - output: 'ServerAPI.xml' -) - -subdir('html/css') -subdir('html/images') - -skip_validation = '--skip-validation' -if get_option('docbook_validation') - skip_validation = [] -endif - -custom_target( - 'Wayland-docbook-html', - command: [ - xmlto, - skip_validation, - '--stringparam', 'chunker.output.encoding=UTF-8', - '--stringparam', 'chunk.section.depth=0', - '--stringparam', 'toc.section.depth=1', - '--stringparam', 'generate.consistent.ids=1', - '--stringparam', 'html.stylesheet=css/default.css', - '-o', '@OUTPUT@', - 'html', - '@INPUT0@' - ], - input: publican_inputs, - output: 'html', - build_by_default: true, - install: true, - install_dir: publican_install_prefix, -) diff --git a/doc/publican/xsl/protocol-interfaces-to-docbook.xsl b/doc/publican/protocol-interfaces-to-docbook.xsl similarity index 68% rename from doc/publican/xsl/protocol-interfaces-to-docbook.xsl rename to doc/publican/protocol-interfaces-to-docbook.xsl index f68216d5..ad6bdda0 100644 --- a/doc/publican/xsl/protocol-interfaces-to-docbook.xsl +++ b/doc/publican/protocol-interfaces-to-docbook.xsl @@ -1,5 +1,6 @@ + @@ -23,10 +24,10 @@ - Core interfaces: - - - + Core interfaces: + + + @@ -34,17 +35,21 @@ - - + protocol-summary-- + + - - - - - - - - + + - + + + + + + + + + diff --git a/doc/publican/protocol-to-docbook.xsl b/doc/publican/protocol-to-docbook.xsl new file mode 100644 index 00000000..939ba40e --- /dev/null +++ b/doc/publican/protocol-to-docbook.xsl @@ -0,0 +1,136 @@ + + + + + + + + +%BOOK_ENTITIES; +]> +]]> + + + Wayland Protocol Specification + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ protocol-spec-- + + + <xsl:value-of select="@name" /> + <!-- only show summary if it exists --> + <xsl:if test="description/@summary"> + - <xsl:value-of select="description/@summary" /> + </xsl:if> + + + + + +
+ Requests provided by <xsl:value-of select="@name" /> + +
+
+ +
+ Events provided by <xsl:value-of select="@name" /> + +
+
+ +
+ Enums provided by <xsl:value-of select="@name" /> + +
+
+
+
+ + + + + + + + Type: + + + Value: + + + + + + + + + + + + +
+ protocol-spec-interface--- + + <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" /> + <xsl:if test="description/@summary"> + - <xsl:value-of select="description/@summary" /> + </xsl:if> + + + + + + + <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" /> arguments + + + + + + <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" /> values + + + +
+
+
+ + diff --git a/doc/publican/publican.cfg b/doc/publican/publican.cfg new file mode 100644 index 00000000..ccb9f04f --- /dev/null +++ b/doc/publican/publican.cfg @@ -0,0 +1,9 @@ +# Config::Simple 4.59 +# Fri Feb 24 09:36:50 2012 + +xml_lang: "en-US" +type: Book +brand: common +tmp_dir: Wayland +toc_section_depth: 1 +chunk_section_depth: 0 diff --git a/doc/publican/sources/Architecture.xml b/doc/publican/sources/Architecture.xml new file mode 100644 index 00000000..5b9300f8 --- /dev/null +++ b/doc/publican/sources/Architecture.xml @@ -0,0 +1,330 @@ + + +%BOOK_ENTITIES; +]> + + Wayland Architecture +
+ X vs. Wayland Architecture + + A good way to understand the Wayland architecture + and how it is different from X is to follow an event + from the input device to the point where the change + it affects appears on screen. + + + This is where we are now with X: + + + + + + + + X architecture diagram + + + + + + + + The kernel gets an event from an input + device and sends it to X through the evdev + input driver. The kernel does all the hard + work here by driving the device and + translating the different device specific + event protocols to the linux evdev input + event standard. + + + + + The X server determines which window the + event affects and sends it to the clients + that have selected for the event in question + on that window. The X server doesn't + actually know how to do this right, since + the window location on screen is controlled + by the compositor and may be transformed in + a number of ways that the X server doesn't + understand (scaled down, rotated, wobbling, + etc). + + + + + The client looks at the event and decides + what to do. Often the UI will have to change + in response to the event - perhaps a check + box was clicked or the pointer entered a + button that must be highlighted. Thus the + client sends a rendering request back to the + X server. + + + + + When the X server receives the rendering + request, it sends it to the driver to let it + program the hardware to do the rendering. + The X server also calculates the bounding + region of the rendering, and sends that to + the compositor as a damage event. + + + + + The damage event tells the compositor that + something changed in the window and that it + has to recomposite the part of the screen + where that window is visible. The compositor + is responsible for rendering the entire + screen contents based on its scenegraph and + the contents of the X windows. Yet, it has + to go through the X server to render this. + + + + + The X server receives the rendering requests + from the compositor and either copies the + compositor back buffer to the front buffer + or does a pageflip. In the general case, the + X server has to do this step so it can + account for overlapping windows, which may + require clipping and determine whether or + not it can page flip. However, for a + compositor, which is always fullscreen, this + is another unnecessary context switch. + + + + + + As suggested above, there are a few problems with this + approach. The X server doesn't have the information to + decide which window should receive the event, nor can it + transform the screen coordinates to window local + coordinates. And even though X has handed responsibility for + the final painting of the screen to the compositing manager, + X still controls the front buffer and modesetting. Most of + the complexity that the X server used to handle is now + available in the kernel or self contained libraries (KMS, + evdev, mesa, fontconfig, freetype, cairo, Qt etc). In + general, the X server is now just a middle man that + introduces an extra step between applications and the + compositor and an extra step between the compositor and the + hardware. + + + In Wayland the compositor is the display server. We transfer + the control of KMS and evdev to the compositor. The Wayland + protocol lets the compositor send the input events directly + to the clients and lets the client send the damage event + directly to the compositor: + + + + + + + + Wayland architecture diagram + + + + + + + + The kernel gets an event and sends + it to the compositor. This + is similar to the X case, which is + great, since we get to reuse all the + input drivers in the kernel. + + + + + The compositor looks through its + scenegraph to determine which window + should receive the event. The + scenegraph corresponds to what's on + screen and the compositor + understands the transformations that + it may have applied to the elements + in the scenegraph. Thus, the + compositor can pick the right window + and transform the screen coordinates + to window local coordinates, by + applying the inverse + transformations. The types of + transformation that can be applied + to a window is only restricted to + what the compositor can do, as long + as it can compute the inverse + transformation for the input events. + + + + + As in the X case, when the client + receives the event, it updates the + UI in response. But in the Wayland + case, the rendering happens in the + client, and the client just sends a + request to the compositor to + indicate the region that was + updated. + + + + + The compositor collects damage + requests from its clients and then + recomposites the screen. The + compositor can then directly issue + an ioctl to schedule a pageflip with + KMS. + + + + + + +
+
+ Wayland Rendering + + One of the details I left out in the above overview + is how clients actually render under Wayland. By + removing the X server from the picture we also + removed the mechanism by which X clients typically + render. But there's another mechanism that we're + already using with DRI2 under X: direct rendering. + With direct rendering, the client and the server + share a video memory buffer. The client links to a + rendering library such as OpenGL that knows how to + program the hardware and renders directly into the + buffer. The compositor in turn can take the buffer + and use it as a texture when it composites the + desktop. After the initial setup, the client only + needs to tell the compositor which buffer to use and + when and where it has rendered new content into it. + + + + This leaves an application with two ways to update its window contents: + + + + + + Render the new content into a new buffer and tell the compositor + to use that instead of the old buffer. The application can + allocate a new buffer every time it needs to update the window + contents or it can keep two (or more) buffers around and cycle + between them. The buffer management is entirely under + application control. + + + + + Render the new content into the buffer that it previously + told the compositor to to use. While it's possible to just + render directly into the buffer shared with the compositor, + this might race with the compositor. What can happen is that + repainting the window contents could be interrupted by the + compositor repainting the desktop. If the application gets + interrupted just after clearing the window but before + rendering the contents, the compositor will texture from a + blank buffer. The result is that the application window will + flicker between a blank window or half-rendered content. The + traditional way to avoid this is to render the new content + into a back buffer and then copy from there into the + compositor surface. The back buffer can be allocated on the + fly and just big enough to hold the new content, or the + application can keep a buffer around. Again, this is under + application control. + + + + + + In either case, the application must tell the compositor + which area of the surface holds new contents. When the + application renders directly to the shared buffer, the + compositor needs to be noticed that there is new content. + But also when exchanging buffers, the compositor doesn't + assume anything changed, and needs a request from the + application before it will repaint the desktop. The idea + that even if an application passes a new buffer to the + compositor, only a small part of the buffer may be + different, like a blinking cursor or a spinner. + +
+
+ Hardware Enabling for Wayland + + Typically, hardware enabling includes modesetting/display + and EGL/GLES2. On top of that Wayland needs a way to share + buffers efficiently between processes. There are two sides + to that, the client side and the server side. + + + On the client side we've defined a Wayland EGL platform. In + the EGL model, that consists of the native types + (EGLNativeDisplayType, EGLNativeWindowType and + EGLNativePixmapType) and a way to create those types. In + other words, it's the glue code that binds the EGL stack and + its buffer sharing mechanism to the generic Wayland API. The + EGL stack is expected to provide an implementation of the + Wayland EGL platform. The full API is in the wayland-egl.h + header. The open source implementation in the mesa EGL stack + is in wayland-egl.c and platform_wayland.c. + + + Under the hood, the EGL stack is expected to define a + vendor-specific protocol extension that lets the client side + EGL stack communicate buffer details with the compositor in + order to share buffers. The point of the wayland-egl.h API + is to abstract that away and just let the client create an + EGLSurface for a Wayland surface and start rendering. The + open source stack uses the drm Wayland extension, which lets + the client discover the drm device to use and authenticate + and then share drm (GEM) buffers with the compositor. + + + The server side of Wayland is the compositor and core UX for + the vertical, typically integrating task switcher, app + launcher, lock screen in one monolithic application. The + server runs on top of a modesetting API (kernel modesetting, + OpenWF Display or similar) and composites the final UI using + a mix of EGL/GLES2 compositor and hardware overlays if + available. Enabling modesetting, EGL/GLES2 and overlays is + something that should be part of standard hardware bringup. + The extra requirement for Wayland enabling is the + EGL_WL_bind_wayland_display extension that lets the + compositor create an EGLImage from a generic Wayland shared + buffer. It's similar to the EGL_KHR_image_pixmap extension + to create an EGLImage from an X pixmap. + + + The extension has a setup step where you have to bind the + EGL display to a Wayland display. Then as the compositor + receives generic Wayland buffers from the clients (typically + when the client calls eglSwapBuffers), it will be able to + pass the struct wl_buffer pointer to eglCreateImageKHR as + the EGLClientBuffer argument and with EGL_WAYLAND_BUFFER_WL + as the target. This will create an EGLImage, which can then + be used by the compositor as a texture or passed to the + modesetting code to use as an overlay plane. Again, this is + implemented by the vendor specific protocol extension, which + on the server side will receive the driver specific details + about the shared buffer and turn that into an EGL image when + the user calls eglCreateImageKHR. + +
+
diff --git a/doc/publican/Author_Group.xml b/doc/publican/sources/Author_Group.xml similarity index 100% rename from doc/publican/Author_Group.xml rename to doc/publican/sources/Author_Group.xml diff --git a/doc/publican/Book_Info.xml b/doc/publican/sources/Book_Info.xml similarity index 50% rename from doc/publican/Book_Info.xml rename to doc/publican/sources/Book_Info.xml index 897673a0..38e5bfce 100644 --- a/doc/publican/Book_Info.xml +++ b/doc/publican/sources/Book_Info.xml @@ -5,7 +5,7 @@ ]> Wayland - The Wayland Protocol + The Wayland display server Documentation 0.1 1 @@ -28,9 +28,9 @@ - - Wayland logo - + + Wayland logo + @@ -40,30 +40,30 @@ Copyright &YEAR; &HOLDER; - - 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: - + + 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 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. - + + 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. + diff --git a/doc/publican/sources/Compositors.xml b/doc/publican/sources/Compositors.xml new file mode 100644 index 00000000..eea627c7 --- /dev/null +++ b/doc/publican/sources/Compositors.xml @@ -0,0 +1,128 @@ + + +%BOOK_ENTITIES; +]> + + Types of Compositors + + + Compositors come in different types, depending on which + role they play in the overall architecture of the OS. + For instance, a + system compositor + can be used for booting the system, handling multiple user switching, a + possible console terminal emulator and so forth. A different compositor, a + session compositor + would provide the actual desktop environment. There are many ways for + different types of compositors to co-exist. + + + In this section, we introduce three types of Wayland compositors relying + on libwayland-server. + + +
+ System Compositor + + A system compositor can run from early boot until shutdown. + It effectively replaces the kernel vt system, and can tie in + with the systems graphical boot setup and multiseat support. + + + A system compositor can host different types of session + compositors, and let us switch between multiple sessions + (fast user switching, or secure/personal desktop switching). + + + A linux implementation of a system compositor will typically + use libudev, egl, kms, evdev and cairo. + + + For fullscreen clients, the system compositor can reprogram the + video scanout address to read directly from the client provided + buffer. + +
+
+ Session Compositor + + A session compositor is responsible for a single user session. + If a system compositor is present, the session compositor will + run nested under the system compositor. Nesting is feasible because + the protocol is asynchronous; roundtrips would be too expensive + when nesting is involved. If no system compositor is present, a + session compositor can run directly on the hw. + + + X applications can continue working under a session compositor + by means of a root-less X server that is activated on demand. + + + Possible examples for session compositors include + + + + gnome-shell + + + + + moblin + + + + + kwin + + + + + kmscon + + + + + rdp session + + + + + Weston with X11 or Wayland backend is a session compositor nested + in another session compositor. + + + + + fullscreen X session under Wayland + + + + +
+
+ Embedding Compositor + + X11 lets clients embed windows from other clients, or lets clients + copy pixmap contents rendered by another client into their window. + This is often used for applets in a panel, browser plugins and similar. + Wayland doesn't directly allow this, but clients can communicate GEM + buffer names out-of-band, for example, using D-Bus, or command line + arguments when the panel launches the applet. Another option is to + use a nested Wayland instance. For this, the Wayland server will have + to be a library that the host application links to. The host + application will then pass the Wayland server socket name to the + embedded application, and will need to implement the Wayland + compositor interface. The host application composites the client + surfaces as part of it's window, that is, in the web page or in the + panel. The benefit of nesting the Wayland server is that it provides + the requests the embedded client needs to inform the host about buffer + updates and a mechanism for forwarding input events from the host + application. + + + An example for this kind of setup is firefox embedding the flash + player as a kind of special-purpose compositor. + +
+
diff --git a/doc/publican/Foreword.xml b/doc/publican/sources/Foreword.xml similarity index 67% rename from doc/publican/Foreword.xml rename to doc/publican/sources/Foreword.xml index 080ed711..e6875a34 100644 --- a/doc/publican/Foreword.xml +++ b/doc/publican/sources/Foreword.xml @@ -1,5 +1,5 @@ - %BOOK_ENTITIES; @@ -9,7 +9,8 @@ Preface - This document describes its library API. Also, the Wayland protocol specification is shown + This document describes the (i) Wayland architecture, (ii) Wayland model of + operation and (iii) its library API. Also, the Wayland protocol specification is shown in the Appendix. This document is aimed primarily at Wayland developers and those looking to program with it; it does not cover application development. @@ -21,7 +22,7 @@ Yours, - the Wayland open-source community - November 2012 + the Wayland open-source community + November 2012 diff --git a/doc/publican/sources/Introduction.xml b/doc/publican/sources/Introduction.xml new file mode 100644 index 00000000..7516c33e --- /dev/null +++ b/doc/publican/sources/Introduction.xml @@ -0,0 +1,116 @@ + + +%BOOK_ENTITIES; +]> + + Introduction +
+ Motivation + + Most Linux and Unix-based systems rely on the X Window System (or + simply X) as the low-level protocol for building + bitmap graphics interfaces. On these systems, the X stack has grown to + encompass functionality arguably belonging in client libraries, + helper libraries, or the host operating system kernel. Support for + things like PCI resource management, display configuration management, + direct rendering, and memory management has been integrated into the X + stack, imposing limitations like limited support for standalone + applications, duplication in other projects (e.g. the Linux fb layer + or the DirectFB project), and high levels of complexity for systems + combining multiple elements (for example radeon memory map handling + between the fb driver and X driver, or VT switching). + + + Moreover, X has grown to incorporate modern features like offscreen + rendering and scene composition, but subject to the limitations of the + X architecture. For example, the X implementation of composition adds + additional context switches and makes things like input redirection + difficult. + + + + + + + + X architecture diagram + + + + + The diagram above illustrates the central role of the X server and + compositor in operations, and the steps required to get contents on to + the screen. + + + Over time, X developers came to understand the shortcomings of this + approach and worked to split things up. Over the past several years, + a lot of functionality has moved out of the X server and into + client-side libraries or kernel drivers. One of the first components + to move out was font rendering, with freetype and fontconfig providing + an alternative to the core X fonts. Direct rendering OpenGL as a + graphics driver in a client side library went through some iterations, + ending up as DRI2, which abstracted most of the direct rendering + buffer management from client code. Then cairo came along and provided + a modern 2D rendering library independent of X, and compositing + managers took over control of the rendering of the desktop as toolkits + like GTK+ and Qt moved away from using X APIs for rendering. Recently, + memory and display management have moved to the Linux kernel, further + reducing the scope of X and its driver stack. The end result is a + highly modular graphics stack. + + +
+ +
+ The compositing manager as the display server + + Wayland is a new display server and compositing protocol, and Weston + is the implementation of this protocol which builds on top of all the + components above. We are trying to distill out the functionality in + the X server that is still used by the modern Linux desktop. This + turns out to be not a whole lot. Applications can allocate their own + off-screen buffers and render their window contents directly, using + hardware accelerated libraries like libGL, or high quality software + implementations like those found in Cairo. In the end, what’s needed + is a way to present the resulting window surface for display, and a + way to receive and arbitrate input among multiple clients. This is + what Wayland provides, by piecing together the components already in + the eco-system in a slightly different way. + + + X will always be relevant, in the same way Fortran compilers and VRML + browsers are, but it’s time that we think about moving it out of the + critical path and provide it as an optional component for legacy + applications. + + + Overall, the philosophy of Wayland is to provide clients with a way to + manage windows and how their contents is displayed. Rendering is left + to clients, and system wide memory management interfaces are used to + pass buffer handles between clients and the compositing manager. + + + + + + + + Wayland architecture diagram + + + + + The figure above illustrates how Wayland clients interact with a + Wayland server. Note that window management and composition are + handled entirely in the server, significantly reducing complexity + while marginally improving performance through reduced context + switching. The resulting system is easier to build and extend than a + similar X system, because often changes need only be made in one + place. Or in the case of protocol extensions, two (rather than 3 or 4 + in the X case where window management and/or composition handling may + also need to be updated). + +
+
diff --git a/doc/publican/sources/Library.xml b/doc/publican/sources/Library.xml new file mode 100644 index 00000000..bc8c89ec --- /dev/null +++ b/doc/publican/sources/Library.xml @@ -0,0 +1,27 @@ + + +%BOOK_ENTITIES; +]> + + Wayland Library + + + The open-source reference implementation of Wayland protocol is split in two + C libraries, libwayland-server and + libwayland-client. Their main + responsibility is to handle the Inter-process communication + (IPC) with each other, therefore guaranteeing the + protocol objects marshaling and messages synchronization. + + + + This Chapter describes in detail each library's methods and their helpers, + aiming implementors who can use for building Wayland clients and servers; + respectively at and + . + + + + + diff --git a/doc/publican/sources/Preface.xml b/doc/publican/sources/Preface.xml new file mode 100644 index 00000000..61720a9c --- /dev/null +++ b/doc/publican/sources/Preface.xml @@ -0,0 +1,20 @@ + + +%BOOK_ENTITIES; +]> + + + Acknowledgments + + + TODO: Kristian has to fill up this with one or two paragraphs and a small + "thank you": http://en.wikipedia.org/wiki/Preface + + +Best, + + Kristian Høgsberg + + diff --git a/doc/publican/sources/Protocol.xml b/doc/publican/sources/Protocol.xml new file mode 100644 index 00000000..b79b6be1 --- /dev/null +++ b/doc/publican/sources/Protocol.xml @@ -0,0 +1,529 @@ + + +%BOOK_ENTITIES; +]> + + Wayland Protocol and Model of Operation +
+ Basic Principles + + The Wayland protocol is an asynchronous object oriented protocol. All + requests are method invocations on some object. The requests include + an object ID that uniquely identifies an object on the server. Each + object implements an interface and the requests include an opcode that + identifies which method in the interface to invoke. + + + The server sends back events to the client, each event is emitted from + an object. Events can be error conditions. The event includes the + object ID and the event opcode, from which the client can determine + the type of event. Events are generated both in response to requests + (in which case the request and the event constitutes a round trip) or + spontaneously when the server state changes. + + + + + + State is broadcast on connect, events are sent + out when state changes. Clients must listen for + these changes and cache the state. + There is no need (or mechanism) to query server state. + + + + + The server will broadcast the presence of a number of global objects, + which in turn will broadcast their current state. + + + + +
+
+ Code Generation + + The interfaces, requests and events are defined in + protocol/wayland.xml. + This xml is used to generate the function prototypes that can be used by + clients and compositors. + + + The protocol entry points are generated as inline functions which just + wrap the wl_proxy_* functions. The inline functions aren't + part of the library ABI and language bindings should generate their + own stubs for the protocol entry points from the xml. + +
+
+ Wire Format + + The protocol is sent over a UNIX domain stream socket, where the endpoint + usually is named wayland-0 + (although it can be changed via WAYLAND_DISPLAY + in the environment). The protocol is message-based. A + message sent by a client to the server is called request. A message + from the server to a client is called event. Every message is + structured as 32-bit words, values are represented in the host's + byte-order. + + + The message header has 2 words in it: + + + + The first word is the sender's object ID (32-bit). + + + + + The second has 2 parts of 16-bit. The upper 16-bits are the message + size in bytes, starting at the header (i.e. it has a minimum value of 8).The lower is the request/event opcode. + + + + The payload describes the request/event arguments. Every argument is always + aligned to 32-bits. Where padding is required, the value of padding bytes is + undefined. There is no prefix that describes the type, but it is + inferred implicitly from the xml specification. + + + + The representation of argument types are as follows: + + + int + uint + + + The value is the 32-bit value of the signed/unsigned + int. + + + + + fixed + + + Signed 24.8 decimal numbers. It is a signed decimal type which + offers a sign bit, 23 bits of integer precision and 8 bits of + decimal precision. This is exposed as an opaque struct with + conversion helpers to and from double and int on the C API side. + + + + + string + + + Starts with an unsigned 32-bit length, followed by the + string contents, including terminating null byte, then padding + to a 32-bit boundary. + + + + + object + + + 32-bit object ID. + + + + + new_id + + + The 32-bit object ID. On requests, the client + decides the ID. The only events with new_id are + advertisements of globals, and the server will use IDs below + 0x10000. + + + + + array + + + Starts with 32-bit array size in bytes, followed by the array + contents verbatim, and finally padding to a 32-bit boundary. + + + + + fd + + + The file descriptor is not stored in the message buffer, but in + the ancillary data of the UNIX domain socket message (msg_control). + + + + + +
+ +
+ Versioning + + Every interface is versioned and every protocol object implements a + particular version of its interface. For global objects, the maximum + version supported by the server is advertised with the global and the + actual verion of the created protocol object is determined by the + version argument passed to wl_registry.bind(). For objects that are + not globals, their version is inferred from the object that created + them. + + + In order to keep things sane, this has a few implications for + interface versions: + + + + The object creation hierarchy must be a tree. Otherwise, + infering object versions from the parent object becomes a much + more difficult to properly track. + + + + + When the version of an interface increases, so does the version + of its parent (recursively until you get to a global interface) + + + + + A global interface's version number acts like a counter for all + of its child interfaces. Whenever a child interface gets + modified, the global parent's interface version number also + increases (see above). The child interface then takes on the + same version number as the new version of its parent global + interface. + + + + + + To illustrate the above, consider the wl_compositor interface. It + has two children, wl_surface and wl_region. As of wayland version + 1.2, wl_surface and wl_compositor are both at version 3. If + something is added to the wl_region interface, both wl_region and + wl_compositor will get bumpped to version 4. If, afterwards, + wl_surface is changed, both wl_compositor and wl_surface will be at + version 5. In this way the global interface version is used as a + sort of "counter" for all of its child interfaces. This makes it + very simple to know the version of the child given the version of its + parent. The child is at the highest possible interface version that + is less than or equal to its parent's version. + + + It is worth noting a particular exception to the above versioning + scheme. The wl_display (and, by extension, wl_registry) interface + cannot change because it is the core protocol object and its version + is never advertised nor is there a mechanism to request a different + version. + +
+
+ Connect Time + + There is no fixed connection setup information, the server emits + multiple events at connect time, to indicate the presence and + properties of global objects: outputs, compositor, input devices. + +
+
+ Security and Authentication + + + + + mostly about access to underlying buffers, need new drm auth + mechanism (the grant-to ioctl idea), need to check the cmd stream? + + + + + getting the server socket depends on the compositor type, could + be a system wide name, through fd passing on the session dbus. + or the client is forked by the compositor and the fd is + already opened. + + + + +
+
+ Creating Objects + + Each object has a unique ID. The IDs are allocated by the entity + creating the object (either client or server). IDs allocated by the + client are in the range [1, 0xfeffffff] while IDs allocated by the + server are in the range [0xff000000, 0xffffffff]. The 0 ID is + reserved to represent a null or non-existant object. + + For efficiency purposes, the IDs are densely packed in the sense that + the ID N will not be used until N-1 has been used. Any ID allocation + algorithm that does not maintain this property is incompatible with + the implementation in libwayland. + +
+
+ Compositor + + The compositor is a global object, advertised at connect time. + + + See for the + protocol description. + +
+
+ Surfaces + + Surfaces are created by the client. + Clients don't know the global position of their surfaces, and + cannot access other clients surfaces. + + + See for the protocol + description. + +
+
+ Input + + A seat represents a group of input devices including mice, + keyboards and touchscreens. It has a keyboard and pointer + focus. Seats are global objects. Pointer events are delivered + in surface local coordinates. + + + The compositor maintains an implicit grab when a button is + pressed, to ensure that the corresponding button release + event gets delivered to the same surface. But there is no way + for clients to take an explicit grab. Instead, surfaces can + be mapped as 'popup', which combines transient window semantics + with a pointer grab. + + + To avoid race conditions, input events that are likely to + trigger further requests (such as button presses, key events, + pointer motions) carry serial numbers, and requests such as + wl_surface.set_popup require that the serial number of the + triggering event is specified. The server maintains a + monotonically increasing counter for these serial numbers. + + + Input events also carry timestamps with millisecond granularity. + Their base is undefined, so they can't be compared against + system time (as obtained with clock_gettime or gettimeofday). + They can be compared with each other though, and for instance + be used to identify sequences of button presses as double + or triple clicks. + + + See for the + protocol description. + + + Talk about: + + + + + keyboard map, change events + + + + + xkb on Wayland + + + + + multi pointer Wayland + + + + + + A surface can change the pointer image when the surface is the pointer + focus of the input device. Wayland doesn't automatically change the + pointer image when a pointer enters a surface, but expects the + application to set the cursor it wants in response to the pointer + focus and motion events. The rationale is that a client has to manage + changing pointer images for UI elements within the surface in response + to motion events anyway, so we'll make that the only mechanism for + setting or changing the pointer image. If the server receives a request + to set the pointer image after the surface loses pointer focus, the + request is ignored. To the client this will look like it successfully + set the pointer image. + + + The compositor will revert the pointer image back to a default image + when no surface has the pointer focus for that device. Clients can + revert the pointer image back to the default image by setting a NULL + image. + + + What if the pointer moves from one window which has set a special + pointer image to a surface that doesn't set an image in response to + the motion event? The new surface will be stuck with the special + pointer image. We can't just revert the pointer image on leaving a + surface, since if we immediately enter a surface that sets a different + image, the image will flicker. Broken app, I suppose. + +
+
+ Output + + An output is a global object, advertised at connect time or as it + comes and goes. + + + See for the protocol + description. + + + + + + + laid out in a big (compositor) coordinate system + + + + + basically xrandr over Wayland + + + + + geometry needs position in compositor coordinate system + + + + + events to advertise available modes, requests to move and change + modes + + + +
+
+ Data sharing between clients + + The Wayland protocol provides clients a mechanism for sharing + data that allows the implementation of copy-paste and + drag-and-drop. The client providing the data creates a + wl_data_source object and the clients + obtaining the data will see it as wl_data_offer + object. This interface allows the clients to agree on a mutually + supported mime type and transfer the data via a file descriptor + that is passed through the protocol. + + + The next section explains the negotiation between data source and + data offer objects. + explains how these objects are created and passed to different + clients using the wl_data_device interface + that implements copy-paste and drag-and-drop support. + + + See , + , + and + for + protocol descriptions. + + + MIME is defined in RFC's 2045-2049. A + + registry of MIME types is maintained by the Internet Assigned + Numbers Authority (IANA). + +
+ Data negotiation + + A client providing data to other clients will create a wl_data_source + object and advertise the mime types for the formats it supports for + that data through the wl_data_source.offer + request. On the receiving end, the data offer object will generate one + wl_data_offer.offer event for each supported mime + type. + + + The actual data transfer happens when the receiving client sends a + wl_data_offer.receive request. This request takes + a mime type and a file descriptor as arguments. This request will generate a + wl_data_source.send event on the sending client + with the same arguments, and the latter client is expected to write its + data to the given file descriptor using the chosen mime type. + +
+
+ Data devices + + Data devices glue data sources and offers together. A data device is + associated with a wl_seat and is obtained by the clients using the + wl_data_device_manager factory object, which is also responsible for + creating data sources. + + + Clients are informed of new data offers through the + wl_data_device.data_offer event. After this + event is generated the data offer will advertise the available mime + types. New data offers are introduced prior to their use for + copy-paste or drag-and-drop. + +
+ Selection + + Each data device has a selection data source. Clients create a data + source object using the device manager and may set it as the + current selection for a given data device. Whenever the current + selection changes, the client with keyboard focus receives a + wl_data_device.selection event. This event is + also generated on a client immediately before it receives keyboard + focus. + + + The data offer is introduced with + wl_data_device.data_offer event before the + selection event. + +
+
+ Drag and Drop + + A drag-and-drop operation is started using the + wl_data_device.start_drag request. This + requests causes a pointer grab that will generate enter, motion and + leave events on the data device. A data source is supplied as + argument to start_drag, and data offers associated with it are + supplied to clients surfaces under the pointer in the + wl_data_device.enter event. The data offer + is introduced to the client prior to the enter event with the + wl_data_device.data_offer event. + + + Clients are expected to provide feedback to the data sending client + by calling the wl_data_offer.accept request with + a mime type it accepts. If none of the advertised mime types is + supported by the receiving client, it should supply NULL to the + accept request. The accept request causes the sending client to + receive a wl_data_source.target event with the + chosen mime type. + + + When the drag ends, the receiving client receives a + wl_data_device.drop event at which it is expected + to transfer the data using the + wl_data_offer.receive request. + +
+
+
+
diff --git a/doc/publican/sources/Revision_History.xml b/doc/publican/sources/Revision_History.xml new file mode 100644 index 00000000..2c540fec --- /dev/null +++ b/doc/publican/sources/Revision_History.xml @@ -0,0 +1,7 @@ + + + 1-0 + krh + Initial version + + diff --git a/doc/publican/Wayland.ent b/doc/publican/sources/Wayland.ent similarity index 100% rename from doc/publican/Wayland.ent rename to doc/publican/sources/Wayland.ent diff --git a/doc/publican/sources/Wayland.xml b/doc/publican/sources/Wayland.xml new file mode 100644 index 00000000..24a98767 --- /dev/null +++ b/doc/publican/sources/Wayland.xml @@ -0,0 +1,17 @@ + + +%BOOK_ENTITIES; +]> + + + + + + + + + + + + diff --git a/doc/book/src/images/icon.svg b/doc/publican/sources/images/icon.svg similarity index 100% rename from doc/book/src/images/icon.svg rename to doc/publican/sources/images/icon.svg diff --git a/doc/publican/sources/images/wayland-architecture.png b/doc/publican/sources/images/wayland-architecture.png new file mode 100644 index 00000000..4f92e0fb Binary files /dev/null and b/doc/publican/sources/images/wayland-architecture.png differ diff --git a/doc/book/src/images/wayland.png b/doc/publican/sources/images/wayland.png similarity index 100% rename from doc/book/src/images/wayland.png rename to doc/publican/sources/images/wayland.png diff --git a/doc/publican/sources/images/x-architecture.png b/doc/publican/sources/images/x-architecture.png new file mode 100644 index 00000000..098205b5 Binary files /dev/null and b/doc/publican/sources/images/x-architecture.png differ diff --git a/doc/publican/xsl/doxygen-to-publican.xsl b/doc/publican/xsl/doxygen-to-publican.xsl deleted file mode 100644 index d7f29597..00000000 --- a/doc/publican/xsl/doxygen-to-publican.xsl +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - -
- Functions - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - Returns: - - - - - - - - - See also: - - - - Since: - - - - Note: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - <xsl:value-of select="compoundname" /> - <xsl:if test="normalize-space(briefdescription) != ''"> - - <xsl:apply-templates select="briefdescription" /> - </xsl:if> - - - - - - - - - - -
-
-
diff --git a/doc/publican/xsl/merge-mapcoords.xsl b/doc/publican/xsl/merge-mapcoords.xsl deleted file mode 100644 index 7adaca36..00000000 --- a/doc/publican/xsl/merge-mapcoords.xsl +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - -%BOOK_ENTITIES; -]> -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/publican/xsl/protocol-to-docbook.xsl b/doc/publican/xsl/protocol-to-docbook.xsl deleted file mode 100644 index 92f8d677..00000000 --- a/doc/publican/xsl/protocol-to-docbook.xsl +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - -%BOOK_ENTITIES; -]> -]]> - - - Wayland Protocol Specification - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - <xsl:value-of select="@name" /> - <!-- only show summary if it exists --> - <xsl:if test="description/@summary"> - - <xsl:value-of select="description/@summary" /> - </xsl:if> - - - - - -
- Requests provided by <xsl:value-of select="@name" /> - -
-
- -
- Events provided by <xsl:value-of select="@name" /> - -
-
- -
- Enums provided by <xsl:value-of select="@name" /> - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - id for the new - - - - - - - - - - - - - - - - - - - - - - - :: - - - - - - - :: - - - - - () - - - - - - - - - - - -
- - <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" /> - <xsl:if test="description/@summary"> - - <xsl:value-of select="description/@summary" /> - </xsl:if> - - - - - - - - - - - -
-
- - - -
- - <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" /> - <xsl:if test="@bitfield"> - - bitfield - </xsl:if> - <xsl:if test="description/@summary"> - - <xsl:value-of select="description/@summary" /> - </xsl:if> - - - - - - - -
-
- -
- - diff --git a/egl/meson.build b/egl/meson.build deleted file mode 100644 index b72c7a46..00000000 --- a/egl/meson.build +++ /dev/null @@ -1,61 +0,0 @@ -wayland_egl = library( - 'wayland-egl', - sources: [ - 'wayland-egl.c', - wayland_client_protocol_h - ], - include_directories: src_inc, - version: meson.project_version(), - install: true -) - -if get_option('tests') - wayland_egl_abi_check = executable('wayland-egl-abi-check', 'wayland-egl-abi-check.c') - test('wayland-egl abi check', wayland_egl_abi_check) - - if get_option('default_library') != 'static' - nm_path = find_program(['llvm-nm', 'nm']).full_path() - wayland_egl_shared = wayland_egl - if get_option('default_library') == 'both' - wayland_egl_shared = wayland_egl.get_shared_lib() - endif - test( - 'wayland-egl symbols check', - find_program('wayland-egl-symbols-check'), - depends: wayland_egl, - env: [ - 'WAYLAND_EGL_LIB=@0@'.format(wayland_egl_shared.full_path()), - 'NM=@0@'.format(nm_path) - ] - ) - endif -endif - -install_headers([ - 'wayland-egl.h', - 'wayland-egl-core.h', - 'wayland-egl-backend.h' -]) - -pkgconfig.generate( - name: 'wayland-egl', - description: 'Frontend wayland-egl library', - version: '18.1.0', - requires: 'wayland-client', - libraries: wayland_egl -) - -pkgconfig.generate( - name: 'wayland-egl-backend', - description: 'Backend wayland-egl interface', - version: '3' -) - -wayland_egl_dep = declare_dependency( - link_with: wayland_egl, - include_directories: [ root_inc, include_directories('.') ], -) - -if meson.version().version_compare('>= 0.54.0') - meson.override_dependency('wayland-egl', wayland_egl_dep) -endif diff --git a/egl/wayland-egl-abi-check.c b/egl/wayland-egl-abi-check.c deleted file mode 100644 index ea877d0e..00000000 --- a/egl/wayland-egl-abi-check.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. - * - * 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 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 /* offsetof */ -#include /* printf */ - -#include "wayland-egl-backend.h" /* Current struct wl_egl_window implementation */ - -/* - * Following are previous implementations of wl_egl_window. - * - * DO NOT EVER CHANGE! - */ - -/* From: 214fc6e850 - Benjamin Franzke : egl: Implement libwayland-egl */ -struct wl_egl_window_v0 { - struct wl_surface *surface; - - int width; - int height; - int dx; - int dy; - - int attached_width; - int attached_height; -}; - -/* From: ca3ed3e024 - Ander Conselvan de Oliveira : egl/wayland: Don't invalidate drawable on swap buffers */ -struct wl_egl_window_v1 { - struct wl_surface *surface; - - int width; - int height; - int dx; - int dy; - - int attached_width; - int attached_height; - - void *private; - void (*resize_callback)(struct wl_egl_window *, void *); -}; - -/* From: 690ead4a13 - Stencel, Joanna : egl/wayland-egl: Fix for segfault in dri2_wl_destroy_surface. */ -#define WL_EGL_WINDOW_VERSION_v2 2 -struct wl_egl_window_v2 { - struct wl_surface *surface; - - int width; - int height; - int dx; - int dy; - - int attached_width; - int attached_height; - - void *private; - void (*resize_callback)(struct wl_egl_window *, void *); - void (*destroy_window_callback)(void *); -}; - -/* From: 2d5d61bc49 - Miguel A. Vico : wayland-egl: Make wl_egl_window a versioned struct */ -#define WL_EGL_WINDOW_VERSION_v3 3 -struct wl_egl_window_v3 { - const intptr_t version; - - int width; - int height; - int dx; - int dy; - - int attached_width; - int attached_height; - - void *driver_private; - void (*resize_callback)(struct wl_egl_window *, void *); - void (*destroy_window_callback)(void *); - - struct wl_surface *surface; -}; - - -/* This program checks we keep a backwards-compatible struct wl_egl_window - * definition whenever it is modified in wayland-egl-backend.h. - * - * The previous definition should be added above as a new struct - * wl_egl_window_vN, and the appropriate checks should be added below - */ - -#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) - -#define CHECK_RENAMED_MEMBER(a_ver, b_ver, a_member, b_member) \ - do { \ - if (offsetof(struct wl_egl_window ## a_ver, a_member) != \ - offsetof(struct wl_egl_window ## b_ver, b_member)) { \ - printf("Backwards incompatible change detected!\n " \ - "offsetof(struct wl_egl_window" #a_ver "::" #a_member ") != " \ - "offsetof(struct wl_egl_window" #b_ver "::" #b_member ")\n"); \ - return 1; \ - } \ - \ - if (MEMBER_SIZE(struct wl_egl_window ## a_ver, a_member) != \ - MEMBER_SIZE(struct wl_egl_window ## b_ver, b_member)) { \ - printf("Backwards incompatible change detected!\n " \ - "MEMBER_SIZE(struct wl_egl_window" #a_ver "::" #a_member ") != " \ - "MEMBER_SIZE(struct wl_egl_window" #b_ver "::" #b_member ")\n"); \ - return 1; \ - } \ - } while (0) - -#define CHECK_MEMBER(a_ver, b_ver, member) CHECK_RENAMED_MEMBER(a_ver, b_ver, member, member) -#define CHECK_MEMBER_CURRENT(a_ver, member) CHECK_MEMBER(a_ver,, member) - -#define CHECK_SIZE(a_ver, b_ver) \ - do { \ - if (sizeof(struct wl_egl_window ## a_ver) > \ - sizeof(struct wl_egl_window ## b_ver)) { \ - printf("Backwards incompatible change detected!\n " \ - "sizeof(struct wl_egl_window" #a_ver ") > " \ - "sizeof(struct wl_egl_window" #b_ver ")\n"); \ - return 1; \ - } \ - } while (0) - -#define CHECK_SIZE_CURRENT(a_ver) \ - do { \ - if (sizeof(struct wl_egl_window ## a_ver) != \ - sizeof(struct wl_egl_window)) { \ - printf("Backwards incompatible change detected!\n " \ - "sizeof(struct wl_egl_window" #a_ver ") != " \ - "sizeof(struct wl_egl_window)\n"); \ - return 1; \ - } \ - } while (0) - -#define CHECK_VERSION(a_ver, b_ver) \ - do { \ - if ((WL_EGL_WINDOW_VERSION ## a_ver) >= \ - (WL_EGL_WINDOW_VERSION ## b_ver)) { \ - printf("Backwards incompatible change detected!\n " \ - "WL_EGL_WINDOW_VERSION" #a_ver " >= " \ - "WL_EGL_WINDOW_VERSION" #b_ver "\n"); \ - return 1; \ - } \ - } while (0) - -#define CHECK_VERSION_CURRENT(a_ver) \ - do { \ - if ((WL_EGL_WINDOW_VERSION ## a_ver) != \ - (WL_EGL_WINDOW_VERSION)) { \ - printf("Backwards incompatible change detected!\n " \ - "WL_EGL_WINDOW_VERSION" #a_ver " != " \ - "WL_EGL_WINDOW_VERSION\n"); \ - return 1; \ - } \ - } while (0) - -int main(int argc, char **argv) -{ - /* Check wl_egl_window_v1 ABI against wl_egl_window_v0 */ - CHECK_MEMBER(_v0, _v1, surface); - CHECK_MEMBER(_v0, _v1, width); - CHECK_MEMBER(_v0, _v1, height); - CHECK_MEMBER(_v0, _v1, dx); - CHECK_MEMBER(_v0, _v1, dy); - CHECK_MEMBER(_v0, _v1, attached_width); - CHECK_MEMBER(_v0, _v1, attached_height); - - CHECK_SIZE(_v0, _v1); - - /* Check wl_egl_window_v2 ABI against wl_egl_window_v1 */ - CHECK_MEMBER(_v1, _v2, surface); - CHECK_MEMBER(_v1, _v2, width); - CHECK_MEMBER(_v1, _v2, height); - CHECK_MEMBER(_v1, _v2, dx); - CHECK_MEMBER(_v1, _v2, dy); - CHECK_MEMBER(_v1, _v2, attached_width); - CHECK_MEMBER(_v1, _v2, attached_height); - CHECK_MEMBER(_v1, _v2, private); - CHECK_MEMBER(_v1, _v2, resize_callback); - - CHECK_SIZE(_v1, _v2); - - /* Check wl_egl_window_v3 ABI against wl_egl_window_v2 */ - CHECK_RENAMED_MEMBER(_v2, _v3, surface, version); - CHECK_MEMBER (_v2, _v3, width); - CHECK_MEMBER (_v2, _v3, height); - CHECK_MEMBER (_v2, _v3, dx); - CHECK_MEMBER (_v2, _v3, dy); - CHECK_MEMBER (_v2, _v3, attached_width); - CHECK_MEMBER (_v2, _v3, attached_height); - CHECK_RENAMED_MEMBER(_v2, _v3, private, driver_private); - CHECK_MEMBER (_v2, _v3, resize_callback); - CHECK_MEMBER (_v2, _v3, destroy_window_callback); - - CHECK_SIZE (_v2, _v3); - CHECK_VERSION(_v2, _v3); - - /* Check current wl_egl_window ABI against wl_egl_window_v3 */ - CHECK_MEMBER_CURRENT(_v3, version); - CHECK_MEMBER_CURRENT(_v3, width); - CHECK_MEMBER_CURRENT(_v3, height); - CHECK_MEMBER_CURRENT(_v3, dx); - CHECK_MEMBER_CURRENT(_v3, dy); - CHECK_MEMBER_CURRENT(_v3, attached_width); - CHECK_MEMBER_CURRENT(_v3, attached_height); - CHECK_MEMBER_CURRENT(_v3, driver_private); - CHECK_MEMBER_CURRENT(_v3, resize_callback); - CHECK_MEMBER_CURRENT(_v3, destroy_window_callback); - CHECK_MEMBER_CURRENT(_v3, surface); - - CHECK_SIZE_CURRENT (_v3); - CHECK_VERSION_CURRENT(_v3); - - return 0; -} diff --git a/egl/wayland-egl-backend.h b/egl/wayland-egl-backend.h deleted file mode 100644 index e5287b76..00000000 --- a/egl/wayland-egl-backend.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright © 2011 Benjamin Franzke - * - * 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. - * - * Authors: - * Benjamin Franzke - */ - -#ifndef _WAYLAND_EGL_PRIV_H -#define _WAYLAND_EGL_PRIV_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * NOTE: This version must be kept in sync with the version field in the - * wayland-egl-backend pkgconfig file generated in meson.build. - */ -#define WL_EGL_WINDOW_VERSION 3 - -struct wl_surface; - -struct wl_egl_window { - const intptr_t version; - - int width; - int height; - int dx; - int dy; - - int attached_width; - int attached_height; - - void *driver_private; - void (*resize_callback)(struct wl_egl_window *, void *); - void (*destroy_window_callback)(void *); - - struct wl_surface *surface; -}; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/egl/wayland-egl-core.h b/egl/wayland-egl-core.h deleted file mode 100644 index b3ab5124..00000000 --- a/egl/wayland-egl-core.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * Copyright © 2011 Benjamin Franzke - * - * 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. - */ - -#ifndef WAYLAND_EGL_CORE_H -#define WAYLAND_EGL_CORE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define WL_EGL_PLATFORM 1 - -struct wl_egl_window; -struct wl_surface; - -struct wl_egl_window * -wl_egl_window_create(struct wl_surface *surface, - int width, int height); - -void -wl_egl_window_destroy(struct wl_egl_window *egl_window); - -void -wl_egl_window_resize(struct wl_egl_window *egl_window, - int width, int height, - int dx, int dy); - -void -wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, - int *width, int *height); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/egl/wayland-egl-symbols-check b/egl/wayland-egl-symbols-check deleted file mode 100755 index d04fd042..00000000 --- a/egl/wayland-egl-symbols-check +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh -set -eu - -RET=0 -LIB=${WAYLAND_EGL_LIB} - -if ! test -f "$LIB"; then - echo "Test binary \"$LIB\" does not exist" - exit 99 -fi - -if ! test -n "$NM"; then - echo "nm environment variable not set" - exit 99 -fi - -AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" - -# Official ABI, taken from the header. -REQ_FUNCS="wl_egl_window_resize -wl_egl_window_create -wl_egl_window_destroy -wl_egl_window_get_attached_size -" - -NEW_ABI=$(echo "$AVAIL_FUNCS" | while read func; do - echo "$func" | grep -q "^_" && continue - echo "$REQ_FUNCS" | grep -q "^$func$" && continue - - echo $func -done) - -if test -n "$NEW_ABI"; then - echo "New ABI detected - If intentional, update the test." - echo "$NEW_ABI" - RET=1 -fi - -REMOVED_ABI=$(echo "$REQ_FUNCS" | while read func; do - echo "$AVAIL_FUNCS" | grep -q "^$func$" && continue - - echo $func -done) - -if test -n "$REMOVED_ABI"; then - echo "ABI break detected - Required symbol(s) no longer exported!" - echo "$REMOVED_ABI" - RET=1 -fi - -exit $RET diff --git a/egl/wayland-egl.c b/egl/wayland-egl.c deleted file mode 100644 index 36a34712..00000000 --- a/egl/wayland-egl.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * Copyright © 2011 Benjamin Franzke - * - * 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. - * - * Authors: - * Kristian Høgsberg - * Benjamin Franzke - */ - -#include -#include - -#include "wayland-egl.h" -#include "wayland-egl-backend.h" -#include "wayland-util.h" - - -/** Resize the EGL window - * - * \param egl_window A pointer to a struct wl_egl_window - * \param width The new width - * \param height The new height - * \param dx Offset on the X axis - * \param dy Offset on the Y axis - * - * Note that applications should prefer using the wl_surface.offset request if - * the associated wl_surface has the interface version 5 or higher. - * - * If the wl_surface.offset request is used, applications MUST pass 0 to both - * dx and dy. - */ -WL_EXPORT void -wl_egl_window_resize(struct wl_egl_window *egl_window, - int width, int height, - int dx, int dy) -{ - if (width <= 0 || height <= 0) - return; - - egl_window->width = width; - egl_window->height = height; - egl_window->dx = dx; - egl_window->dy = dy; - - if (egl_window->resize_callback) - egl_window->resize_callback(egl_window, egl_window->driver_private); -} - -WL_EXPORT struct wl_egl_window * -wl_egl_window_create(struct wl_surface *surface, - int width, int height) -{ - struct wl_egl_window *egl_window; - - if (width <= 0 || height <= 0) - return NULL; - - egl_window = calloc(1, sizeof *egl_window); - if (!egl_window) - return NULL; - - /* Cast away the constness to set the version number. - * - * We want the const notation since it gives an explicit - * feedback to the backend implementation, should it try to - * change it. - * - * The latter in itself is not too surprising as these days APIs - * tend to provide bidirectional version field. - */ - intptr_t *version = (intptr_t *)&egl_window->version; - *version = WL_EGL_WINDOW_VERSION; - - egl_window->surface = surface; - - egl_window->width = width; - egl_window->height = height; - - return egl_window; -} - -WL_EXPORT void -wl_egl_window_destroy(struct wl_egl_window *egl_window) -{ - if (egl_window->destroy_window_callback) - egl_window->destroy_window_callback(egl_window->driver_private); - free(egl_window); -} - -WL_EXPORT void -wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, - int *width, int *height) -{ - if (width) - *width = egl_window->attached_width; - if (height) - *height = egl_window->attached_height; -} diff --git a/egl/wayland-egl.h b/egl/wayland-egl.h deleted file mode 100644 index 279dcb8b..00000000 --- a/egl/wayland-egl.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * Copyright © 2011 Benjamin Franzke - * - * 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. - */ - -#ifndef WAYLAND_EGL_H -#define WAYLAND_EGL_H - -#include -#include "wayland-egl-core.h" - -#endif diff --git a/git-blame-ignore-revs b/git-blame-ignore-revs deleted file mode 120000 index c17c5dd1..00000000 --- a/git-blame-ignore-revs +++ /dev/null @@ -1 +0,0 @@ -.git-blame-ignore-revs \ No newline at end of file diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 00000000..38066ddf --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1,5 @@ +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 diff --git a/meson.build b/meson.build deleted file mode 100644 index cb6c2385..00000000 --- a/meson.build +++ /dev/null @@ -1,145 +0,0 @@ -project( - 'wayland', 'c', - version: '1.25.90', - license: 'MIT', - meson_version: '>= 0.64.0', - default_options: [ - 'warning_level=2', - 'buildtype=debugoptimized', - 'c_std=c99', - ] -) - -fs = import('fs') -pkgconfig = import('pkgconfig') - -wayland_version = meson.project_version().split('.') - -config_h = configuration_data() -config_h.set_quoted('PACKAGE', meson.project_name()) -config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) - -cc_args = [] -if host_machine.system() not in ['freebsd', 'openbsd'] - cc_args += ['-D_POSIX_C_SOURCE=200809L'] -endif -add_project_arguments(cc_args, language: 'c') - -compiler_flags = [ - '-Wno-unused-parameter', - '-Wstrict-prototypes', - '-Wmissing-prototypes', - '-fvisibility=hidden', -] - -cc = meson.get_compiler('c') -add_project_arguments( - cc.get_supported_arguments(compiler_flags), - language: 'c' -) - -foreach h: [ 'sys/prctl.h', 'sys/procctl.h', 'sys/ucred.h' ] - config_h.set('HAVE_' + h.underscorify().to_upper(), cc.has_header(h)) -endforeach - -have_funcs = [ - 'accept4', - 'mkostemp', - 'posix_fallocate', - 'prctl', - 'memfd_create', - 'mremap', - 'strndup', - 'gettid', -] -foreach f: have_funcs - config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f)) -endforeach -config_h.set10('HAVE_XUCRED_CR_PID', cc.has_member('struct xucred', 'cr_pid', prefix : '#include ')) -have_broken_msg_cmsg_cloexec = false -if host_machine.system() == 'freebsd' - have_broken_msg_cmsg_cloexec = not cc.compiles(''' -#include /* To get __FreeBSD_version. */ -#if __FreeBSD_version < 1300502 || \ - (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400006) -/* - * FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015 and - * 2021. Check if we are compiling against a version that includes the fix - * (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211). - */ -#error "Broken MSG_CMSG_CLOEXEC" -#endif -''', name : 'MSG_CMSG_CLOEXEC works correctly') -endif -config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec) - -if get_option('libraries') - if host_machine.system() in ['freebsd', 'openbsd'] - # When building for FreeBSD, epoll(7) is provided by a userspace - # wrapper around kqueue(2). - epoll_dep = dependency('epoll-shim') - else - # Otherwise, assume that epoll(7) is supported natively. - epoll_dep = [] - endif - ffi_dep = dependency('libffi') - - decls = [ - { 'header': 'sys/signalfd.h', 'symbol': 'SFD_CLOEXEC' }, - { 'header': 'sys/timerfd.h', 'symbol': 'TFD_CLOEXEC' }, - { 'header': 'time.h', 'symbol': 'CLOCK_MONOTONIC' }, - ] - - foreach d: decls - if not cc.has_header_symbol(d['header'], d['symbol'], dependencies: epoll_dep, args: cc_args) - error('@0@ is needed to compile Wayland libraries'.format(d['symbol'])) - endif - endforeach - - rt_dep = [] - if not cc.has_function('clock_gettime', prefix: '#include ') - rt_dep = cc.find_library('rt') - if not cc.has_function('clock_gettime', prefix: '#include ', dependencies: rt_dep, args: cc_args) - error('clock_gettime not found') - endif - endif -endif - -configure_file( - output: 'config.h', - configuration: config_h, -) - -wayland_protocol_xml = files('protocol/wayland.xml') - -root_inc = include_directories('.') -protocol_inc = include_directories('protocol') -src_inc = include_directories('src') - -subdir('src') - -if get_option('libraries') - subdir('cursor') - subdir('egl') -endif -if get_option('tests') - subdir('tests') -endif -if get_option('documentation') - subdir('doc') -endif - -if get_option('scanner') - install_data([ - 'wayland-scanner.mk', - 'protocol/wayland.xml', - 'protocol/wayland.dtd', - ], - install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'wayland'), - ) - - install_data( - [ 'wayland-scanner.m4' ], - install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'aclocal'), - ) -endif diff --git a/meson_options.txt b/meson_options.txt deleted file mode 100644 index 02c2346a..00000000 --- a/meson_options.txt +++ /dev/null @@ -1,28 +0,0 @@ -option('libraries', - description: 'Compile Wayland libraries', - type: 'boolean', - value: true) -option('scanner', - description: 'Compile wayland-scanner binary', - type: 'boolean', - value: true) -option('tests', - description: 'Compile Wayland tests', - type: 'boolean', - value: true) -option('documentation', - description: 'Build the documentation (requires Doxygen, dot, xmlto, xsltproc)', - type: 'boolean', - value: true) -option('docbook_validation', - type: 'boolean', - value: false, - description: 'Validate the intermediate DocBook XML during the documentation build') -option('dtd_validation', - description: 'Validate the protocol DTD (requires libxml2)', - type: 'boolean', - value: true) -option('icon_directory', - description: 'Location used to look for cursors (defaults to ${datadir}/icons if unset)', - type: 'string', - value: '') diff --git a/protocol/generate-shm-formats.py b/protocol/generate-shm-formats.py deleted file mode 100755 index c56642e1..00000000 --- a/protocol/generate-shm-formats.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python3 - -# This script synchronizes wayland.xml's wl_shm.format enum with drm_fourcc.h. -# Invoke it to update wayland.xml, then manually check the changes applied. -# -# Requires Python 3, python-lxml, a C compiler and pkg-config. - -import os -import subprocess -import sys -import tempfile -# We need lxml instead of the standard library because we want -# Element.sourceline -from lxml import etree as ElementTree - -proto_dir = os.path.dirname(os.path.realpath(__file__)) -wayland_proto = proto_dir + "/wayland.xml" - -cc = os.getenv("CC", "cc") -pkg_config = os.getenv("PKG_CONFIG", "pkg-config") - -# Find drm_fourcc.h -version = subprocess.check_output([pkg_config, "libdrm", - "--modversion"]).decode().strip() -cflags = subprocess.check_output([pkg_config, "libdrm", - "--cflags-only-I"]).decode().strip().split() -libdrm_include = None -for include_flag in cflags: - if not include_flag.startswith("-I"): - raise Exception("Expected one include dir for libdrm") - include_dir = include_flag[2:] - if include_dir.endswith("/libdrm"): - libdrm_include = include_dir - fourcc_include = libdrm_include + "/drm_fourcc.h" -if libdrm_include == None: - raise Exception("Failed to find libdrm include dir") - -print("Using libdrm " + version, file=sys.stderr) - -def drm_format_to_wl(ident): - return ident.replace("DRM_FORMAT_", "").lower() - -# Collect DRM format constant names -ident_list = [] -descriptions = {} -prev_comment = None -with open(fourcc_include) as input_file: - for l in input_file.readlines(): - l = l.strip() - - # Collect comments right before format definitions - if l.startswith("/*") and l.endswith("*/"): - prev_comment = l[2:-2] - continue - desc = prev_comment - prev_comment = None - - # Recognize format definitions - parts = l.split() - if len(parts) < 3 or parts[0] != "#define": - continue - ident = parts[1] - if not ident.startswith("DRM_FORMAT_") or ident.startswith( - "DRM_FORMAT_MOD_"): - continue - - ident_list.append(ident) - - # Prefer in-line comments - if l.endswith("*/"): - desc = l[l.rfind("/*") + 2:-2] - if desc != None: - descriptions[drm_format_to_wl(ident)] = desc.strip() - -# Collect DRM format values -idents = {} -with tempfile.TemporaryDirectory() as work_dir: - c_file_name = work_dir + "/print-formats.c" - exe_file_name = work_dir + "/print-formats" - - with open(c_file_name, "w+") as c_file: - c_file.write('#include \n') - c_file.write('#include \n') - c_file.write('#include \n') - c_file.write('#include \n') - c_file.write('\n') - c_file.write('int main(void) {\n') - for ident in ident_list: - c_file.write('printf("0x%" PRIX64 "\\n", (uint64_t)' + ident + ');\n') - c_file.write('}\n') - - subprocess.check_call([cc, "-Wall", "-Wextra", "-o", exe_file_name, - c_file_name] + cflags) - output = subprocess.check_output([exe_file_name]).decode().strip() - for i, val in enumerate(output.splitlines()): - idents[ident_list[i]] = val - -# We don't need those -del idents["DRM_FORMAT_BIG_ENDIAN"] -del idents["DRM_FORMAT_INVALID"] -del idents["DRM_FORMAT_RESERVED"] - -# Convert from DRM constants to Wayland wl_shm.format entries -formats = {} -for ident, val in idents.items(): - formats[drm_format_to_wl(ident)] = val.lower() -# Special case for ARGB8888 and XRGB8888 -formats["argb8888"] = "0" -formats["xrgb8888"] = "1" - -print("Loaded {} formats from drm_fourcc.h".format(len(formats)), file=sys.stderr) - -tree = ElementTree.parse("wayland.xml") -root = tree.getroot() -wl_shm_format = root.find("./interface[@name='wl_shm']/enum[@name='format']") -if wl_shm_format == None: - raise Exception("wl_shm.format not found in wayland.xml") - -# Remove formats we already know about -last_line = None -for node in wl_shm_format: - if node.tag != "entry": - continue - fmt = node.attrib["name"] - val = node.attrib["value"] - if fmt not in formats: - raise Exception("Format present in wl_shm.formats but not in " - "drm_fourcc.h: " + fmt) - if val != formats[fmt]: - raise Exception("Format value in wl_shm.formats ({}) differs " - "from value in drm_fourcc.h ({}) for format {}" - .format(val, formats[fmt], fmt)) - del formats[fmt] - last_line = node.sourceline -if last_line == None: - raise Exception("Expected at least one existing wl_shm.format entry") - -print("Adding {} formats to wayland.xml...".format(len(formats)), file=sys.stderr) - -# Append new formats -new_wayland_proto = wayland_proto + ".new" -with open(new_wayland_proto, "w+") as output_file, \ - open(wayland_proto) as input_file: - for i, l in enumerate(input_file.readlines()): - output_file.write(l) - if i + 1 == last_line: - for fmt, val in formats.items(): - output_file.write(' \n') -os.rename(new_wayland_proto, wayland_proto) diff --git a/protocol/tests.xml b/protocol/tests.xml deleted file mode 100644 index 22d80a10..00000000 --- a/protocol/tests.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Copyright © 2017 Samsung Electronics Co., 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. - - - - - A trivial interface for fd passing tests. - - - - - - - - - - - - - - - Tells this fd passer object about another one to send events - to for more complicated fd leak tests. - - - - - diff --git a/protocol/wayland.dtd b/protocol/wayland.dtd index ae8340d6..b8b15731 100644 --- a/protocol/wayland.dtd +++ b/protocol/wayland.dtd @@ -1,36 +1,29 @@ - + - - - - - - - diff --git a/protocol/wayland.xml b/protocol/wayland.xml index 11f0de36..bb457bcf 100644 --- a/protocol/wayland.xml +++ b/protocol/wayland.xml @@ -6,26 +6,26 @@ Copyright © 2010-2011 Intel Corporation Copyright © 2012-2013 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: + 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 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. + 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. @@ -36,84 +36,74 @@ - The sync request asks the server to emit the 'done' event - on the returned wl_callback object. Since requests are - handled in-order and events are delivered in-order, this can - be used as a barrier to ensure all previous requests and the - resulting events have been handled. + The sync request asks the server to emit the 'done' event + on the returned wl_callback object. Since requests are + handled in-order and events are delivered in-order, this can + be used as a barrier to ensure all previous requests and the + resulting events have been handled. - The object returned by this request will be destroyed by the - compositor after the callback is fired and as such the client must not - attempt to use it after that point. + The object returned by this request will be destroyed by the + compositor after the callback is fired and as such the client must not + attempt to use it after that point. - The callback_data passed in the callback is undefined and should be ignored. + The callback_data passed in the callback is the event serial. - + - This request creates a registry object that allows the client - to list and bind the global objects available from the - compositor. - - It should be noted that the server side resources consumed in - response to a get_registry request can only be released when the - client disconnects, not when the client side proxy is destroyed. - Therefore, clients should invoke get_registry as infrequently as - possible to avoid wasting memory. + This request creates a registry object that allows the client + to list and bind the global objects available from the + compositor. - + - The error event is sent out when a fatal (non-recoverable) - error has occurred. The object_id argument is the object - where the error occurred, most often in response to a request - to that object. The code identifies the error and is defined - by the object interface. As such, each interface defines its - own set of error codes. The message is a brief description - of the error, for (debugging) convenience. + The error event is sent out when a fatal (non-recoverable) + error has occurred. The object_id argument is the object + where the error occurred, most often in response to a request + to that object. The code identifies the error and is defined + by the object interface. As such, each interface defines its + own set of error codes. The message is an brief description + of the error, for (debugging) convenience. - - - + + + - These errors are global and can be emitted in response to any - server request. + These errors are global and can be emitted in response to any + server request. + summary="server couldn't find object"/> + summary="method doesn't exist on the specified interface"/> - + summary="server is out of memory"/> - This event is used internally by the object ID management - logic. When a client deletes an object that it had created, - the server will send this event to acknowledge that it has - seen the delete request. When the client receives this event, - it will know that it can safely reuse the object ID. + This event is used internally by the object ID management + logic. When a client deletes an object, the server will send + this event to acknowledge that it has seen the delete request. + When the client receive this event, it will know that it can + safely reuse the object ID. - + - The singleton global registry object. The server has a number of - global objects that are available to all clients. These objects + The global registry object. The server has a number of global + objects that are available to all clients. These objects typically represent an actual object in the server (for example, an input device) or they are singleton objects that provide extension functionality. @@ -136,61 +126,57 @@ - Binds a new, client-created object to the server using the + Binds a new, client-created object to the server using the specified name as the identifier. - - + + - Notify the client of global objects. + Notify the client of global objects. The event notifies the client that a global object with the given name is now available, and it implements the given version of the given interface. - - - + + + - Notify the client of removed global objects. + Notify the client of removed global objects. This event notifies the client that the global identified by name is no longer available. If the client bound to the global using the bind request, the client should now destroy that object. - The object remains valid and requests to the object will be - ignored until the client destroys it, to avoid races between - the global going away and a client sending a request to it. + The object remains valid and requests to the object will be + ignored until the client destroys it, to avoid races between + the global going away and a client sending a request to it. - + - + Clients can handle the 'done' event to get notified when the related request is done. - - Note, because wl_callback objects are created from multiple independent - factory interfaces, the wl_callback interface is frozen at version 1. - - + - Notify the client when the related request is done. + Notify the client when the related request is done. - + - + A compositor. This object is a singleton global. The compositor is in charge of combining the contents of multiple @@ -199,28 +185,20 @@ - Ask the compositor to create a new surface. + Ask the compositor to create a new surface. - + - Ask the compositor to create a new region. - - - - - - - - - This request destroys the wl_compositor. This has no effect on any other objects. + Ask the compositor to create a new region. + - + The wl_shm_pool object encapsulates a piece of memory shared between the compositor and client. Through the wl_shm_pool @@ -233,69 +211,65 @@ - Create a wl_buffer object from the pool. + Create a wl_buffer object from the pool. - The buffer is created offset bytes into the pool and has - width and height as specified. The stride argument specifies - the number of bytes from the beginning of one row to the beginning - of the next. The format is the pixel format of the buffer and - must be one of those advertised through the wl_shm.format event. + The buffer is created offset bytes into the pool and has + width and height as specified. The stride arguments specifies + the number of bytes from beginning of one row to the beginning + of the next. The format is the pixel format of the buffer and + must be one of those advertised through the wl_shm.format event. - A buffer will keep a reference to the pool it was created from - so it is valid to destroy the pool immediately after creating - a buffer from it. + A buffer will keep a reference to the pool it was created from + so it is valid to destroy the pool immediately after creating + a buffer from it. - - - - - - + + + + + + + - Destroy the shared memory pool. + Destroy the shared memory pool. - The mmapped memory will be released when all - buffers that have been created from this pool - are gone. + The mmapped memory will be released when all + buffers that have been created from this pool + are gone. - This request will cause the server to remap the backing memory - for the pool from the file descriptor passed when the pool was - created, but using the new size. This request can only be - used to make the pool bigger. - - This request only changes the amount of bytes that are mmapped - by the server and does not touch the file corresponding to the - file descriptor passed at creation time. It is the client's - responsibility to ensure that the file is at least as big as - the new pool size. + This request will cause the server to remap the backing memory + for the pool from the file descriptor passed when the pool was + created, but using the new size. This request can only be + used to make the pool bigger. - + + - + - A singleton global object that provides support for shared + A global singleton object that provides support for shared memory. Clients can create wl_shm_pool objects using the create_pool request. - On binding the wl_shm object one or more format events - are emitted to inform clients about the valid pixel formats + At connection setup time, the wl_shm object emits one or more + format events to inform clients about the valid pixel formats that can be used for buffers. - These errors can be emitted in response to wl_shm requests. + These errors can be emitted in response to wl_shm requests. @@ -304,254 +278,137 @@ - This describes the memory layout of an individual pixel. + This describes the memory layout of an individual pixel. - All renderers should support argb8888 and xrgb8888 but any other - formats are optional and may not be supported by the particular - renderer in use. - - The drm format codes match the macros defined in drm_fourcc.h, except - argb8888 and xrgb8888. The formats actually supported by the compositor - will be reported by the format event. See drm_fourcc.h for more detailed - format descriptions. - - For all wl_shm formats and unless specified in another protocol - extension, pre-multiplied alpha is used for pixel values. + All renderers should support argb8888 and xrgb8888 but any other + formats are optional and may not be supported by the particular + renderer in use. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Create a new wl_shm_pool object. + Create a new wl_shm_pool object. - The pool can be used to create shared memory based buffer - objects. The server will mmap size bytes of the passed file + The pool can be used to create shared memory based buffer + objects. The server will mmap size bytes of the passed file descriptor, to use as backing memory for the pool. - - - + + + + - Informs the client about a valid pixel format that - can be used for buffers. Known formats include - argb8888 and xrgb8888. - - Extensions to drm_fourcc.h (or the format enum) do not require - increasing the wl_shm version; as a result, clients may receive format - codes which were not in the list at the time the client was made. + Informs the client about a valid pixel format that + can be used for buffers. Known formats include + argb8888 and xrgb8888. - + - - - - - - Using this request a client can tell the server that it is not going to - use the shm object anymore. - - Objects created via this interface remain unaffected. - - - + A buffer provides the content for a wl_surface. Buffers are - created through factory interfaces such as wl_shm, wp_linux_buffer_params - (from the linux-dmabuf protocol extension) or similar. It has a width and - a height and can be attached to a wl_surface, but the mechanism by which a - client provides and updates the contents is defined by the buffer factory - interface. - - Color channels are assumed to be electrical rather than optical (in other - words, encoded with a transfer function) unless otherwise specified. If - the buffer uses a format that has an alpha channel, the alpha channel is - assumed to be premultiplied into the electrical color channel values - (after transfer function encoding) unless otherwise specified. - - Note, because wl_buffer objects are created from multiple independent - factory interfaces, the wl_buffer interface is frozen at version 1. + created through factory interfaces such as wl_drm, wl_shm or + similar. It has a width and a height and can be attached to a + wl_surface, but the mechanism by which a client provides and + updates the contents is defined by the buffer factory interface. - Destroy a buffer. If and how you need to release the backing - storage is defined by the buffer factory interface. + Destroy a buffer. If and how you need to release the backing + storage is defined by the buffer factory interface. - For possible side-effects to a surface, see wl_surface.attach. + For possible side-effects to a surface, see wl_surface.attach. - Sent when this wl_buffer is no longer used by the compositor. + Sent when this wl_buffer is no longer used by the compositor. + The client is now free to re-use or destroy this buffer and its + backing storage. - For more information on when release events may or may not be sent, - and what consequences it has, please see the description of - wl_surface.attach. - - If a client receives a release event before the frame callback - requested in the same wl_surface.commit that attaches this - wl_buffer to a surface, then the client is immediately free to - reuse the buffer and its backing storage, and does not need a - second buffer for the next surface content update. Typically - this is possible, when the compositor maintains a copy of the - wl_surface contents, e.g. as a GL texture. This is an important - optimization for GL(ES) compositors with wl_shm clients. + If a client receives a release event before the frame callback + requested in the same wl_surface.commit that attaches this + wl_buffer to a surface, then the client is immediately free to + re-use the buffer and its backing storage, and does not need a + second buffer for the next surface content update. Typically + this is possible, when the compositor maintains a copy of the + wl_surface contents, e.g. as a GL texture. This is an important + optimization for GL(ES) compositors with wl_shm clients. - + + A wl_data_offer represents a piece of data offered for transfer by another client (the source client). It is used by the @@ -561,190 +418,52 @@ data directly from the source client. - - - - - - - - Indicate that the client can accept the given mime type, or - NULL for not accepted. + Indicate that the client can accept the given mime type, or + NULL for not accepted. - For objects of version 2 or older, this request is used by the - client to give feedback whether the client can receive the given - mime type, or NULL if none is accepted; the feedback does not - determine whether the drag-and-drop operation succeeds or not. - - For objects of version 3 or newer, this request determines the - final result of the drag-and-drop operation. If the end result - is that no mime types were accepted, the drag-and-drop operation - will be cancelled and the corresponding drag source will receive - wl_data_source.cancelled. Clients may still use this event in - conjunction with wl_data_source.action for feedback. + Used for feedback during drag-and-drop. - - + + + - To transfer the offered data, the client issues this request - and indicates the mime type it wants to receive. The transfer - happens through the passed file descriptor (typically created - with the pipe system call). The source client writes the data - in the mime type representation requested and then closes the - file descriptor. + To transfer the offered data, the client issues this request + and indicates the mime type it wants to receive. The transfer + happens through the passed file descriptor (typically created + with the pipe system call). The source client writes the data + in the mime type representation requested and then closes the + file descriptor. - The receiving client reads from the read end of the pipe until - EOF and then closes its end, at which point the transfer is - complete. - - This request may happen multiple times for different mime types, - both before and after wl_data_device.drop. Drag-and-drop destination - clients may preemptively fetch data or examine it more closely to - determine acceptance. + The receiving client reads from the read end of the pipe until + EOF and the closes its end, at which point the transfer is + complete. - - + + - Destroy the data offer. + Destroy the data offer. - Sent immediately after creating the wl_data_offer object. One - event per offered mime type. + Sent immediately after creating the wl_data_offer object. One + event per offered mime type. - - - - - - - Notifies the compositor that the drag destination successfully - finished the drag-and-drop operation. - - Upon receiving this request, the compositor will emit - wl_data_source.dnd_finished on the drag source client. - - It is a client error to perform other requests than - wl_data_offer.destroy after this one. It is also an error to perform - this request after a NULL mime type has been set in - wl_data_offer.accept or no action was received through - wl_data_offer.action. - - If wl_data_offer.finish request is received for a non drag and drop - operation, the invalid_finish protocol error is raised. - - - - - - Sets the actions that the destination side client supports for - this operation. This request may trigger the emission of - wl_data_source.action and wl_data_offer.action events if the compositor - needs to change the selected action. - - This request can be called multiple times throughout the - drag-and-drop operation, typically in response to wl_data_device.enter - or wl_data_device.motion events. - - This request determines the final result of the drag-and-drop - operation. If the end result is that no action is accepted, - the drag source will receive wl_data_source.cancelled. - - The dnd_actions argument must contain only values expressed in the - wl_data_device_manager.dnd_actions enum, and the preferred_action - argument must only contain one of those values set, otherwise it - will result in a protocol error. - - While managing an "ask" action, the destination drag-and-drop client - may perform further wl_data_offer.receive requests, and is expected - to perform one last wl_data_offer.set_actions request with a preferred - action other than "ask" (and optionally wl_data_offer.accept) before - requesting wl_data_offer.finish, in order to convey the action selected - by the user. If the preferred action is not in the - wl_data_offer.source_actions mask, an error will be raised. - - If the "ask" action is dismissed (e.g. user cancellation), the client - is expected to perform wl_data_offer.destroy right away. - - This request can only be made on drag-and-drop offers, a protocol error - will be raised otherwise. - - - - - - - - This event indicates the actions offered by the data source. It - will be sent immediately after creating the wl_data_offer object, - or anytime the source side changes its offered actions through - wl_data_source.set_actions. - - - - - - - This event indicates the action selected by the compositor after - matching the source/destination side actions. Only one action (or - none) will be offered here. - - This event can be emitted multiple times during the drag-and-drop - operation in response to destination side action changes through - wl_data_offer.set_actions. - - This event will no longer be emitted after wl_data_device.drop - happened on the drag-and-drop destination, the client must - honor the last action received, or the last preferred one set - through wl_data_offer.set_actions when handling an "ask" action. - - Compositors may also change the selected action on the fly, mainly - in response to keyboard modifier changes during the drag-and-drop - operation. - - The most recent action received is always the valid one. Prior to - receiving wl_data_device.drop, the chosen action may change (e.g. - due to keyboard modifiers being pressed). At the time of receiving - wl_data_device.drop the drag-and-drop destination must honor the - last action received. - - Action changes may still happen after wl_data_device.drop, - especially on "ask" actions, where the drag-and-drop destination - may choose another action afterwards. Action changes happening - at this stage are always the result of inter-client negotiation, the - compositor shall no longer be able to induce a different action. - - Upon "ask" actions, it is expected that the drag-and-drop destination - may potentially choose a different action and/or mime type, - based on wl_data_offer.source_actions and finally chosen by the - user (e.g. popping up a menu with the available options). The - final wl_data_offer.set_actions and wl_data_offer.accept requests - must happen before the call to wl_data_offer.finish. - - + - + The wl_data_source object is the source side of a wl_data_offer. It is created by the source client in a data transfer and @@ -752,154 +471,53 @@ to requests to transfer the data. - - - - - - This request adds a mime type to the set of mime types - advertised to targets. Can be called several times to offer - multiple types. + This request adds a mime type to the set of mime types + advertised to targets. Can be called several times to offer + multiple types. - + - Destroy the data source. + Destroy the data source. - Sent when a target accepts pointer_focus or motion events. If - a target does not accept any of the offered types, type is NULL. + Sent when a target accepts pointer_focus or motion events. If + a target does not accept any of the offered types, type is NULL. - Used for feedback during drag-and-drop. + Used for feedback during drag-and-drop. - + + - Request for data from the client. Send the data as the - specified mime type over the passed file descriptor, then - close it. + Request for data from the client. Send the data as the + specified mime type over the passed file descriptor, then + close it. - - + + + - This data source is no longer valid. There are several reasons why - this could happen: - - - The data source has been replaced by another data source. - - The drag-and-drop operation was performed, but the drop destination - did not accept any of the mime types offered through - wl_data_source.target. - - The drag-and-drop operation was performed, but the drop destination - did not select any of the actions present in the mask offered through - wl_data_source.action. - - The drag-and-drop operation was performed but didn't happen over a - surface. - - The compositor cancelled the drag-and-drop operation (e.g. compositor - dependent timeouts to avoid stale drag-and-drop transfers). - - The client should clean up and destroy this data source. - - For objects of version 2 or older, wl_data_source.cancelled will - only be emitted if the data source was replaced by another data - source. + This data source has been replaced by another data source. + The client should clean up and destroy this data source. - - - - - Sets the actions that the source side client supports for this - operation. This request may trigger wl_data_source.action and - wl_data_offer.action events if the compositor needs to change the - selected action. - - The dnd_actions argument must contain only values expressed in the - wl_data_device_manager.dnd_actions enum, otherwise it will result - in a protocol error. - - This request must be made once only, and can only be made on sources - used in drag-and-drop, so it must be performed before - wl_data_device.start_drag. Attempting to use the source other than - for drag-and-drop will raise a protocol error. - - - - - - - The user performed the drop action. This event does not indicate - acceptance, wl_data_source.cancelled may still be emitted afterwards - if the drop destination does not accept any mime type. - - However, this event might however not be received if the compositor - cancelled the drag-and-drop operation before this event could happen. - - Note that the data_source may still be used in the future and should - not be destroyed here. - - - - - - The drop destination finished interoperating with this data - source, so the client is now free to destroy this data source and - free all associated data. - - If the action used to perform the operation was "move", the - source can now delete the transferred data. - - - - - - This event indicates the action selected by the compositor after - matching the source/destination side actions. Only one action (or - none) will be offered here. - - This event can be emitted multiple times during the drag-and-drop - operation, mainly in response to destination side changes through - wl_data_offer.set_actions, and as the data device enters/leaves - surfaces. - - It is only possible to receive this event after - wl_data_source.dnd_drop_performed if the drag-and-drop operation - ended in an "ask" action, in which case the final wl_data_source.action - event will happen immediately before wl_data_source.dnd_finished. - - Compositors may also change the selected action on the fly, mainly - in response to keyboard modifier changes during the drag-and-drop - operation. - - The most recent action received is always the valid one. The chosen - action may change alongside negotiation (e.g. an "ask" action can turn - into a "move" operation), so the effects of the final action must - always be applied in wl_data_offer.dnd_finished. - - Clients can trigger cursor surface changes from this point, so - they reflect the current action. - - - - + There is one wl_data_device per seat which can be obtained from the global wl_data_device_manager singleton. @@ -907,229 +525,145 @@ A wl_data_device provides access to inter-client data transfer mechanisms such as copy-and-paste and drag-and-drop. - - - - - - - This request asks the compositor to start a drag-and-drop - operation on behalf of the client. + This request asks the compositor to start a drag-and-drop + operation on behalf of the client. - The source argument is the data source that provides the data - for the eventual data transfer. If source is NULL, enter, leave - and motion events are sent only to the client that initiated the - drag and the client is expected to handle the data passing - internally. If source is destroyed, the drag-and-drop session will be - cancelled. + The source argument is the data source that provides the data + for the eventual data transfer. If source is NULL, enter, leave + and motion events are sent only to the client that initiated the + drag and the client is expected to handle the data passing + internally. - The origin surface is the surface where the drag originates and - the client must have an active implicit grab that matches the - serial. + The origin surface is the surface where the drag originates and + the client must have an active implicit grab that matches the + serial. - The icon surface is an optional (can be NULL) surface that - provides an icon to be moved around with the cursor. Initially, - the top-left corner of the icon surface is placed at the cursor - hotspot, but subsequent wl_surface.offset requests can move the - relative position. Attach requests must be confirmed with - wl_surface.commit as usual. The icon surface is given the role of - a drag-and-drop icon. If the icon surface already has another role, - it raises a protocol error. + The icon surface is an optional (can be NULL) surface that + provides an icon to be moved around with the cursor. Initially, + the top-left corner of the icon surface is placed at the cursor + hotspot, but subsequent wl_surface.attach request can move the + relative position. Attach requests must be confirmed with + wl_surface.commit as usual. - The input region is ignored for wl_surfaces with the role of a - drag-and-drop icon. - - The given source may not be used in any further set_selection or - start_drag requests. Attempting to reuse a previously-used source - may send a used_source error. + The current and pending input regions of the icon wl_surface are + cleared, and wl_surface.set_input_region is ignored until the + wl_surface is no longer used as the icon surface. When the use + as an icon ends, the current and pending input regions become + undefined, and the wl_surface is unmapped. - - - - + + + + - This request asks the compositor to set the selection - to the data from the source on behalf of the client. + This request asks the compositor to set the selection + to the data from the source on behalf of the client. - To unset the selection, set the source to NULL. - - The given source may not be used in any further set_selection or - start_drag requests. Attempting to reuse a previously-used source - may send a used_source error. + To unset the selection, set the source to NULL. - - + + - The data_offer event introduces a new wl_data_offer object, - which will subsequently be used in either the - data_device.enter event (for drag-and-drop) or the - data_device.selection event (for selections). Immediately - following the data_device.data_offer event, the new data_offer - object will send out data_offer.offer events to describe the - mime types it offers. + The data_offer event introduces a new wl_data_offer object, + which will subsequently be used in either the + data_device.enter event (for drag-and-drop) or the + data_device.selection event (for selections). Immediately + following the data_device_data_offer event, the new data_offer + object will send out data_offer.offer events to describe the + mime types it offers. - + + - This event is sent when an active drag-and-drop pointer enters - a surface owned by the client. The position of the pointer at - enter time is provided by the x and y arguments, in surface-local - coordinates. + This event is sent when an active drag-and-drop pointer enters + a surface owned by the client. The position of the pointer at + enter time is provided by the x and y arguments, in surface + local coordinates. - - - - - + + + + + + - This event is sent when the drag-and-drop pointer leaves the - surface and the session ends. The client must destroy the - wl_data_offer introduced at enter time at this point. + This event is sent when the drag-and-drop pointer leaves the + surface and the session ends. The client must destroy the + wl_data_offer introduced at enter time at this point. - This event is sent when the drag-and-drop pointer moves within - the currently focused surface. The new position of the pointer - is provided by the x and y arguments, in surface-local - coordinates. + This event is sent when the drag-and-drop pointer moves within + the currently focused surface. The new position of the pointer + is provided by the x and y arguments, in surface local + coordinates. - - + + - - The event is sent when a drag-and-drop operation is ended - because the implicit grab is removed. - - The drag-and-drop destination is expected to honor the last action - received through wl_data_offer.action, if the resulting action is - "copy" or "move", the destination can still perform - wl_data_offer.receive requests, and is expected to end all - transfers with a wl_data_offer.finish request. - - If the resulting action is "ask", the action will not be considered - final. The drag-and-drop destination is expected to perform one last - wl_data_offer.set_actions request, or wl_data_offer.destroy in order - to cancel the operation. + + The event is sent when a drag-and-drop operation is ended + because the implicit grab is removed. - The selection event is sent out to notify the client of a new - wl_data_offer for the selection for this device. The - data_device.data_offer and the data_offer.offer events are - sent out immediately before this event to introduce the data - offer object. The selection event is sent to a client - immediately before receiving keyboard focus and when a new - selection is set while the client has keyboard focus. The - data_offer is valid until a new data_offer or NULL is received - or until the client loses keyboard focus. Switching surface with - keyboard focus within the same client doesn't mean a new selection - will be sent. The client must destroy the previous selection - data_offer, if any, upon receiving this event. + The selection event is sent out to notify the client of a new + wl_data_offer for the selection for this device. The + data_device.data_offer and the data_offer.offer events are + sent out immediately before this event to introduce the data + offer object. The selection event is sent to a client + immediately before receiving keyboard focus and when a new + selection is set while the client has keyboard focus. The + data_offer is valid until a new data_offer or NULL is received + or until the client loses keyboard focus. - + - - - - - - This request destroys the data device. - - - + The wl_data_device_manager is a singleton global object that provides access to inter-client data transfer mechanisms such as copy-and-paste and drag-and-drop. These mechanisms are tied to a wl_seat and this interface lets a client get a wl_data_device corresponding to a wl_seat. - - Depending on the version bound, the objects created from the bound - wl_data_device_manager object will have different requirements for - functioning properly. See wl_data_source.set_actions, - wl_data_offer.accept and wl_data_offer.finish for details. Create a new data source. - + Create a new data device for a given seat. - - - - - - - - - This is a bitmask of the available/preferred actions in a - drag-and-drop operation. - - In the compositor, the selected action is a result of matching the - actions offered by the source and destination sides. "action" events - with a "none" action will be sent to both source and destination if - there is no match. All further checks will effectively happen on - (source actions ∩ destination actions). - - In addition, compositors may also pick different actions in - reaction to key modifiers being pressed. One common design that - is used in major toolkits (and the behavior recommended for - compositors) is: - - - If no modifiers are pressed, the first match (in bit order) - will be used. - - Pressing Shift selects "move", if enabled in the mask. - - Pressing Control selects "copy", if enabled in the mask. - - Behavior beyond that is considered implementation-dependent. - Compositors may for example bind other modifiers (like Alt/Meta) - or drags initiated with other buttons than BTN_LEFT to specific - actions (e.g. "ask"). - - - - - - - - - - - - This request destroys the wl_data_device_manager. This has no effect on any other - objects. - + + @@ -1140,30 +674,21 @@ It allows clients to associate a wl_shell_surface with a basic surface. - - Note! This protocol is deprecated and not intended for production use. - For desktop-style user interfaces, use xdg_shell. Compositors and clients - should not implement this interface. - - - - - Create a shell surface for an existing surface. This gives - the wl_surface the role of a shell surface. If the wl_surface - already has another role, it raises a protocol error. + Create a shell surface for an existing surface. - Only one shell surface can be associated with a given surface. + Only one shell surface can be associated with a given surface. - - + + + An interface that may be implemented by a wl_surface, for implementations that provide a desktop-style user interface. @@ -1173,99 +698,100 @@ metadata like title and class, etc. On the server side the object is automatically destroyed when - the related wl_surface is destroyed. On the client side, + the related wl_surface is destroyed. On client side, wl_shell_surface_destroy() must be called before destroying the wl_surface object. - A client must respond to a ping event with a pong request or - the client may be deemed unresponsive. + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. - + - Start a pointer-driven move of the surface. + Start a pointer-driven move of the surface. - This request must be used in response to a button press event. - The server may ignore move requests depending on the state of - the surface (e.g. fullscreen or maximized). + This request must be used in response to a button press event. + The server may ignore move requests depending on the state of + the surface (e.g. fullscreen or maximized). - - + + - + - These values are used to indicate which edge of a surface - is being dragged in a resize operation. The server may - use this information to adapt its behavior, e.g. choose - an appropriate cursor image. + These values are used to indicate which edge of a surface + is being dragged in a resize operation. The server may + use this information to adapt its behavior, e.g. choose + an appropriate cursor image. - - - - - - - - - + + + + + + + + + - Start a pointer-driven resizing of the surface. + Start a pointer-driven resizing of the surface. - This request must be used in response to a button press event. - The server may ignore resize requests depending on the state of - the surface (e.g. fullscreen or maximized). + This request must be used in response to a button press event. + The server may ignore resize requests depending on the state of + the surface (e.g. fullscreen or maximized). - - - + + + - Map the surface as a toplevel surface. + Map the surface as a toplevel surface. - A toplevel surface is not fullscreen, maximized or transient. + A toplevel surface is not fullscreen, maximized or transient. - + - These flags specify details of the expected behaviour - of transient surfaces. Used in the set_transient request. + These flags specify details of the expected behaviour + of transient surfaces. Used in the set_transient request. - Map the surface relative to an existing surface. + Map the surface relative to an existing surface. - The x and y arguments specify the location of the upper left - corner of the surface relative to the upper left corner of the - parent surface, in surface-local coordinates. + The x and y arguments specify the locations of the upper left + corner of the surface relative to the upper left corner of the + parent surface, in surface local coordinates. - The flags argument controls details of the transient behaviour. + The flags argument controls details of the transient behaviour. - - - - + + + + + - Hints to indicate to the compositor how to deal with a conflict - between the dimensions of the surface and the dimensions of the - output. The compositor is free to ignore this parameter. + Hints to indicate to the compositor how to deal with a conflict + between the dimensions of the surface and the dimensions of the + output. The compositor is free to ignore this parameter. @@ -1275,212 +801,180 @@ - Map the surface as a fullscreen surface. + Map the surface as a fullscreen surface. - If an output parameter is given then the surface will be made - fullscreen on that output. If the client does not specify the - output then the compositor will apply its policy - usually - choosing the output on which the surface has the biggest surface - area. + If an output parameter is given then the surface will be made + fullscreen on that output. If the client does not specify the + output then the compositor will apply its policy - usually + choosing the output on which the surface has the biggest surface + area. - The client may specify a method to resolve a size conflict - between the output size and the surface size - this is provided - through the method parameter. + The client may specify a method to resolve a size conflict + between the output size and the surface size - this is provided + through the method parameter. - The framerate parameter is used only when the method is set - to "driver", to indicate the preferred framerate. A value of 0 - indicates that the client does not care about framerate. The - framerate is specified in mHz, that is framerate of 60000 is 60Hz. + The framerate parameter is used only when the method is set + to "driver", to indicate the preferred framerate. A value of 0 + indicates that the app does not care about framerate. The + framerate is specified in mHz, that is framerate of 60000 is 60Hz. - A method of "scale" or "driver" implies a scaling operation of - the surface, either via a direct scaling operation or a change of - the output mode. This will override any kind of output scaling, so - that mapping a surface with a buffer size equal to the mode can - fill the screen independent of buffer_scale. + A method of "scale" or "driver" implies a scaling operation of + the surface, either via a direct scaling operation or a change of + the output mode. This will override any kind of output scaling, so + that mapping a surface with a buffer size equal to the mode can + fill the screen independent of buffer_scale. - A method of "fill" means we don't scale up the buffer, however - any output scale is applied. This means that you may run into - an edge case where the application maps a buffer with the same - size of the output mode but buffer_scale 1 (thus making a - surface larger than the output). In this case it is allowed to - downscale the results to fit the screen. + A method of "fill" means we don't scale up the buffer, however + any output scale is applied. This means that you may run into + an edge case where the application maps a buffer with the same + size of the output mode but buffer_scale 1 (thus making a + surface larger than the output). In this case it is allowed to + downscale the results to fit the screen. - The compositor must reply to this request with a configure event - with the dimensions for the output on which the surface will - be made fullscreen. + The compositor must reply to this request with a configure event + with the dimensions for the output on which the surface will + be made fullscreen. - - - + + + - Map the surface as a popup. + Map the surface as a popup. - A popup surface is a transient surface with an added pointer - grab. + A popup surface is a transient surface with an added pointer + grab. - An existing implicit grab will be changed to owner-events mode, - and the popup grab will continue after the implicit grab ends - (i.e. releasing the mouse button does not cause the popup to - be unmapped). + An existing implicit grab will be changed to owner-events mode, + and the popup grab will continue after the implicit grab ends + (i.e. releasing the mouse button does not cause the popup to + be unmapped). - The popup grab continues until the window is destroyed or a - mouse button is pressed in any other client's window. A click - in any of the client's surfaces is reported as normal, however, - clicks in other clients' surfaces will be discarded and trigger - the callback. + The popup grab continues until the window is destroyed or a + mouse button is pressed in any other clients window. A click + in any of the clients surfaces is reported as normal, however, + clicks in other clients surfaces will be discarded and trigger + the callback. - The x and y arguments specify the location of the upper left - corner of the surface relative to the upper left corner of the - parent surface, in surface-local coordinates. + The x and y arguments specify the locations of the upper left + corner of the surface relative to the upper left corner of the + parent surface, in surface local coordinates. - - - - - - + + + + + + + - Map the surface as a maximized surface. + Map the surface as a maximized surface. - If an output parameter is given then the surface will be - maximized on that output. If the client does not specify the - output then the compositor will apply its policy - usually - choosing the output on which the surface has the biggest surface - area. + If an output parameter is given then the surface will be + maximized on that output. If the client does not specify the + output then the compositor will apply its policy - usually + choosing the output on which the surface has the biggest surface + area. - The compositor will reply with a configure event telling - the expected new surface size. The operation is completed - on the next buffer attach to this surface. + The compositor will reply with a configure event telling + the expected new surface size. The operation is completed + on the next buffer attach to this surface. - A maximized surface typically fills the entire output it is - bound to, except for desktop elements such as panels. This is - the main difference between a maximized shell surface and a - fullscreen shell surface. + A maximized surface typically fills the entire output it is + bound to, except for desktop element such as panels. This is + the main difference between a maximized shell surface and a + fullscreen shell surface. - The details depend on the compositor implementation. + The details depend on the compositor implementation. - + - Set a short title for the surface. + Set a short title for the surface. - This string may be used to identify the surface in a task bar, - window list, or other user interface elements provided by the - compositor. + This string may be used to identify the surface in a task bar, + window list, or other user interface elements provided by the + compositor. - The string must be encoded in UTF-8. + The string must be encoded in UTF-8. - + - Set a class for the surface. + Set a class for the surface. - The surface class identifies the general class of applications - to which the surface belongs. A common convention is to use the - file name (or the full path if it is a non-standard location) of - the application's .desktop file as the class. + The surface class identifies the general class of applications + to which the surface belongs. A common convention is to use the + file name (or the full path if it is a non-standard location) of + the application's .desktop file as the class. - + - Ping a client to check if it is receiving events and sending - requests. A client is expected to reply with a pong request. + Ping a client to check if it is receiving events and sending + requests. A client is expected to reply with a pong request. - + - The configure event asks the client to resize its surface. + The configure event asks the client to resize its surface. - The size is a hint, in the sense that the client is free to - ignore it if it doesn't resize, pick a smaller size (to - satisfy aspect ratio or resize in steps of NxM pixels). + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). - The edges parameter provides a hint about how the surface - was resized. The client may use this information to decide - how to adjust its content to the new size (e.g. a scrolling - area might adjust its content position to leave the viewable - content unmoved). + The edges parameter provides a hint about how the surface + was resized. The client may use this information to decide + how to adjust its content to the new size (e.g. a scrolling + area might adjust its content position to leave the viewable + content unmoved). - The client is free to dismiss all but the last configure - event it received. + The client is free to dismiss all but the last configure + event it received. - The width and height arguments specify the size of the window - in surface-local coordinates. + The width and height arguments specify the size of the window + in surface local coordinates. - - - + + + + - The popup_done event is sent out when a popup grab is broken, - that is, when the user clicks a surface that doesn't belong - to the client owning the popup surface. + The popup_done event is sent out when a popup grab is broken, + that is, when the user clicks a surface that doesn't belong + to the client owning the popup surface. - + - A surface is a rectangular area that may be displayed on zero - or more outputs, and shown any number of times at the compositor's - discretion. They can present wl_buffers, receive user input, and - define a local coordinate system. + A surface is a rectangular area that is displayed on the screen. + It has a location, size and pixel contents. The size of a surface (and relative positions on it) is described - in surface-local coordinates, which may differ from the buffer - coordinates of the pixel content, in case a buffer_transform + in surface local coordinates, which may differ from the buffer + local coordinates of the pixel content, in case a buffer_transform or a buffer_scale is used. - A surface without a "role" is fairly useless: a compositor does - not know where, when or how to present it. The role is the - purpose of a wl_surface. Examples of roles are a cursor for a - pointer (as set by wl_pointer.set_cursor), a drag icon - (wl_data_device.start_drag), a sub-surface - (wl_subcompositor.get_subsurface), and a window as defined by a - shell protocol (e.g. wl_shell.get_shell_surface). - - A surface can have only one role at a time. Initially a - wl_surface does not have a role. Once a wl_surface is given a - role, it is set permanently for the whole lifetime of the - wl_surface object. Giving the current role again is allowed, - unless explicitly forbidden by the relevant interface - specification. - - Surface roles are given by requests in other interfaces such as - wl_pointer.set_cursor. The request should explicitly mention - that this request gives a role to a wl_surface. Often, this - request also creates a new protocol object that represents the - role and adds additional functionality to wl_surface. When a - client wants to destroy a wl_surface, they must destroy this role - object before the wl_surface, otherwise a defunct_role_object error is - sent. - - Destroying the role object does not remove the role from the - wl_surface, but it may stop the wl_surface from "playing the role". - For instance, if a wl_subsurface object is destroyed, the wl_surface - it was created for will be unmapped and forget its position and - z-order. It is allowed to create a wl_subsurface for the same - wl_surface again, but it is not allowed to use the wl_surface as - a cursor (cursor is a different role than sub-surface, and role - switching is not allowed). + Surfaces are also used for some special purposes, e.g. as + cursor images for pointers, drag icons, etc. @@ -1489,502 +983,301 @@ - - - - - Deletes the surface and invalidates its object ID. + Deletes the surface and invalidates its object ID. - Set a buffer as the content of this surface. + Set a buffer as the content of this surface. - The new size of the surface is calculated based on the buffer - size transformed by the inverse buffer_transform and the - inverse buffer_scale. This means that at commit time the supplied - buffer size must be an integer multiple of the buffer_scale. If - that's not the case, an invalid_size error is sent. + The new size of the surface is calculated based on the buffer + size transformed by the inverse buffer_transform and the + inverse buffer_scale. This means that the supplied buffer + must be an integer multiple of the buffer_scale. - The x and y arguments specify the location of the new pending - buffer's upper left corner, relative to the current buffer's upper - left corner, in surface-local coordinates. In other words, the - x and y, combined with the new surface size define in which - directions the surface's size changes. Setting anything other than 0 - as x and y arguments is discouraged, and should instead be replaced - with using the separate wl_surface.offset request. + The x and y arguments specify the location of the new pending + buffer's upper left corner, relative to the current buffer's upper + left corner, in surface local coordinates. In other words, the + x and y, combined with the new surface size define in which + directions the surface's size changes. - When the bound wl_surface version is 5 or higher, passing any - non-zero x or y is a protocol violation, and will result in an - 'invalid_offset' error being raised. The x and y arguments are ignored - and do not change the pending state. To achieve equivalent semantics, - use wl_surface.offset. + Surface contents are double-buffered state, see wl_surface.commit. - Surface contents are double-buffered state, see wl_surface.commit. + The initial surface contents are void; there is no content. + wl_surface.attach assigns the given wl_buffer as the pending + wl_buffer. wl_surface.commit makes the pending wl_buffer the new + surface contents, and the size of the surface becomes the size + calculated from the wl_buffer, as described above. After commit, + there is no pending buffer until the next attach. - The initial surface contents are void; there is no content. - wl_surface.attach assigns the given wl_buffer as the pending - wl_buffer. wl_surface.commit makes the pending wl_buffer the new - surface contents, and the size of the surface becomes the size - calculated from the wl_buffer, as described above. After commit, - there is no pending buffer until the next attach. + Committing a pending wl_buffer allows the compositor to read the + pixels in the wl_buffer. The compositor may access the pixels at + any time after the wl_surface.commit request. When the compositor + will not access the pixels anymore, it will send the + wl_buffer.release event. Only after receiving wl_buffer.release, + the client may re-use the wl_buffer. A wl_buffer that has been + attached and then replaced by another attach instead of committed + will not receive a release event, and is not used by the + compositor. - Committing a pending wl_buffer allows the compositor to read the - pixels in the wl_buffer. The compositor may access the pixels at - any time after the wl_surface.commit request. When the compositor - will not access the pixels anymore, it will send the - wl_buffer.release event. Only after receiving wl_buffer.release, - the client may reuse the wl_buffer. A wl_buffer that has been - attached and then replaced by another attach instead of committed - will not receive a release event, and is not used by the - compositor. + Destroying the wl_buffer after wl_buffer.release does not change + the surface contents. However, if the client destroys the + wl_buffer before receiving the wl_buffer.release event, the surface + contents become undefined immediately. - If a pending wl_buffer has been committed to more than one wl_surface, - the delivery of wl_buffer.release events becomes undefined. A well - behaved client should not rely on wl_buffer.release events in this - case. Instead, clients hitting this case should use - wl_surface.get_release or use a protocol extension providing per-commit - release notifications (if none of these options are available, a - fallback can be implemented by creating multiple wl_buffer objects from - the same backing storage). - - Destroying the wl_buffer after wl_buffer.release does not change - the surface contents. Destroying the wl_buffer before wl_buffer.release - is allowed as long as the underlying buffer storage isn't re-used (this - can happen e.g. on client process termination). However, if the client - destroys the wl_buffer before receiving the wl_buffer.release event and - mutates the underlying buffer storage, the surface contents become - undefined immediately. - - If wl_surface.attach is sent with a NULL wl_buffer, the - following wl_surface.commit will remove the surface content. - - If a pending wl_buffer has been destroyed, the result is not specified. - Many compositors are known to remove the surface content on the following - wl_surface.commit, but this behaviour is not universal. Clients seeking to - maximise compatibility should not destroy pending buffers and should - ensure that they explicitly remove content from surfaces, even after - destroying buffers. + If wl_surface.attach is sent with a NULL wl_buffer, the + following wl_surface.commit will remove the surface content. - - - + + + + - This request is used to describe the regions where the pending - buffer is different from the current surface contents, and where - the surface therefore needs to be repainted. The compositor - ignores the parts of the damage that fall outside of the surface. + This request is used to describe the regions where the pending + buffer is different from the current surface contents, and where + the surface therefore needs to be repainted. The pending buffer + must be set by wl_surface.attach before sending damage. The + compositor ignores the parts of the damage that fall outside of + the surface. - Damage is double-buffered state, see wl_surface.commit. + Damage is double-buffered state, see wl_surface.commit. - The damage rectangle is specified in surface-local coordinates, - where x and y specify the upper left corner of the damage rectangle. + The damage rectangle is specified in surface local coordinates. - The initial value for pending damage is empty: no damage. - wl_surface.damage adds pending damage: the new pending damage - is the union of old pending damage and the given rectangle. + The initial value for pending damage is empty: no damage. + wl_surface.damage adds pending damage: the new pending damage + is the union of old pending damage and the given rectangle. - wl_surface.commit assigns pending damage as the current damage, - and clears pending damage. The server will clear the current - damage as it repaints the surface. - - Note! New clients should not use this request. Instead damage can be - posted with wl_surface.damage_buffer which uses buffer coordinates - instead of surface coordinates. + wl_surface.commit assigns pending damage as the current damage, + and clears pending damage. The server will clear the current + damage as it repaints the surface. - - - - + + + + + - Request a notification when it is a good time to start drawing a new - frame, by creating a frame callback. This is useful for throttling - redrawing operations, and driving animations. + Request a notification when it is a good time start drawing a new + frame, by creating a frame callback. This is useful for throttling + redrawing operations, and driving animations. - When a client is animating on a wl_surface, it can use the 'frame' - request to get notified when it is a good time to draw and commit the - next frame of animation. If the client commits an update earlier than - that, it is likely that some updates will not make it to the display, - and the client is wasting resources by drawing too often. + When a client is animating on a wl_surface, it can use the 'frame' + request to get notified when it is a good time to draw and commit the + next frame of animation. If the client commits an update earlier than + that, it is likely that some updates will not make it to the display, + and the client is wasting resources by drawing too often. - The frame request will take effect on the next wl_surface.commit. - The notification will only be posted for one frame unless - requested again. For a wl_surface, the notifications are posted in - the order the frame requests were committed. + The frame request will take effect on the next wl_surface.commit. + The notification will only be posted for one frame unless + requested again. For a wl_surface, the notifications are posted in + the order the frame requests were committed. - The server must send the notifications so that a client - will not send excessive updates, while still allowing - the highest possible update rate for clients that wait for the reply - before drawing again. The server should give some time for the client - to draw and commit after sending the frame callback events to let it - hit the next output refresh. + The server must send the notifications so that a client + will not send excessive updates, while still allowing + the highest possible update rate for clients that wait for the reply + before drawing again. The server should give some time for the client + to draw and commit after sending the frame callback events to let them + hit the next output refresh. - A server should avoid signaling the frame callbacks if the - surface is not visible in any way, e.g. the surface is off-screen, - or completely obscured by other opaque surfaces. + A server should avoid signalling the frame callbacks if the + surface is not visible in any way, e.g. the surface is off-screen, + or completely obscured by other opaque surfaces. - The object returned by this request will be destroyed by the - compositor after the callback is fired and as such the client must not - attempt to use it after that point. + The object returned by this request will be destroyed by the + compositor after the callback is fired and as such the client must not + attempt to use it after that point. - The callback_data passed in the callback is the current time, in - milliseconds, with an undefined base. + The callback_data passed in the callback is the current time, in + milliseconds, with an undefined base. - + + - This request sets the region of the surface that contains - opaque content. + This request sets the region of the surface that contains + opaque content. - The opaque region is an optimization hint for the compositor - that lets it optimize the redrawing of content behind opaque - regions. Setting an opaque region is not required for correct - behaviour, but marking transparent content as opaque will result - in repaint artifacts. + The opaque region is an optimization hint for the compositor + that lets it optimize out redrawing of content behind opaque + regions. Setting an opaque region is not required for correct + behaviour, but marking transparent content as opaque will result + in repaint artifacts. - The opaque region is specified in surface-local coordinates. + The opaque region is specified in surface local coordinates. - The compositor ignores the parts of the opaque region that fall - outside of the surface. + The compositor ignores the parts of the opaque region that fall + outside of the surface. - Opaque region is double-buffered state, see wl_surface.commit. + Opaque region is double-buffered state, see wl_surface.commit. - wl_surface.set_opaque_region changes the pending opaque region. - wl_surface.commit copies the pending region to the current region. - Otherwise, the pending and current regions are never changed. + wl_surface.set_opaque_region changes the pending opaque region. + wl_surface.commit copies the pending region to the current region. + Otherwise, the pending and current regions are never changed. - The initial value for an opaque region is empty. Setting the pending - opaque region has copy semantics, and the wl_region object can be - destroyed immediately. A NULL wl_region causes the pending opaque - region to be set to empty. + The initial value for opaque region is empty. Setting the pending + opaque region has copy semantics, and the wl_region object can be + destroyed immediately. A NULL wl_region causes the pending opaque + region to be set to empty. - + + - This request sets the region of the surface that can receive - pointer and touch events. + This request sets the region of the surface that can receive + pointer and touch events. - Input events happening outside of this region will try the next - surface in the server surface stack. The compositor ignores the - parts of the input region that fall outside of the surface. + Input events happening outside of this region will try the next + surface in the server surface stack. The compositor ignores the + parts of the input region that fall outside of the surface. - The input region is specified in surface-local coordinates. + The input region is specified in surface local coordinates. - Input region is double-buffered state, see wl_surface.commit. + Input region is double-buffered state, see wl_surface.commit. - wl_surface.set_input_region changes the pending input region. - wl_surface.commit copies the pending region to the current region. - Otherwise the pending and current regions are never changed, - except cursor and icon surfaces are special cases, see - wl_pointer.set_cursor and wl_data_device.start_drag. + wl_surface.set_input_region changes the pending input region. + wl_surface.commit copies the pending region to the current region. + Otherwise the pending and current regions are never changed, + except cursor and icon surfaces are special cases, see + wl_pointer.set_cursor and wl_data_device.start_drag. - The initial value for an input region is infinite. That means the - whole surface will accept input. Setting the pending input region - has copy semantics, and the wl_region object can be destroyed - immediately. A NULL wl_region causes the input region to be set - to infinite. + The initial value for input region is infinite. That means the + whole surface will accept input. Setting the pending input region + has copy semantics, and the wl_region object can be destroyed + immediately. A NULL wl_region causes the input region to be set + to infinite. - + + - Surface state (input, opaque, and damage regions, attached buffers, - etc.) is double-buffered. Protocol requests modify the pending state, - as opposed to the active state in use by the compositor. + Surface state (input, opaque, and damage regions, attached buffers, + etc.) is double-buffered. Protocol requests modify the pending + state, as opposed to current state in use by the compositor. Commit + request atomically applies all pending state, replacing the current + state. After commit, the new pending state is as documented for each + related request. - All requests that need a commit to become effective are documented - to affect double-buffered state. + On commit, a pending wl_buffer is applied first, all other state + second. This means that all coordinates in double-buffered state are + relative to the new wl_buffer coming into use, except for + wl_surface.attach itself. If there is no pending wl_buffer, the + coordinates are relative to the current surface contents. - Other interfaces may add further double-buffered surface state. + All requests that need a commit to become effective are documented + to affect double-buffered state. - A commit request atomically creates a Content Update (CU) from the - pending state, even if the pending state has not been touched. The - content update is placed at the end of a per-surface queue until it - becomes active. After commit, the new pending state is as documented for - each related request. - - A CU is either a Desync Content Update (DCU) or a Sync Content Update - (SCU). If the surface is effectively synchronized at the commit request, - it is a SCU, otherwise a DCU. - - When a surface transitions from effectively synchronized to effectively - desynchronized, all SCUs in its queue which are not reachable by any - DCU become DCUs and dependency edges from outside the queue to these CUs - are removed. - - See wl_subsurface for the definition of 'effectively synchronized' and - 'effectively desynchronized'. - - When a CU is placed in the queue, the CU has a dependency on the CU in - front of it and to the SCU at end of the queue of every direct child - surface if that SCU exists and does not have another dependent. This can - form a directed acyclic graph of CUs with dependencies as edges. - - In addition to surface state, the CU can have constraints that must be - satisfied before it can be applied. Other interfaces may add CU - constraints. - - All DCUs which do not have a SCU in front of themselves in their queue, - are candidates. If the graph that's reachable by a candidate does not - have any unsatisfied constraints, the entire graph must be applied - atomically. - - When a CU is applied, the wl_buffer is applied before all other state. - This means that all coordinates in double-buffered state are relative to - the newly attached wl_buffers, except for wl_surface.attach itself. If - there is no newly attached wl_buffer, the coordinates are relative to - the previous content update. + Other interfaces may add further double-buffered surface state. - This is emitted whenever a surface's creation, movement, or resizing - results in some part of it being within the scanout region of an - output. + This is emitted whenever a surface's creation, movement, or resizing + results in some part of it being within the scanout region of an + output. - Note that a surface may be overlapping with zero or more outputs. + Note that a surface may be overlapping with zero or more outputs. - + - This is emitted whenever a surface's creation, movement, or resizing - results in it no longer having any part of it within the scanout region - of an output. - - Clients should not use the number of outputs the surface is on for frame - throttling purposes. The surface might be hidden even if no leave event - has been sent, and the compositor might expect new surface content - updates even if no enter event has been sent. The frame event should be - used instead. + This is emitted whenever a surface's creation, movement, or resizing + results in it no longer having any part of it within the scanout region + of an output. - + - This request sets the transformation that the client has already applied - to the content of the buffer. The accepted values for the transform - parameter are the values for wl_output.transform. + This request sets an optional transformation on how the compositor + interprets the contents of the buffer attached to the surface. The + accepted values for the transform parameter are the values for + wl_output.transform. - The compositor applies the inverse of this transformation whenever it - uses the buffer contents. + Buffer transform is double-buffered state, see wl_surface.commit. - Buffer transform is double-buffered state, see wl_surface.commit. + A newly created surface has its buffer transformation set to normal. - A newly created surface has its buffer transformation set to normal. + wl_surface.set_buffer_transform changes the pending buffer + transformation. wl_surface.commit copies the pending buffer + transformation to the current one. Otherwise, the pending and current + values are never changed. - wl_surface.set_buffer_transform changes the pending buffer - transformation. wl_surface.commit copies the pending buffer - transformation to the current one. Otherwise, the pending and current - values are never changed. + The purpose of this request is to allow clients to render content + according to the output transform, thus permiting the compositor to + use certain optimizations even if the display is rotated. Using + hardware overlays and scanning out a client buffer for fullscreen + surfaces are examples of such optimizations. Those optimizations are + highly dependent on the compositor implementation, so the use of this + request should be considered on a case-by-case basis. - The purpose of this request is to allow clients to render content - according to the output transform, thus permitting the compositor to - use certain optimizations even if the display is rotated. Using - hardware overlays and scanning out a client buffer for fullscreen - surfaces are examples of such optimizations. Those optimizations are - highly dependent on the compositor implementation, so the use of this - request should be considered on a case-by-case basis. + Note that if the transform value includes 90 or 270 degree rotation, + the width of the buffer will become the surface height and the height + of the buffer will become the surface width. - Note that if the transform value includes 90 or 270 degree rotation, - the width of the buffer will become the surface height and the height - of the buffer will become the surface width. - - If transform is not one of the values from the - wl_output.transform enum the invalid_transform protocol error - is raised. + If transform is not one of the values from the + wl_output.transform enum the invalid_transform protocol error + is raised. - + - This request sets an optional scaling factor on how the compositor - interprets the contents of the buffer attached to the window. + This request sets an optional scaling factor on how the compositor + interprets the contents of the buffer attached to the window. - Buffer scale is double-buffered state, see wl_surface.commit. + Buffer scale is double-buffered state, see wl_surface.commit. - A newly created surface has its buffer scale set to 1. + A newly created surface has its buffer scale set to 1. - wl_surface.set_buffer_scale changes the pending buffer scale. - wl_surface.commit copies the pending buffer scale to the current one. - Otherwise, the pending and current values are never changed. + wl_surface.set_buffer_scale changes the pending buffer scale. + wl_surface.commit copies the pending buffer scale to the current one. + Otherwise, the pending and current values are never changed. - The purpose of this request is to allow clients to supply higher - resolution buffer data for use on high resolution outputs. It is - intended that you pick the same buffer scale as the scale of the - output that the surface is displayed on. This means the compositor - can avoid scaling when rendering the surface on that output. + The purpose of this request is to allow clients to supply higher + resolution buffer data for use on high resolution outputs. Its + intended that you pick the same buffer scale as the scale of the + output that the surface is displayed on.This means the compositor + can avoid scaling when rendering the surface on that output. - Note that if the scale is larger than 1, then you have to attach - a buffer that is larger (by a factor of scale in each dimension) - than the desired surface size. + Note that if the scale is larger than 1, then you have to attach + a buffer that is larger (by a factor of scale in each dimension) + than the desired surface size. - If scale is not greater than 0 the invalid_scale protocol error is - raised. + If scale is not positive the invalid_scale protocol error is + raised. - - - - - - - This request is used to describe the regions where the pending - buffer is different from the current surface contents, and where - the surface therefore needs to be repainted. The compositor - ignores the parts of the damage that fall outside of the surface. - - Damage is double-buffered state, see wl_surface.commit. - - The damage rectangle is specified in buffer coordinates, - where x and y specify the upper left corner of the damage rectangle. - - The initial value for pending damage is empty: no damage. - wl_surface.damage_buffer adds pending damage: the new pending - damage is the union of old pending damage and the given rectangle. - - wl_surface.commit assigns pending damage as the current damage, - and clears pending damage. The server will clear the current - damage as it repaints the surface. - - This request differs from wl_surface.damage in only one way - it - takes damage in buffer coordinates instead of surface-local - coordinates. While this generally is more intuitive than surface - coordinates, it is especially desirable when using wp_viewport - or when a drawing library (like EGL) is unaware of buffer scale - and buffer transform. - - Note: Because buffer transformation changes and damage requests may - be interleaved in the protocol stream, it is impossible to determine - the actual mapping between surface and buffer damage until - wl_surface.commit time. Therefore, compositors wishing to take both - kinds of damage into account will have to accumulate damage from the - two requests separately and only transform from one to the other - after receiving the wl_surface.commit. - - - - - - - - - - - - The x and y arguments specify the location of the new pending - buffer's upper left corner, relative to the current buffer's upper - left corner, in surface-local coordinates. In other words, the - x and y, combined with the new surface size define in which - directions the surface's size changes. - - The exact semantics of wl_surface.offset are role-specific. Refer to - the documentation of specific roles for more information. - - Surface location offset is double-buffered state, see - wl_surface.commit. - - This request is semantically equivalent to and the replaces the x and y - arguments in the wl_surface.attach request in wl_surface versions prior - to 5. See wl_surface.attach for details. - - - - - - - - - - This event indicates the preferred buffer scale for this surface. It is - sent whenever the compositor's preference changes. - - Before receiving this event the preferred buffer scale for this surface - is 1. - - It is intended that scaling aware clients use this event to scale their - content and use wl_surface.set_buffer_scale to indicate the scale they - have rendered with. This allows clients to supply a higher detail - buffer. - - The compositor shall emit a scale value greater than 0. - - - - - - - This event indicates the preferred buffer transform for this surface. - It is sent whenever the compositor's preference changes. - - Before receiving this event the preferred buffer transform for this - surface is normal. - - Applying this transformation to the surface buffer contents and using - wl_surface.set_buffer_transform might allow the compositor to use the - surface buffer more efficiently. - - - - - - - - - Create a callback for the release of the buffer attached by the client - with wl_surface.attach. - - The compositor will release the buffer when it has finished its usage of - the underlying storage for the relevant commit. Once the client receives - this event, and assuming the associated buffer is not pending release - from other wl_surface.commit requests, the client can safely re-use the - buffer. - - Release callbacks are double-buffered state, and will be associated - with the pending buffer at wl_surface.commit time. - - The callback_data passed in the wl_callback.done event is unused and - is always zero. - - Sending this request without attaching a non-null buffer in the same - content update is a protocol error. The compositor will send the - no_buffer error in this case. - - + - + A seat is a group of keyboards, pointer and touch devices. This object is published as a global during start up, or when such a @@ -1992,133 +1285,72 @@ maintains a keyboard focus and a pointer focus. - + This is a bitmask of capabilities this seat has; if a member is set, then it is present on the seat. - - - - - - - - These errors can be emitted in response to wl_seat requests. - - + + + - This is sent on binding to the seat global or whenever a seat gains - or loses the pointer, keyboard or touch capabilities. - The argument is a capability enum containing the complete set of - capabilities this seat has. - - When the pointer capability is added, a client may create a - wl_pointer object using the wl_seat.get_pointer request. This object - will receive pointer events until the capability is removed in the - future. - - When the pointer capability is removed, a client should destroy the - wl_pointer objects associated with the seat where the capability was - removed, using the wl_pointer.release request. No further pointer - events will be received on these objects. - - In some compositors, if a seat regains the pointer capability and a - client has a previously obtained wl_pointer object of version 4 or - less, that object may start sending pointer events again. This - behavior is considered a misinterpretation of the intended behavior - and must not be relied upon by the client. wl_pointer objects of - version 5 or later must not send events if created before the most - recent event notifying the client of an added pointer capability. - - The above behavior also applies to wl_keyboard and wl_touch with the - keyboard and touch capabilities, respectively. + This is emitted whenever a seat gains or loses the pointer, + keyboard or touch capabilities. The argument is a capability + enum containing the complete set of capabilities this seat has. - + The ID provided will be initialized to the wl_pointer interface - for this seat. + for this seat. This request only takes effect if the seat has the pointer - capability, or has had the pointer capability in the past. - It is a protocol violation to issue this request on a seat that has - never had the pointer capability. The missing_capability error will - be sent in this case. + capability. - + The ID provided will be initialized to the wl_keyboard interface - for this seat. + for this seat. This request only takes effect if the seat has the keyboard - capability, or has had the keyboard capability in the past. - It is a protocol violation to issue this request on a seat that has - never had the keyboard capability. The missing_capability error will - be sent in this case. + capability. - + The ID provided will be initialized to the wl_touch interface - for this seat. + for this seat. This request only takes effect if the seat has the touch - capability, or has had the touch capability in the past. - It is a protocol violation to issue this request on a seat that has - never had the touch capability. The missing_capability error will - be sent in this case. + capability. - + - + - In a multi-seat configuration the seat name can be used by clients to - help identify which physical devices the seat represents. - - The seat name is a UTF-8 string with no convention defined for its - contents. Each name is unique among all wl_seat globals. The name is - only guaranteed to be unique for the current compositor instance. - - The same seat names are used for all clients. Thus, the name can be - shared across processes to refer to a specific wl_seat global. - - The name event is sent after binding to the seat global, and should be sent - before announcing capabilities. This event only sent once per seat object, - and the name does not change over the lifetime of the wl_seat global. - - Compositors may re-use the same seat name if the wl_seat global is - destroyed and re-created later. + In a multiseat configuration this can be used by the client to help + identify which physical devices the seat represents. Based on + the seat configuration used by the compositor. - + - - - - - Using this request a client can tell the server that it is not going to - use the seat object anymore. - - - - + The wl_pointer interface represents one or more input devices, such as mice, which control the pointer location and pointer_focus @@ -2130,556 +1362,230 @@ and scrolling. - - - - - Set the pointer surface, i.e., the surface that contains the - pointer image (cursor). This request gives the surface the role - of a cursor. If the surface already has another role, it raises - a protocol error. + Set the pointer surface, i.e., the surface that contains the + pointer image (cursor). This request only takes effect if the pointer + focus for this device is one of the requesting client's surfaces + or the surface parameter is the current pointer surface. If + there was a previous surface set with this request it is + replaced. If surface is NULL, the pointer image is hidden. - The cursor actually changes only if the pointer - focus for this device is one of the requesting client's surfaces - or the surface parameter is the current pointer surface. If - there was a previous surface set with this request it is - replaced. If surface is NULL, the pointer image is hidden. + The parameters hotspot_x and hotspot_y define the position of + the pointer surface relative to the pointer location. Its + top-left corner is always at (x, y) - (hotspot_x, hotspot_y), + where (x, y) are the coordinates of the pointer location, in surface + local coordinates. - The parameters hotspot_x and hotspot_y define the position of - the pointer surface relative to the pointer location. Its - top-left corner is always at (x, y) - (hotspot_x, hotspot_y), - where (x, y) are the coordinates of the pointer location, in - surface-local coordinates. + On surface.attach requests to the pointer surface, hotspot_x + and hotspot_y are decremented by the x and y parameters + passed to the request. Attach must be confirmed by + wl_surface.commit as usual. - On wl_surface.offset requests to the pointer surface, hotspot_x - and hotspot_y are decremented by the x and y parameters - passed to the request. The offset must be applied by - wl_surface.commit as usual. + The hotspot can also be updated by passing the currently set + pointer surface to this request with new values for hotspot_x + and hotspot_y. - The hotspot can also be updated by passing the currently set - pointer surface to this request with new values for hotspot_x - and hotspot_y. - - The input region is ignored for wl_surfaces with the role of - a cursor. When the use as a cursor ends, the wl_surface is - unmapped. - - The serial parameter must match the latest wl_pointer.enter - serial number sent to the client. Otherwise the request will be - ignored. + The current and pending input regions of the wl_surface are + cleared, and wl_surface.set_input_region is ignored until the + wl_surface is no longer used as the cursor. When the use as a + cursor ends, the current and pending input regions become + undefined, and the wl_surface is unmapped. - - - - + + + + + - Notification that this seat's pointer is focused on a certain - surface. + Notification that this seat's pointer is focused on a certain + surface. - When a seat's focus enters a surface, the pointer image - is undefined and a client should respond to this event by setting - an appropriate pointer image with the set_cursor request. + When an seat's focus enters a surface, the pointer image + is undefined and a client should respond to this event by setting + an appropriate pointer image with the set_cursor request. - - - - + + + + + - Notification that this seat's pointer is no longer focused on - a certain surface. + Notification that this seat's pointer is no longer focused on + a certain surface. - The leave notification is sent before the enter notification - for the new focus. + The leave notification is sent before the enter notification + for the new focus. - - + + - Notification of pointer location change. The arguments - surface_x and surface_y are the location relative to the - focused surface. + Notification of pointer location change. The arguments + surface_x and surface_y are the location relative to the + focused surface. + - - + + - Describes the physical state of a button that produced the button - event. + Describes the physical state of a button which provoked the button + event. - - + + - Mouse button click and release notifications. + Mouse button click and release notifications. - The location of the click is given by the last motion or - enter event. + The location of the click is given by the last motion or + enter event. The time argument is a timestamp with millisecond granularity, with an undefined base. - - The button is a button code as defined in the Linux kernel's - linux/input-event-codes.h header file, e.g. BTN_LEFT. - - Any 16-bit button code value is reserved for future additions to the - kernel's event code list. All other button codes above 0xFFFF are - currently undefined but may be used in future versions of this - protocol. - + + - - + + - Describes the axis types of scroll events. + Describes the axis types of scroll events. - - + + - Scroll and other axis notifications. + Scroll and other axis notifications. - For scroll events (vertical and horizontal scroll axes), the - value parameter is the length of a vector along the specified - axis in a coordinate space identical to those of motion events, - representing a relative movement along the specified axis. + For scroll events (vertical and horizontal scroll axes), the + value parameter is the length of a vector along the specified + axis in a coordinate space identical to those of motion events, + representing a relative movement along the specified axis. - For devices that support movements non-parallel to axes multiple - axis events will be emitted. + For devices that support movements non-parallel to axes multiple + axis events will be emitted. - When applicable, for example for touch pads, the server can - choose to emit scroll events where the motion vector is - equivalent to a motion event vector. + When applicable, for example for touch pads, the server can + choose to emit scroll events where the motion vector is + equivalent to a motion event vector. - When applicable, a client can transform its content relative to the - scroll distance. + When applicable, clients can transform its view relative to the + scroll distance. + - - + + - - Using this request a client can tell the server that it is not going to - use the pointer object anymore. - - This request destroys the pointer proxy object, so clients must not call - wl_pointer_destroy() after using this request. - + - - - - - Indicates the end of a set of events that logically belong together. - A client is expected to accumulate the data in all events within the - frame before proceeding. - - All wl_pointer events before a wl_pointer.frame event belong - logically together. For example, in a diagonal scroll motion the - compositor will send an optional wl_pointer.axis_source event, two - wl_pointer.axis events (horizontal and vertical) and finally a - wl_pointer.frame event. The client may use this information to - calculate a diagonal vector for scrolling. - - When multiple wl_pointer.axis events occur within the same frame, - the motion vector is the combined motion of all events. - When a wl_pointer.axis and a wl_pointer.axis_stop event occur within - the same frame, this indicates that axis movement in one axis has - stopped but continues in the other axis. - When multiple wl_pointer.axis_stop events occur within the same - frame, this indicates that these axes stopped in the same instance. - - A wl_pointer.frame event is sent for every logical event group, - even if the group only contains a single wl_pointer event. - Specifically, a client may get a sequence: motion, frame, button, - frame, axis, frame, axis_stop, frame. - - The wl_pointer.enter and wl_pointer.leave events are logical events - generated by the compositor and not the hardware. These events are - also grouped by a wl_pointer.frame. When a pointer moves from one - surface to another, a compositor should group the - wl_pointer.leave event within the same wl_pointer.frame. - However, a client must not rely on wl_pointer.leave and - wl_pointer.enter being in the same wl_pointer.frame. - Compositor-specific policies may require the wl_pointer.leave and - wl_pointer.enter event being split across multiple wl_pointer.frame - groups. - - - - - - Describes the source types for axis events. This indicates to the - client how an axis event was physically generated; a client may - adjust the user interface accordingly. For example, scroll events - from a "finger" source may be in a smooth coordinate space with - kinetic scrolling whereas a "wheel" source may be in discrete steps - of a number of lines. - - The "continuous" axis source is a device generating events in a - continuous coordinate space, but using something other than a - finger. One example for this source is button-based scrolling where - the vertical motion of a device is converted to scroll events while - a button is held down. - - The "wheel tilt" axis source indicates that the actual device is a - wheel but the scroll event is not caused by a rotation but a - (usually sideways) tilt of the wheel. - - - - - - - - - - Source information for scroll and other axes. - - This event does not occur on its own. It is sent before a - wl_pointer.frame event and carries the source information for - all events within that frame. - - The source specifies how this event was generated. If the source is - wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be - sent when the user lifts the finger off the device. - - If the source is wl_pointer.axis_source.wheel, - wl_pointer.axis_source.wheel_tilt or - wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may - or may not be sent. Whether a compositor sends an axis_stop event - for these sources is hardware-specific and implementation-dependent; - clients must not rely on receiving an axis_stop event for these - scroll sources and should treat scroll sequences from these scroll - sources as unterminated by default. - - This event is optional. If the source is unknown for a particular - axis event sequence, no event is sent. - Only one wl_pointer.axis_source event is permitted per frame. - - The order of wl_pointer.axis_discrete and wl_pointer.axis_source is - not guaranteed. - - - - - - - Stop notification for scroll and other axes. - - For some wl_pointer.axis_source types, a wl_pointer.axis_stop event - is sent to notify a client that the axis sequence has terminated. - This enables the client to implement kinetic scrolling. - See the wl_pointer.axis_source documentation for information on when - this event may be generated. - - Any wl_pointer.axis events with the same axis_source after this - event should be considered as the start of a new axis motion. - - The timestamp is to be interpreted identical to the timestamp in the - wl_pointer.axis event. The timestamp value may be the same as a - preceding wl_pointer.axis event. - - - - - - - - Discrete step information for scroll and other axes. - - This event carries the axis value of the wl_pointer.axis event in - discrete steps (e.g. mouse wheel clicks). - - This event is deprecated with wl_pointer version 8 - this event is not - sent to clients supporting version 8 or later. - - This event does not occur on its own, it is coupled with a - wl_pointer.axis event that represents this axis value on a - continuous scale. The protocol guarantees that each axis_discrete - event is always followed by exactly one axis event with the same - axis number within the same wl_pointer.frame. Note that the protocol - allows for other events to occur between the axis_discrete and - its coupled axis event, including other axis_discrete or axis - events. A wl_pointer.frame must not contain more than one axis_discrete - event per axis type. - - This event is optional; continuous scrolling devices - like two-finger scrolling on touchpads do not have discrete - steps and do not generate this event. - - The discrete value carries the directional information. e.g. a value - of -2 is two steps towards the negative direction of this axis. - - The axis number is identical to the axis number in the associated - axis event. - - The order of wl_pointer.axis_discrete and wl_pointer.axis_source is - not guaranteed. - - - - - - - - Discrete high-resolution scroll information. - - This event carries high-resolution wheel scroll information, - with each multiple of 120 representing one logical scroll step - (a wheel detent). For example, an axis_value120 of 30 is one quarter of - a logical scroll step in the positive direction, a value120 of - -240 are two logical scroll steps in the negative direction within the - same hardware event. - Clients that rely on discrete scrolling should accumulate the - value120 to multiples of 120 before processing the event. - - The value120 must not be zero. - - This event replaces the wl_pointer.axis_discrete event in clients - supporting wl_pointer version 8 or later. - - Where a wl_pointer.axis_source event occurs in the same - wl_pointer.frame, the axis source applies to this event. - - The order of wl_pointer.axis_value120 and wl_pointer.axis_source is - not guaranteed. - - - - - - - - - - This specifies the direction of the physical motion that caused a - wl_pointer.axis event, relative to the wl_pointer.axis direction. - - - - - - - - Relative directional information of the entity causing the axis - motion. - - For a wl_pointer.axis event, the wl_pointer.axis_relative_direction - event specifies the movement direction of the entity causing the - wl_pointer.axis event. For example: - - if a user's fingers on a touchpad move down and this - causes a wl_pointer.axis vertical_scroll down event, the physical - direction is 'identical' - - if a user's fingers on a touchpad move down and this causes a - wl_pointer.axis vertical_scroll up scroll up event ('natural - scrolling'), the physical direction is 'inverted'. - - A client may use this information to adjust scroll motion of - components. Specifically, enabling natural scrolling causes the - content to change direction compared to traditional scrolling. - Some widgets like volume control sliders should usually match the - physical direction regardless of whether natural scrolling is - active. This event enables clients to match the scroll direction of - a widget to the physical direction. - - This event does not occur on its own, it is coupled with a - wl_pointer.axis event that represents this axis value. - The protocol guarantees that each axis_relative_direction event is - always followed by exactly one axis event with the same - axis number within the same wl_pointer.frame. Note that the protocol - allows for other events to occur between the axis_relative_direction - and its coupled axis event. - - The axis number is identical to the axis number in the associated - axis event. - - The order of wl_pointer.axis_relative_direction, - wl_pointer.axis_discrete and wl_pointer.axis_source is not - guaranteed. - - - - - + The wl_keyboard interface represents one or more keyboards associated with a seat. - - Each wl_keyboard has the following logical state: - - - an active surface (possibly null), - - the keys currently logically down, - - the active modifiers, - - the active group. - - By default, the active surface is null, the keys currently logically down - are empty, the active modifiers and the active group are 0. - This specifies the format of the keymap provided to the - client with the wl_keyboard.keymap event. + This specifies the format of the keymap provided to the + client with the wl_keyboard.keymap event. + summary="no keymap; client must understand how to interpret the raw keycode"/> + summary="libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode"/> - This event provides a file descriptor to the client which can be - memory-mapped in read-only mode to provide a keyboard mapping - description. - - From version 7 onwards, the fd must be mapped with MAP_PRIVATE by - the recipient, as MAP_SHARED may fail. + This event provides a file descriptor to the client which can be + memory-mapped to provide a keyboard mapping description. - - - + + + - Notification that this seat's keyboard focus is on a certain - surface. - - The compositor must send the wl_keyboard.modifiers event after this - event. - - In the wl_keyboard logical state, this event sets the active surface to - the surface argument and the keys currently logically down to the keys - in the keys argument. The compositor must not send this event if the - wl_keyboard already had an active surface immediately before this event. - - Clients should not use the list of pressed keys to emulate key-press - events. The order of keys in the list is unspecified. + Notification that this seat's keyboard focus is on a certain + surface. - - - + + + - Notification that this seat's keyboard focus is no longer on - a certain surface. + Notification that this seat's keyboard focus is no longer on + a certain surface. - The leave notification is sent before the enter notification - for the new focus. - - In the wl_keyboard logical state, this event resets all values to their - defaults. The compositor must not send this event if the active surface - of the wl_keyboard was not equal to the surface argument immediately - before this event. + The leave notification is sent before the enter notification + for the new focus. - - + + - Describes the physical state of a key that produced the key event. - - Since version 10, the key can be in a "repeated" pseudo-state which - means the same as "pressed", but is used to signal repetition in the - key event. - - The key may only enter the repeated state after entering the pressed - state and before entering the released state. This event may be - generated multiple times while the key is down. + Describes the physical state of a key which provoked the key event. - - A key was pressed or released. + A key was pressed or released. The time argument is a timestamp with millisecond granularity, with an undefined base. - - The key is a platform-specific key code that can be interpreted - by feeding it to the keyboard mapping (see the keymap event). - - If this event produces a change in modifiers, then the resulting - wl_keyboard.modifiers event must be sent after this event. - - In the wl_keyboard logical state, this event adds the key to the keys - currently logically down (if the state argument is pressed) or removes - the key from the keys currently logically down (if the state argument is - released). The compositor must not send this event if the wl_keyboard - did not have an active surface immediately before this event. The - compositor must not send this event if state is pressed (resp. released) - and the key was already logically down (resp. was not logically down) - immediately before this event. - - Since version 10, compositors may send key events with the "repeated" - key state when a wl_keyboard.repeat_info event with a rate argument of - 0 has been received. This allows the compositor to take over the - responsibility of key repetition. - + + - - + + - Notifies clients that the modifier and/or group state has - changed, and it should update its local state. - - The compositor may send this event without a surface of the client - having keyboard focus, for example to tie modifier information to - pointer focus instead. If a modifier event with pressed modifiers is sent - without a prior enter event, the client can assume the modifier state is - valid until it receives the next wl_keyboard.modifiers event. In order to - reset the modifier state again, the compositor can send a - wl_keyboard.modifiers event with no pressed modifiers. - - In the wl_keyboard logical state, this event updates the modifiers and - group. + Notifies clients that the modifier and/or group state has + changed, and it should update its local state. - - - - - + + + + + + @@ -2705,6 +1611,7 @@ so clients should continue listening for the event past the creation of wl_keyboard. + - + The wl_touch interface represents a touchscreen associated with a seat. @@ -2726,63 +1633,54 @@ - A new touch point has appeared on the surface. This touch point is - assigned a unique ID. Future events from this touch point reference - this ID. The ID ceases to be valid after a touch up event and may be - reused in the future. + A new touch point has appeared on the surface. This touch point is + assigned a unique @id. Future events from this touchpoint reference + this ID. The ID ceases to be valid after a touch up event and may be + re-used in the future. - + - + - - + + - The touch point has disappeared. No further events will be sent for - this touch point and the touch point's ID is released and may be - reused in a future touch down event. + The touch point has disappeared. No further events will be sent for + this touchpoint and the touch point's ID is released and may be + re-used in a future touch down event. - + - A touch point has changed coordinates. + A touchpoint has changed coordinates. - - + + - Indicates the end of a set of events that logically belong together. - A client is expected to accumulate the data in all events within the - frame before proceeding. - - A wl_touch.frame terminates at least one event but otherwise no - guarantee is provided about the set of events within a frame. A client - must assume that any state not updated in a frame is unchanged from the - previously known state. + Indicates the end of a contact point list. - Sent if the compositor decides the touch stream is a global - gesture. No further events are sent to the clients from that - particular gesture. Touch cancellation applies to all touch points - currently active on this client's surface. The client is - responsible for finalizing the touch points, future touch points on - this surface may reuse the touch point ID. - - No frame event is required after the cancel event. + Sent if the compositor decides the touch stream is a global + gesture. No further events are sent to the clients from that + particular gesture. Touch cancellation applies to all touch points + currently active on this client's surface. The client is + responsible for finalizing the touch points, future touch points on + this surface may re-use the touch point ID. @@ -2791,78 +1689,13 @@ - - - - - - Sent when a touchpoint has changed its shape. - - This event does not occur on its own. It is sent before a - wl_touch.frame event and carries the new shape information for - any previously reported, or new touch points of that frame. - - Other events describing the touch point such as wl_touch.down, - wl_touch.motion or wl_touch.orientation may be sent within the - same wl_touch.frame. A client should treat these events as a single - logical touch point update. The order of wl_touch.shape, - wl_touch.orientation and wl_touch.motion is not guaranteed. - A wl_touch.down event is guaranteed to occur before the first - wl_touch.shape event for this touch ID but both events may occur within - the same wl_touch.frame. - - A touchpoint shape is approximated by an ellipse through the major and - minor axis length. The major axis length describes the longer diameter - of the ellipse, while the minor axis length describes the shorter - diameter. Major and minor are orthogonal and both are specified in - surface-local coordinates. The center of the ellipse is always at the - touchpoint location as reported by wl_touch.down or wl_touch.move. - - This event is only sent by the compositor if the touch device supports - shape reports. The client has to make reasonable assumptions about the - shape if it did not receive this event. - - - - - - - - - Sent when a touchpoint has changed its orientation. - - This event does not occur on its own. It is sent before a - wl_touch.frame event and carries the new shape information for - any previously reported, or new touch points of that frame. - - Other events describing the touch point such as wl_touch.down, - wl_touch.motion or wl_touch.shape may be sent within the - same wl_touch.frame. A client should treat these events as a single - logical touch point update. The order of wl_touch.shape, - wl_touch.orientation and wl_touch.motion is not guaranteed. - A wl_touch.down event is guaranteed to occur before the first - wl_touch.orientation event for this touch ID but both events may occur - within the same wl_touch.frame. - - The orientation describes the clockwise angle of a touchpoint's major - axis to the positive surface y-axis and is normalized to the -180 to - +180 degree range. The granularity of orientation depends on the touch - device, some devices only support binary rotation values between 0 and - 90 degrees. - - This event is only sent by the compositor if the touch device supports - orientation reports. - - - - - + An output describes part of the compositor geometry. The compositor works in the 'compositor coordinate system' and an - output corresponds to a rectangular area in that space that is + output corresponds to rectangular area in that space that is actually visible. This typically corresponds to a monitor that displays part of the compositor space. This object is published as global during start up, or when a monitor is hotplugged. @@ -2870,139 +1703,102 @@ - This enumeration describes how the physical - pixels on an output are laid out. + This enumeration describes how the physical + pixels on an output are layed out. - - - - - - + + + + + + - - This describes transformations that clients and compositors apply to - buffer contents. + + This describes the transform that a compositor will apply to a + surface to compensate for the rotation or mirroring of an + output device. - The flipped values correspond to an initial flip around a - vertical axis followed by rotation. + The flipped values correspond to an initial flip around a + vertical axis followed by rotation. - The purpose is mainly to allow clients to render accordingly and - tell the compositor, so that for fullscreen surfaces, the - compositor will still be able to scan out directly from client - surfaces. + The purpose is mainly to allow clients render accordingly and + tell the compositor, so that for fullscreen surfaces, the + compositor will still be able to scan out directly from client + surfaces. - - - - - - - - + + + + + + + + + - The geometry event describes geometric properties of the output. - The event is sent when binding to the output object and whenever - any of the properties change. - - The physical size can be set to zero if it doesn't make sense for this - output (e.g. for projectors or virtual outputs). - - The geometry event will be followed by a done event (starting from - version 2). - - Clients should use wl_surface.preferred_buffer_transform instead of the - transform advertised by this event to find the preferred buffer - transform to use for a surface. - - Note: wl_output only advertises partial information about the output - position and identification. Some compositors, for instance those not - implementing a desktop-style output layout or those exposing virtual - outputs, might fake this information. Instead of using x and y, clients - should use xdg_output.logical_position. Instead of using make and model, - clients should use name and description. + The geometry event describes geometric properties of the output. + The event is sent when binding to the output object and whenever + any of the properties change. + summary="x position within the global compositor space"/> + summary="y position within the global compositor space"/> + summary="width in millimeters of the output"/> - + summary="height in millimeters of the output"/> + + summary="textual description of the manufacturer"/> - + summary="textual description of the model"/> + - + - These flags describe properties of an output mode. - They are used in the flags bitfield of the mode event. + These flags describe properties of an output mode. + They are used in the flags bitfield of the mode event. + summary="indicates this is the current mode"/> + summary="indicates this is the preferred mode"/> - The mode event describes an available mode for the output. + The mode event describes an available mode for the output. - The event is sent when binding to the output object and there - will always be one mode, the current mode. The event is sent - again if an output changes mode, for the mode that is now - current. In other words, the current mode is always the last - mode that was received with the current flag set. + The event is sent when binding to the output object and there + will always be one mode, the current mode. The event is sent + again if an output changes mode, for the mode that is now + current. In other words, the current mode is always the last + mode that was received with the current flag set. - Non-current modes are deprecated. A compositor can decide to only - advertise the current mode and never send other modes. Clients - should not rely on non-current modes. - - The size of a mode is given in physical hardware units of + The size of a mode is given in physical hardware units of the output device. This is not necessarily the same as the output size in the global compositor space. For instance, the output may be scaled, as described in wl_output.scale, - or transformed, as described in wl_output.transform. Clients - willing to retrieve the output size in the global compositor - space should use xdg_output.logical_size instead. - - The vertical refresh rate can be set to zero if it doesn't make - sense for this output (e.g. for virtual outputs). - - The mode event will be followed by a done event (starting from - version 2). - - Clients should not use the refresh rate to schedule frames. Instead, - they should use the wl_surface.frame event or the presentation-time - protocol. - - Note: this information is not always meaningful for all outputs. Some - compositors, such as those exposing virtual outputs, might fake the - refresh rate or the size. + or transformed , as described in wl_output.transform. - + - - - This event is sent after all other properties have been + This event is sent after all other properties has been sent after binding to the output object and after any other property changes done after that. This allows changes to the output properties to be seen as @@ -3012,95 +1808,30 @@ - This event contains scaling geometry information + This event contains scaling geometry information that is not in the geometry event. It may be sent after binding the output object or if the output scale changes - later. The compositor will emit a non-zero, positive - value for scale. If it is not sent, the client should - assume a scale of 1. + later. If it is not sent, the client should assume a + scale of 1. - A scale larger than 1 means that the compositor will - automatically scale surface buffers by this amount - when rendering. This is used for very high resolution - displays where applications rendering at the native - resolution would be too small to be legible. + A scale larger than 1 means that the compositor will + automatically scale surface buffers by this amount + when rendering. This is used for very high resolution + displays where applications rendering at the native + resolution would be too small to be legible. - Clients should use wl_surface.preferred_buffer_scale - instead of this event to find the preferred buffer - scale to use for a surface. - - The scale event will be followed by a done event. + It is intended that scaling aware clients track the + current output of a surface, and if it is on a scaled + output it should use wl_surface.set_buffer_scale with + the scale of the output. That way the compositor can + avoid scaling the surface, and the client can supply + a higher detail image. - - - - - - Using this request a client can tell the server that it is not going to - use the output object anymore. - - - - - - - - Many compositors will assign user-friendly names to their outputs, show - them to the user, allow the user to refer to an output, etc. The client - may wish to know this name as well to offer the user similar behaviors. - - The name is a UTF-8 string with no convention defined for its contents. - Each name is unique among all wl_output globals. The name is only - guaranteed to be unique for the compositor instance. - - The same output name is used for all clients for a given wl_output - global. Thus, the name can be shared across processes to refer to a - specific wl_output global. - - The name is not guaranteed to be persistent across sessions, thus cannot - be used to reliably identify an output in e.g. configuration files. - - Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do - not assume that the name is a reflection of an underlying DRM connector, - X11 connection, etc. - - The name event is sent after binding the output object. This event is - only sent once per output object, and the name does not change over the - lifetime of the wl_output global. - - Compositors may re-use the same output name if the wl_output global is - destroyed and re-created later. Compositors should avoid re-using the - same name if possible. - - The name event will be followed by a done event. - - - - - - - Many compositors can produce human-readable descriptions of their - outputs. The client may wish to know this description as well, e.g. for - output selection purposes. - - The description is a UTF-8 string with no convention defined for its - contents. The description is not guaranteed to be unique among all - wl_output globals. Examples might include 'Foocorp 11" Display' or - 'Virtual X11 output via :1'. - - The description event is sent after binding the output object and - whenever the description changes. The description is optional, and may - not be sent at all. - - The description event will be followed by a done event. - - - - + A region object describes an area. @@ -3110,29 +1841,32 @@ - Destroy the region. This will invalidate the object ID. + Destroy the region. This will invalidate the object ID. - Add the specified rectangle to the region. + Add the specified rectangle to the region. - - - - + + + + + - Subtract the specified rectangle from the region. + Subtract the specified rectangle from the region. - - - - + + + + + + @@ -3160,43 +1894,30 @@ - Informs the server that the client will not be using this - protocol object anymore. This does not affect any other - objects, wl_subsurface objects included. + Informs the server that the client will not be using this + protocol object anymore. This does not affect any other + objects, wl_subsurface objects included. - - Create a sub-surface interface for the given surface, and - associate it with the given parent surface. This turns a - plain wl_surface into a sub-surface. + Create a sub-surface interface for the given surface, and + associate it with the given parent surface. This turns a + plain wl_surface into a sub-surface. - The to-be sub-surface must not already have another role, and it - must not have an existing wl_subsurface object. Otherwise the - bad_surface protocol error is raised. - - Adding sub-surfaces to a parent is a double-buffered operation on the - parent (see wl_surface.commit). The effect of adding a sub-surface - becomes visible on the next time the state of the parent surface is - applied. - - The parent surface must not be one of the child surface's descendants, - and the parent must be different from the child surface, otherwise the - bad_parent protocol error is raised. - - This request modifies the behaviour of wl_surface.commit request on - the sub-surface, see the documentation on wl_subsurface interface. + The to-be sub-surface must not already have a dedicated + purpose, like any shell surface type, cursor image, drag icon, + or sub-surface. Otherwise a protocol error is raised. + + summary="the new subsurface object id"/> - The sub-surface interface is removed from the wl_surface object - that was turned into a sub-surface with a - wl_subcompositor.get_subsurface request. The wl_surface's association - to the parent is deleted. The wl_surface is unmapped immediately. + The sub-surface interface is removed from the wl_surface object + that was turned into a sub-surface with + wl_subcompositor.get_subsurface request. The wl_surface's association + to the parent is deleted, and the wl_surface loses its role as + a sub-surface. The wl_surface is unmapped. @@ -3271,133 +1995,99 @@ - This sets the position of the sub-surface, relative to the parent - surface. + This schedules a sub-surface position change. + The sub-surface will be moved so, that its origin (top-left + corner pixel) will be at the location x, y of the parent surface + coordinate system. The coordinates are not restricted to the parent + surface area. Negative values are allowed. - The sub-surface will be moved so that its origin (top left - corner pixel) will be at the location x, y of the parent surface - coordinate system. The coordinates are not restricted to the parent - surface area. Negative values are allowed. + The next wl_surface.commit on the parent surface will reset + the sub-surface's position to the scheduled coordinates. - The initial position is 0, 0. + If more than one set_position request is invoked by the client before + the commit of the parent surface, the position of a new request always + replaces the scheduled position from any previous request. - Position is double-buffered state on the parent surface, see - wl_subsurface and wl_surface.commit for more information. + The initial position is 0, 0. - - + + + - This sub-surface is taken from the stack, and put back just - above the reference surface, changing the z-order of the sub-surfaces. - The reference surface must be one of the sibling surfaces, or the - parent surface. Using any other surface, including this sub-surface, - will cause a protocol error. + This sub-surface is taken from the stack, and put back just + above the reference surface, changing the z-order of the sub-surfaces. + The reference surface must be one of the sibling surfaces, or the + parent surface. Using any other surface, including this sub-surface, + will cause a protocol error. - A new sub-surface is initially added as the top-most in the stack - of its siblings and parent. + The z-order is double-buffered. Requests are handled in order and + applied immediately to a pending state, then committed to the active + state on the next commit of the parent surface. + See wl_surface.commit and wl_subcompositor.get_subsurface. - Z-order is double-buffered state on the parent surface, see - wl_subsurface and wl_surface.commit for more information. + A new sub-surface is initially added as the top-most in the stack + of its siblings and parent. + - The sub-surface is placed just below the reference surface. - - See wl_subsurface.place_above. + The sub-surface is placed just below of the reference surface. + See wl_subsurface.place_above. + - Change the commit behaviour of the sub-surface to synchronized - mode. + Change the commit behaviour of the sub-surface to synchronized + mode, also described as the parent dependant mode. - See wl_subsurface and wl_surface.commit for more information. + In synchronized mode, wl_surface.commit on a sub-surface will + accumulate the committed state in a cache, but the state will + not be applied and hence will not change the compositor output. + The cached state is applied to the sub-surface immediately after + the parent surface's state is applied. This ensures atomic + updates of the parent and all its synchronized sub-surfaces. + Applying the cached state will invalidate the cache, so further + parent surface commits do not (re-)apply old state. + + See wl_subsurface for the recursive effect of this mode. - Change the commit behaviour of the sub-surface to desynchronized - mode. + Change the commit behaviour of the sub-surface to desynchronized + mode, also described as independent or freely running mode. - See wl_subsurface and wl_surface.commit for more information. + In desynchronized mode, wl_surface.commit on a sub-surface will + apply the pending state directly, without caching, as happens + normally with a wl_surface. Calling wl_surface.commit on the + parent surface has no effect on the sub-surface's wl_surface + state. This mode allows a sub-surface to be updated on its own. + + If cached state exists when wl_surface.commit is called in + desynchronized mode, the pending state is added to the cached + state, and applied as whole. This invalidates the cache. + + Note: even if a sub-surface is set to desynchronized, a parent + sub-surface may override it to behave as synchronized. For details, + see wl_subsurface. + + If a surface's parent surface behaves as desynchronized, then + the cached state is applied on set_desync. - - - - This global fixes problems with other core-protocol interfaces that - cannot be fixed in these interfaces themselves. - - - - - These errors can be emitted in response to wl_fixes requests. - - - - - - - - - - - This request destroys a wl_registry object. - - The client should no longer use the wl_registry after making this - request. - - The compositor will emit a wl_display.delete_id event with the object ID - of the registry and will no longer emit any events on the registry. The - client should re-use the object ID once it receives the - wl_display.delete_id event. - - - - - - - Acknowledge the removal of the specified global. - - If no global with the specified name exists or the global is not removed, - the wl_fixes.invalid_ack_remove protocol error will be posted. - - Due to the Wayland protocol being asynchronous, the wl_global objects - cannot be destroyed immediately. For example, if a wl_global is removed - and a client attempts to bind that global around same time, it can - result in a protocol error due to an unknown global name in the bind - request. - - In order to avoid crashing clients, the compositor should remove the - wl_global once it is guaranteed that no more bind requests will come. - - The wl_fixes.ack_global_remove() request is used to signal to the - compositor that the client will not bind the given global anymore. After - all clients acknowledge the removal of the global, the compositor can - safely destroy it. - - The client must call the wl_fixes.ack_global_remove() request in - response to a wl_registry.global_remove() event even if it did not bind - the corresponding global. - - - - diff --git a/release.sh b/release.sh deleted file mode 100755 index 8e843f56..00000000 --- a/release.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh -eu - -build_dir=build-release - -if ! type glab >/dev/null; then - echo "glab is needed to create a release" - exit 1 -fi - -case "$(git rev-parse --abbrev-ref HEAD)" in -main | [0-9]*.[0-9]*) - ;; -*) - echo "Not on the main or a stable branch" - exit 1 -esac - -if [ -n "$(git log @{upstream}..)" ]; then - echo "The main branch has unpushed commits" - exit 1 -fi - -meson_options="" -if [ -e "$build_dir" ]; then - meson_options="$meson_options --wipe" -fi -meson setup "$build_dir" $meson_options - -prev_version="$(git describe --tags --abbrev=0)" -version="$(meson introspect "$build_dir" --projectinfo | jq -r .version)" -if [ "$version" = "$prev_version" ]; then - echo "Version not bumped" - exit 1 -fi - -name="$(meson introspect "$build_dir" --projectinfo | jq -r .descriptive_name)" -if [ "$name" = "" ]; then - echo "Cannot determine project name" - exit 1 -fi - -ninja -C "$build_dir" dist - -archive_name="$name-$version.tar.xz" -archive_path="$build_dir/meson-dist/$archive_name" -gpg --detach-sig "$archive_path" - -sha256="$(cd $build_dir/meson-dist && sha256sum $archive_name)" -sha512="$(cd $build_dir/meson-dist && sha512sum $archive_name)" -archive_url="https://gitlab.freedesktop.org/wayland/$name/-/releases/$version/downloads/$archive_name" -announce_path="$build_dir/meson-dist/$name-$version-announce.eml" -current_branch=$(git branch --show-current) -remote_name=$(git config --get branch.${current_branch}.remote) - -cat >"$announce_path" < -Subject: [ANNOUNCE] $name $version - -`git shortlog --no-merges "$prev_version.."` - -git tag: $version - -$archive_url -SHA256: $sha256 -SHA512: $sha512 -PGP: $archive_url.sig -EOF - -echo "Release announcement written to $announce_path" - -echo -n "Release $name $version? [y/N] " -read answer -if [ "$answer" != "y" ]; then - exit 1 -fi - -git tag -s -m "$version" "$version" -git push "$remote_name" "$version" -glab release create "$version" "$archive_path"* --notes "" diff --git a/releasing.txt b/releasing.txt deleted file mode 100644 index e93f53dd..00000000 --- a/releasing.txt +++ /dev/null @@ -1,62 +0,0 @@ -To make a release of Wayland, 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. Update the first stanza of meson.build to the intended version. - - Then commit your changes: - - $ export RELEASE_NUMBER="x.y.z" - $ export 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 - - 2. Run the release.sh script to generate the tarballs, sign and - upload them, and generate a release announcement template. - - 3. Compose the release announcements. The script will generate a - wayland-x.y.z-announce.eml file with a list of changes and tags. - Prepend it 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. - - 4. PGP sign the release announcements and send them to - wayland-devel@lists.freedesktop.org - - 5. Update releases.html in wayland-web with links to tarballs and - the release email URL. - - The wl_register_release script in wayland-web will generate an HTML - snippet that can be pasted into releases.html (or e.g. in emacs - insert it via "C-u M-! scripts/wl_register_release x.y.z") and - customized. - - Once satisfied: - - $ git commit ./releases.html -m "releases: Add ${RELEASE_NUMBER} release" - $ git push - $ ./deploy - -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 cherry-pick -them back to the stable branch. diff --git a/spec/.gitignore b/spec/.gitignore new file mode 100644 index 00000000..4962683d --- /dev/null +++ b/spec/.gitignore @@ -0,0 +1,3 @@ +main.aux +main.log +main.pdf diff --git a/spec/wayland-architecture.png b/spec/wayland-architecture.png new file mode 100644 index 00000000..4f92e0fb Binary files /dev/null and b/spec/wayland-architecture.png differ diff --git a/spec/x-architecture.png b/spec/x-architecture.png new file mode 100644 index 00000000..098205b5 Binary files /dev/null and b/spec/x-architecture.png differ diff --git a/src/.gitignore b/src/.gitignore index 128e4f7c..1438b744 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,5 @@ -*.dtd.embed +wayland-scanner +wayland-client-protocol.h +wayland-protocol.c +wayland-server-protocol.h /wayland-version.h diff --git a/src/connection.c b/src/connection.c index 2d1e8d1d..f2928536 100644 --- a/src/connection.c +++ b/src/connection.c @@ -2,32 +2,27 @@ * Copyright © 2008 Kristian Høgsberg * Copyright © 2013 Jason Ekstrand * - * 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: + * 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 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. + * 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. */ #define _GNU_SOURCE -#include "../config.h" - #include #include #include @@ -35,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -46,66 +42,42 @@ #include "wayland-private.h" #include "wayland-os.h" -static inline uint32_t -div_roundup(uint32_t n, size_t a) -{ - /* The cast to uint64_t is necessary to prevent overflow when rounding - * values close to UINT32_MAX. After the division it is again safe to - * cast back to uint32_t. - */ - return (uint32_t) (((uint64_t) n + (a - 1)) / a); -} +#define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) ) -struct wl_ring_buffer { - char *data; - size_t head, tail; - uint32_t size_bits; - uint32_t max_size_bits; /* 0 for unlimited */ +struct wl_buffer { + char data[4096]; + uint32_t head, tail; }; +#define MASK(i) ((i) & 4095) + #define MAX_FDS_OUT 28 #define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t))) struct wl_connection { - struct wl_ring_buffer in, out; - struct wl_ring_buffer fds_in, fds_out; + struct wl_buffer in, out; + struct wl_buffer fds_in, fds_out; int fd; int want_flush; }; -static inline size_t -size_pot(uint32_t size_bits) -{ - if (!(size_bits < 8 * sizeof(size_t))) - wl_abort("Too many bits for size_t\n"); - - return ((size_t)1) << size_bits; -} - -static size_t -ring_buffer_capacity(const struct wl_ring_buffer *b) { - return size_pot(b->size_bits); -} - -static size_t -ring_buffer_mask(const struct wl_ring_buffer *b, size_t i) { - size_t m = ring_buffer_capacity(b) - 1; - return i & m; -} - static int -ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count) +wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) { - size_t head, size; + uint32_t head, size; - if (count == 0) - return 0; + if (count > sizeof(b->data)) { + wl_log("Data too big for buffer (%d > %d).\n", + count, sizeof(b->data)); + errno = E2BIG; + return -1; + } - head = ring_buffer_mask(b, b->head); - if (head + count <= ring_buffer_capacity(b)) { + head = MASK(b->head); + if (head + count <= sizeof b->data) { memcpy(b->data + head, data, count); } else { - size = ring_buffer_capacity(b) - head; + size = sizeof b->data - head; memcpy(b->data + head, data, size); memcpy(b->data, (const char *) data + size, count - size); } @@ -116,23 +88,23 @@ ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count) } static void -ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) +wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count) { - size_t head, tail; + uint32_t head, tail; - head = ring_buffer_mask(b, b->head); - tail = ring_buffer_mask(b, b->tail); + head = MASK(b->head); + tail = MASK(b->tail); if (head < tail) { iov[0].iov_base = b->data + head; iov[0].iov_len = tail - head; *count = 1; } else if (tail == 0) { iov[0].iov_base = b->data + head; - iov[0].iov_len = ring_buffer_capacity(b) - head; + iov[0].iov_len = sizeof b->data - head; *count = 1; } else { iov[0].iov_base = b->data + head; - iov[0].iov_len = ring_buffer_capacity(b) - head; + iov[0].iov_len = sizeof b->data - head; iov[1].iov_base = b->data; iov[1].iov_len = tail; *count = 2; @@ -140,23 +112,23 @@ ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) } static void -ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) +wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count) { - size_t head, tail; + uint32_t head, tail; - head = ring_buffer_mask(b, b->head); - tail = ring_buffer_mask(b, b->tail); + head = MASK(b->head); + tail = MASK(b->tail); if (tail < head) { iov[0].iov_base = b->data + tail; iov[0].iov_len = head - tail; *count = 1; } else if (head == 0) { iov[0].iov_base = b->data + tail; - iov[0].iov_len = ring_buffer_capacity(b) - tail; + iov[0].iov_len = sizeof b->data - tail; *count = 1; } else { iov[0].iov_base = b->data + tail; - iov[0].iov_len = ring_buffer_capacity(b) - tail; + iov[0].iov_len = sizeof b->data - tail; iov[1].iov_base = b->data; iov[1].iov_len = head; *count = 2; @@ -164,222 +136,72 @@ ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) } static void -ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count) +wl_buffer_copy(struct wl_buffer *b, void *data, size_t count) { - size_t tail, size; + uint32_t tail, size; - if (count == 0) - return; - - tail = ring_buffer_mask(b, b->tail); - if (tail + count <= ring_buffer_capacity(b)) { + tail = MASK(b->tail); + if (tail + count <= sizeof b->data) { memcpy(data, b->data + tail, count); } else { - size = ring_buffer_capacity(b) - tail; + size = sizeof b->data - tail; memcpy(data, b->data + tail, size); memcpy((char *) data + size, b->data, count - size); } } -static size_t -ring_buffer_size(struct wl_ring_buffer *b) +static uint32_t +wl_buffer_size(struct wl_buffer *b) { return b->head - b->tail; } -static char * -ring_buffer_tail(const struct wl_ring_buffer *b) -{ - return b->data + ring_buffer_mask(b, b->tail); -} - -static uint32_t -get_max_size_bits_for_size(size_t buffer_size) -{ - uint32_t max_size_bits = WL_BUFFER_DEFAULT_SIZE_POT; - - /* buffer_size == 0 means unbound buffer size */ - if (buffer_size == 0) - return 0; - - while (max_size_bits < 8 * sizeof(size_t) && size_pot(max_size_bits) < buffer_size) - max_size_bits++; - - return max_size_bits; -} - -static int -ring_buffer_allocate(struct wl_ring_buffer *b, size_t size_bits) -{ - char *new_data; - - new_data = calloc(size_pot(size_bits), 1); - if (!new_data) - return -1; - - ring_buffer_copy(b, new_data, ring_buffer_size(b)); - free(b->data); - b->data = new_data; - b->size_bits = size_bits; - b->head = ring_buffer_size(b); - b->tail = 0; - - return 0; -} - -static size_t -ring_buffer_get_bits_for_size(struct wl_ring_buffer *b, size_t net_size) -{ - size_t max_size_bits = get_max_size_bits_for_size(net_size); - - if (max_size_bits < WL_BUFFER_DEFAULT_SIZE_POT) - max_size_bits = WL_BUFFER_DEFAULT_SIZE_POT; - - if (b->max_size_bits > 0 && max_size_bits > b->max_size_bits) - max_size_bits = b->max_size_bits; - - return max_size_bits; -} - -static bool -ring_buffer_is_max_size_reached(struct wl_ring_buffer *b) -{ - size_t net_size = ring_buffer_size(b) + 1; - size_t size_bits = ring_buffer_get_bits_for_size(b, net_size); - - return net_size >= size_pot(size_bits); -} - -static int -ring_buffer_ensure_space(struct wl_ring_buffer *b, size_t count) -{ - size_t net_size = ring_buffer_size(b) + count; - size_t size_bits = ring_buffer_get_bits_for_size(b, net_size); - - /* The 'size_bits' value represents the required size (in POT) to store - * 'net_size', which depending whether the buffers are bounded or not - * might not be sufficient (i.e. we might have reached the maximum size - * allowed). - */ - if (net_size > size_pot(size_bits)) { - wl_log("Data too big for buffer (%zu + %zu > %zu).\n", - ring_buffer_size(b), count, size_pot(size_bits)); - errno = E2BIG; - return -1; - } - - /* The following test here is a short-cut to avoid reallocating a buffer - * of the same size. - */ - if (size_bits == b->size_bits) - return 0; - - /* Otherwise, we (re)allocate the buffer to match the required size */ - return ring_buffer_allocate(b, size_bits); -} - -static void -ring_buffer_close_fds(struct wl_ring_buffer *buffer, int32_t count) -{ - int32_t i, *p; - size_t size, tail; - - size = ring_buffer_capacity(buffer); - tail = ring_buffer_mask(buffer, buffer->tail); - p = (int32_t *) (buffer->data + tail); - - for (i = 0; i < count; i++) { - if (p >= (int32_t *) (buffer->data + size)) - p = (int32_t *) buffer->data; - close(*p++); - } -} - -void -wl_connection_set_max_buffer_size(struct wl_connection *connection, - size_t max_buffer_size) -{ - uint32_t max_size_bits; - - max_size_bits = get_max_size_bits_for_size(max_buffer_size); - - connection->fds_in.max_size_bits = max_size_bits; - ring_buffer_ensure_space(&connection->fds_in, 0); - - connection->fds_out.max_size_bits = max_size_bits; - ring_buffer_ensure_space(&connection->fds_out, 0); - - connection->in.max_size_bits = max_size_bits; - ring_buffer_ensure_space(&connection->in, 0); - - connection->out.max_size_bits = max_size_bits; - ring_buffer_ensure_space(&connection->out, 0); -} - struct wl_connection * -wl_connection_create(int fd, size_t max_buffer_size) +wl_connection_create(int fd) { struct wl_connection *connection; - connection = zalloc(sizeof *connection); + connection = malloc(sizeof *connection); if (connection == NULL) return NULL; - - wl_connection_set_max_buffer_size(connection, max_buffer_size); - + memset(connection, 0, sizeof *connection); connection->fd = fd; return connection; } static void -close_fds(struct wl_ring_buffer *buffer, int max) +close_fds(struct wl_buffer *buffer, int max) { + int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count; size_t size; - int32_t count; - size = ring_buffer_size(buffer); + size = buffer->head - buffer->tail; if (size == 0) return; - count = size / sizeof(int32_t); + wl_buffer_copy(buffer, fds, size); + count = size / sizeof fds[0]; if (max > 0 && max < count) count = max; - - ring_buffer_close_fds(buffer, count); - - size = count * sizeof(int32_t); + for (i = 0; i < count; i++) + close(fds[i]); buffer->tail += size; } void -wl_connection_close_fds_in(struct wl_connection *connection, int max) -{ - close_fds(&connection->fds_in, max); -} - -int wl_connection_destroy(struct wl_connection *connection) { - int fd = connection->fd; - close_fds(&connection->fds_out, -1); - free(connection->fds_out.data); - free(connection->out.data); - close_fds(&connection->fds_in, -1); - free(connection->fds_in.data); - free(connection->in.data); - + close(connection->fd); free(connection); - - return fd; } void wl_connection_copy(struct wl_connection *connection, void *data, size_t size) { - ring_buffer_copy(&connection->in, data, size); + wl_buffer_copy(&connection->in, data, size); } void @@ -389,12 +211,12 @@ wl_connection_consume(struct wl_connection *connection, size_t size) } static void -build_cmsg(struct wl_ring_buffer *buffer, char *data, size_t *clen) +build_cmsg(struct wl_buffer *buffer, char *data, int *clen) { struct cmsghdr *cmsg; size_t size; - size = ring_buffer_size(buffer); + size = buffer->head - buffer->tail; if (size > MAX_FDS_OUT * sizeof(int32_t)) size = MAX_FDS_OUT * sizeof(int32_t); @@ -403,7 +225,7 @@ build_cmsg(struct wl_ring_buffer *buffer, char *data, size_t *clen) cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(size); - ring_buffer_copy(buffer, CMSG_DATA(cmsg), size); + wl_buffer_copy(buffer, CMSG_DATA(cmsg), size); *clen = cmsg->cmsg_len; } else { *clen = 0; @@ -411,10 +233,10 @@ build_cmsg(struct wl_ring_buffer *buffer, char *data, size_t *clen) } static int -decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg) +decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg) { struct cmsghdr *cmsg; - size_t size, i; + size_t size, max, i; int overflow = 0; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; @@ -424,13 +246,13 @@ decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg) continue; size = cmsg->cmsg_len - CMSG_LEN(0); - - if (ring_buffer_ensure_space(buffer, size) < 0 || overflow) { + max = sizeof(buffer->data) - wl_buffer_size(buffer); + if (size > max || overflow) { overflow = 1; size /= sizeof(int32_t); for (i = 0; i < size; i++) close(((int*)CMSG_DATA(cmsg))[i]); - } else if (ring_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) { + } else if (wl_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) { return -1; } } @@ -447,48 +269,27 @@ int wl_connection_flush(struct wl_connection *connection) { struct iovec iov[2]; - struct msghdr msg = {0}; + struct msghdr msg; char cmsg[CLEN]; - int len = 0, count; - size_t clen; - size_t tail; + int len = 0, count, clen; + uint32_t tail; if (!connection->want_flush) return 0; tail = connection->out.tail; - while (ring_buffer_size(&connection->out) > 0) { - build_cmsg(&connection->fds_out, cmsg, &clen); + while (connection->out.head - connection->out.tail > 0) { + wl_buffer_get_iov(&connection->out, iov, &count); - if (clen >= CLEN) { - /* UNIX domain sockets allows to send file descriptors - * using ancillary data. - * - * As per the UNIX domain sockets man page (man 7 unix), - * "at least one byte of real data should be sent when - * sending ancillary data". - * - * This is why we send only a single byte here, to ensure - * all file descriptors are sent before the bytes are - * cleared out. - * - * Otherwise This can fail to clear the file descriptors - * first if individual messages are allowed to have 224 - * (8 bytes * MAX_FDS_OUT = 224) file descriptors . - */ - iov[0].iov_base = ring_buffer_tail(&connection->out); - iov[0].iov_len = 1; - count = 1; - } else { - ring_buffer_get_iov(&connection->out, iov, &count); - } + build_cmsg(&connection->fds_out, cmsg, &clen); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = count; - msg.msg_control = (clen > 0) ? cmsg : NULL; + msg.msg_control = cmsg; msg.msg_controllen = clen; + msg.msg_flags = 0; do { len = sendmsg(connection->fd, &msg, @@ -508,12 +309,6 @@ wl_connection_flush(struct wl_connection *connection) return connection->out.head - tail; } -uint32_t -wl_connection_pending_input(struct wl_connection *connection) -{ - return ring_buffer_size(&connection->in); -} - int wl_connection_read(struct wl_connection *connection) { @@ -522,55 +317,49 @@ wl_connection_read(struct wl_connection *connection) char cmsg[CLEN]; int len, count, ret; - while (1) { - int data_size = ring_buffer_size(&connection->in); - - /* Stop once we've read the max buffer size. */ - if (ring_buffer_is_max_size_reached(&connection->in)) - return data_size; - - if (ring_buffer_ensure_space(&connection->in, 1) < 0) - return -1; - - ring_buffer_put_iov(&connection->in, iov, &count); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = count; - msg.msg_control = cmsg; - msg.msg_controllen = sizeof cmsg; - msg.msg_flags = 0; - - do { - len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT); - } while (len < 0 && errno == EINTR); - - if (len == 0) { - /* EOF, return previously read data first */ - return data_size; - } - if (len < 0) { - if (errno == EAGAIN && data_size > 0) { - /* nothing new read, return previously read data */ - return data_size; - } - return len; - } - - ret = decode_cmsg(&connection->fds_in, &msg); - if (ret) - return -1; - - connection->in.head += len; + if (wl_buffer_size(&connection->in) >= sizeof(connection->in.data)) { + errno = EOVERFLOW; + return -1; } + + wl_buffer_put_iov(&connection->in, iov, &count); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = count; + msg.msg_control = cmsg; + msg.msg_controllen = sizeof cmsg; + msg.msg_flags = 0; + + do { + len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT); + } while (len < 0 && errno == EINTR); + + if (len <= 0) + return len; + + ret = decode_cmsg(&connection->fds_in, &msg); + if (ret) + return -1; + + connection->in.head += len; + + return connection->in.head - connection->in.tail; } int wl_connection_write(struct wl_connection *connection, const void *data, size_t count) { - if (wl_connection_queue(connection, data, count) < 0) + if (connection->out.head - connection->out.tail + + count > ARRAY_LENGTH(connection->out.data)) { + connection->want_flush = 1; + if (wl_connection_flush(connection) < 0) + return -1; + } + + if (wl_buffer_put(&connection->out, data, count) < 0) return -1; connection->want_flush = 1; @@ -582,58 +371,39 @@ int wl_connection_queue(struct wl_connection *connection, const void *data, size_t count) { - /* We want to try to flush when the buffer reaches the default maximum - * size even if the buffer has been previously expanded. - * - * Otherwise the larger buffer will cause us to flush less frequently, - * which could increase lag. - * - * We'd like to flush often and get the buffer size back down if possible. - */ - if (ring_buffer_size(&connection->out) + count > WL_BUFFER_DEFAULT_MAX_SIZE) { + if (connection->out.head - connection->out.tail + + count > ARRAY_LENGTH(connection->out.data)) { connection->want_flush = 1; - if (wl_connection_flush(connection) < 0 && errno != EAGAIN) + if (wl_connection_flush(connection) < 0) return -1; } - if (ring_buffer_ensure_space(&connection->out, count) < 0) - return -1; - - return ring_buffer_put(&connection->out, data, count); + return wl_buffer_put(&connection->out, data, count); } -int +static int wl_message_count_arrays(const struct wl_message *message) { int i, arrays; for (i = 0, arrays = 0; message->signature[i]; i++) { - if (message->signature[i] == WL_ARG_ARRAY) + if (message->signature[i] == 'a') arrays++; } return arrays; } -int -wl_connection_get_fd(struct wl_connection *connection) -{ - return connection->fd; -} - static int wl_connection_put_fd(struct wl_connection *connection, int32_t fd) { - if (ring_buffer_size(&connection->fds_out) >= MAX_FDS_OUT * sizeof fd) { + if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) { connection->want_flush = 1; - if (wl_connection_flush(connection) < 0 && errno != EAGAIN) + if (wl_connection_flush(connection) < 0) return -1; } - if (ring_buffer_ensure_space(&connection->fds_out, sizeof fd) < 0) - return -1; - - return ring_buffer_put(&connection->fds_out, &fd, sizeof fd); + return wl_buffer_put(&connection->fds_out, &fd, sizeof fd); } const char * @@ -642,14 +412,14 @@ get_next_argument(const char *signature, struct argument_details *details) details->nullable = 0; for(; *signature; ++signature) { switch(*signature) { - case WL_ARG_INT: - case WL_ARG_UINT: - case WL_ARG_FIXED: - case WL_ARG_STRING: - case WL_ARG_OBJECT: - case WL_ARG_NEW_ID: - case WL_ARG_ARRAY: - case WL_ARG_FD: + case 'i': + case 'u': + case 'f': + case 's': + case 'o': + case 'n': + case 'a': + case 'h': details->type = *signature; return signature + 1; case '?': @@ -666,14 +436,14 @@ arg_count_for_signature(const char *signature) int count = 0; for(; *signature; ++signature) { switch(*signature) { - case WL_ARG_INT: - case WL_ARG_UINT: - case WL_ARG_FIXED: - case WL_ARG_STRING: - case WL_ARG_OBJECT: - case WL_ARG_NEW_ID: - case WL_ARG_ARRAY: - case WL_ARG_FD: + case 'i': + case 'u': + case 'f': + case 's': + case 'o': + case 'n': + case 'a': + case 'h': ++count; } } @@ -706,99 +476,36 @@ wl_argument_from_va_list(const char *signature, union wl_argument *args, sig_iter = get_next_argument(sig_iter, &arg); switch(arg.type) { - case WL_ARG_INT: + case 'i': args[i].i = va_arg(ap, int32_t); break; - case WL_ARG_UINT: + case 'u': args[i].u = va_arg(ap, uint32_t); break; - case WL_ARG_FIXED: + case 'f': args[i].f = va_arg(ap, wl_fixed_t); break; - case WL_ARG_STRING: + case 's': args[i].s = va_arg(ap, const char *); break; - case WL_ARG_OBJECT: + case 'o': args[i].o = va_arg(ap, struct wl_object *); break; - case WL_ARG_NEW_ID: + case 'n': args[i].o = va_arg(ap, struct wl_object *); break; - case WL_ARG_ARRAY: + case 'a': args[i].a = va_arg(ap, struct wl_array *); break; - case WL_ARG_FD: + case 'h': args[i].h = va_arg(ap, int32_t); break; + case '\0': + return; } } } -static void -wl_closure_clear_fds(struct wl_closure *closure) -{ - const char *signature = closure->message->signature; - struct argument_details arg; - int i; - - for (i = 0; i < closure->count; i++) { - signature = get_next_argument(signature, &arg); - if (arg.type == WL_ARG_FD) - closure->args[i].h = -1; - } -} - -static struct wl_closure * -wl_closure_init(const struct wl_message *message, uint32_t size, - int *num_arrays, union wl_argument *args) -{ - struct wl_closure *closure; - int count; - - count = arg_count_for_signature(message->signature); - if (count > WL_CLOSURE_MAX_ARGS) { - wl_log("too many args (%d) for %s (signature %s)\n", count, - message->name, message->signature); - errno = EINVAL; - return NULL; - } - - int size_to_allocate; - - if (size) { - *num_arrays = wl_message_count_arrays(message); - size_to_allocate = sizeof *closure + size + - *num_arrays * sizeof(struct wl_array); - } else { - size_to_allocate = sizeof *closure; - } - closure = zalloc(size_to_allocate); - - if (!closure) { - wl_log("could not allocate closure of size (%d) for " - "%s (signature %s)\n", size_to_allocate, message->name, - message->signature); - errno = ENOMEM; - return NULL; - } - - if (args) - memcpy(closure->args, args, count * sizeof *args); - - closure->message = message; - closure->count = count; - - /* Set these all to -1 so we can close any that have been - * set to a real value during wl_closure_destroy(). - * We may have copied a bunch of fds into the closure with - * memcpy previously, but those are undup()d client fds - * that we would have replaced anyway. - */ - wl_closure_clear_fds(closure); - - return closure; -} - struct wl_closure * wl_closure_marshal(struct wl_object *sender, uint32_t opcode, union wl_argument *args, @@ -810,59 +517,70 @@ wl_closure_marshal(struct wl_object *sender, uint32_t opcode, const char *signature; struct argument_details arg; - closure = wl_closure_init(message, 0, NULL, args); - if (closure == NULL) + count = arg_count_for_signature(message->signature); + if (count > WL_CLOSURE_MAX_ARGS) { + wl_log("too many args (%d)\n", count); + errno = EINVAL; return NULL; + } - count = closure->count; + closure = malloc(sizeof *closure); + if (closure == NULL) { + errno = ENOMEM; + return NULL; + } + + memcpy(closure->args, args, count * sizeof *args); signature = message->signature; for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); switch (arg.type) { - case WL_ARG_FIXED: - case WL_ARG_UINT: - case WL_ARG_INT: + case 'f': + case 'u': + case 'i': break; - case WL_ARG_STRING: + case 's': if (!arg.nullable && args[i].s == NULL) goto err_null; break; - case WL_ARG_OBJECT: + case 'o': if (!arg.nullable && args[i].o == NULL) goto err_null; break; - case WL_ARG_NEW_ID: + case 'n': object = args[i].o; - if (object == NULL) + if (!arg.nullable && object == NULL) goto err_null; closure->args[i].n = object ? object->id : 0; break; - case WL_ARG_ARRAY: - if (args[i].a == NULL) + case 'a': + if (!arg.nullable && args[i].a == NULL) goto err_null; break; - case WL_ARG_FD: + case 'h': fd = args[i].h; dup_fd = wl_os_dupfd_cloexec(fd, 0); if (dup_fd < 0) { - wl_closure_destroy(closure); - wl_log("error marshalling arguments for %s: dup failed: %s\n", - message->name, strerror(errno)); - return NULL; + wl_log("dup failed: %m"); + abort(); } closure->args[i].h = dup_fd; break; default: - wl_abort("unhandled format code: '%c'\n", arg.type); + wl_log("unhandled format code: '%c'\n", + arg.type); + assert(0); break; } } closure->sender_id = sender->id; closure->opcode = opcode; + closure->message = message; + closure->count = count; return closure; @@ -893,30 +611,30 @@ wl_connection_demarshal(struct wl_connection *connection, struct wl_map *objects, const struct wl_message *message) { - uint32_t *p, *next, *end, length, length_in_u32, id; + uint32_t *p, *next, *end, length, id; int fd; char *s; - int i, count, num_arrays; + unsigned int i, count, num_arrays; const char *signature; struct argument_details arg; struct wl_closure *closure; - struct wl_array *array_extra; + struct wl_array *array, *array_extra; - /* Space for sender_id and opcode */ - if (size < 2 * sizeof *p) { - wl_log("message too short, invalid header\n"); - wl_connection_consume(connection, size); + count = arg_count_for_signature(message->signature); + if (count > WL_CLOSURE_MAX_ARGS) { + wl_log("too many args (%d)\n", count); errno = EINVAL; - return NULL; - } - - closure = wl_closure_init(message, size, &num_arrays, NULL); - if (closure == NULL) { wl_connection_consume(connection, size); return NULL; } - count = closure->count; + num_arrays = wl_message_count_arrays(message); + closure = malloc(sizeof *closure + size + num_arrays * sizeof *array); + if (closure == NULL) { + errno = ENOMEM; + wl_connection_consume(connection, size); + return NULL; + } array_extra = closure->extra; p = (uint32_t *)(closure->extra + num_arrays); @@ -930,42 +648,34 @@ wl_connection_demarshal(struct wl_connection *connection, for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); - if (arg.type != WL_ARG_FD && p >= end) { + if (arg.type != 'h' && p + 1 > end) { wl_log("message too short, " "object (%d), message %s(%s)\n", - closure->sender_id, message->name, - message->signature); + *p, message->name, message->signature); errno = EINVAL; goto err; } switch (arg.type) { - case WL_ARG_UINT: + case 'u': closure->args[i].u = *p++; break; - case WL_ARG_INT: + case 'i': closure->args[i].i = *p++; break; - case WL_ARG_FIXED: + case 'f': closure->args[i].f = *p++; break; - case WL_ARG_STRING: + case 's': length = *p++; - if (length == 0 && !arg.nullable) { - wl_log("NULL string received on non-nullable " - "type, message %s(%s)\n", message->name, - message->signature); - errno = EINVAL; - goto err; - } if (length == 0) { closure->args[i].s = NULL; break; } - length_in_u32 = div_roundup(length, sizeof *p); - if ((uint32_t) (end - p) < length_in_u32) { + next = p + DIV_ROUNDUP(length, sizeof *p); + if (next > end) { wl_log("message too short, " "object (%d), message %s(%s)\n", closure->sender_id, message->name, @@ -973,11 +683,10 @@ wl_connection_demarshal(struct wl_connection *connection, errno = EINVAL; goto err; } - next = p + length_in_u32; s = (char *) p; - if (s[length - 1] != '\0') { + if (length > 0 && s[length - 1] != '\0') { wl_log("string not nul-terminated, " "message %s(%s)\n", message->name, message->signature); @@ -985,18 +694,10 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } - if (strlen(s) != length - 1) { - wl_log("string has embedded nul at offset %zu, " - "message %s(%s)\n", strlen(s), - message->name, message->signature); - errno = EINVAL; - goto err; - } - closure->args[i].s = s; p = next; break; - case WL_ARG_OBJECT: + case 'o': id = *p++; closure->args[i].n = id; @@ -1008,11 +709,11 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } break; - case WL_ARG_NEW_ID: + case 'n': id = *p++; closure->args[i].n = id; - if (id == 0) { + if (id == 0 && !arg.nullable) { wl_log("NULL new ID received on non-nullable " "type, message %s(%s)\n", message->name, message->signature); @@ -1021,21 +722,19 @@ wl_connection_demarshal(struct wl_connection *connection, } if (wl_map_reserve_new(objects, id) < 0) { - if (errno == EINVAL) { - wl_log("not a valid new object id (%u), " - "message %s(%s)\n", id, - message->name, - message->signature); - } + wl_log("not a valid new object id (%u), " + "message %s(%s)\n", + id, message->name, message->signature); + errno = EINVAL; goto err; } break; - case WL_ARG_ARRAY: + case 'a': length = *p++; - length_in_u32 = div_roundup(length, sizeof *p); - if ((uint32_t) (end - p) < length_in_u32) { + next = p + DIV_ROUNDUP(length, sizeof *p); + if (next > end) { wl_log("message too short, " "object (%d), message %s(%s)\n", closure->sender_id, message->name, @@ -1043,7 +742,6 @@ wl_connection_demarshal(struct wl_connection *connection, errno = EINVAL; goto err; } - next = p + length_in_u32; array_extra->size = length; array_extra->alloc = 0; @@ -1052,7 +750,7 @@ wl_connection_demarshal(struct wl_connection *connection, closure->args[i].a = array_extra++; p = next; break; - case WL_ARG_FD: + case 'h': if (connection->fds_in.tail == connection->fds_in.head) { wl_log("file descriptor expected, " "object (%d), message %s(%s)\n", @@ -1062,16 +760,20 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } - ring_buffer_copy(&connection->fds_in, &fd, sizeof fd); + wl_buffer_copy(&connection->fds_in, &fd, sizeof fd); connection->fds_in.tail += sizeof fd; closure->args[i].h = fd; break; default: - wl_abort("unknown type\n"); + wl_log("unknown type\n"); + assert(0); break; } } + closure->count = count; + closure->message = message; + wl_connection_consume(connection, size); return closure; @@ -1083,21 +785,17 @@ wl_connection_demarshal(struct wl_connection *connection, return NULL; } -bool -wl_object_is_zombie(struct wl_map *map, uint32_t id) +int +wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b) { - uint32_t flags; + /* In most cases the pointer equality test is sufficient. + * However, in some cases, depending on how things are split + * across shared objects, we can end up with multiple + * instances of the interface metadata constants. So if the + * pointers match, the interfaces are equal, if they don't + * match we have to compare the interface names. */ - /* Zombie objects only exist on the client side. */ - if (map->side == WL_MAP_SERVER_SIDE) - return false; - - /* Zombie objects can only have been created by the client. */ - if (id >= WL_SERVER_ID_START) - return false; - - flags = wl_map_lookup_flags(map, id); - return !!(flags & WL_MAP_ENTRY_ZOMBIE); + return a == b || strcmp(a->name, b->name) == 0; } int @@ -1115,35 +813,36 @@ wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects) count = arg_count_for_signature(signature); for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); - if (arg.type != WL_ARG_OBJECT) - continue; + switch (arg.type) { + case 'o': + id = closure->args[i].n; + closure->args[i].o = NULL; - id = closure->args[i].n; - closure->args[i].o = NULL; + object = wl_map_lookup(objects, id); + if (object == WL_ZOMBIE_OBJECT) { + /* references object we've already + * destroyed client side */ + object = NULL; + } else if (object == NULL && id != 0) { + wl_log("unknown object (%u), message %s(%s)\n", + id, message->name, message->signature); + object = NULL; + errno = EINVAL; + return -1; + } - object = wl_map_lookup(objects, id); - if (wl_object_is_zombie(objects, id)) { - /* references object we've already - * destroyed client side */ - object = NULL; - } else if (object == NULL && id != 0) { - wl_log("unknown object (%u), message %s(%s)\n", - id, message->name, message->signature); - errno = EINVAL; - return -1; + if (object != NULL && message->types[i] != NULL && + !wl_interface_equal((object)->interface, + message->types[i])) { + wl_log("invalid object (%u), type (%s), " + "message %s(%s)\n", + id, (object)->interface->name, + message->name, message->signature); + errno = EINVAL; + return -1; + } + closure->args[i].o = object; } - - if (object != NULL && message->types[i] != NULL && - !wl_interface_equal((object)->interface, - message->types[i])) { - wl_log("invalid object (%u), type (%s), " - "message %s(%s)\n", - id, (object)->interface->name, - message->name, message->signature); - errno = EINVAL; - return -1; - } - closure->args[i].o = object; } return 0; @@ -1163,27 +862,27 @@ convert_arguments_to_ffi(const char *signature, uint32_t flags, sig_iter = get_next_argument(sig_iter, &arg); switch(arg.type) { - case WL_ARG_INT: + case 'i': ffi_types[i] = &ffi_type_sint32; ffi_args[i] = &args[i].i; break; - case WL_ARG_UINT: + case 'u': ffi_types[i] = &ffi_type_uint32; ffi_args[i] = &args[i].u; break; - case WL_ARG_FIXED: + case 'f': ffi_types[i] = &ffi_type_sint32; ffi_args[i] = &args[i].f; break; - case WL_ARG_STRING: + case 's': ffi_types[i] = &ffi_type_pointer; ffi_args[i] = &args[i].s; break; - case WL_ARG_OBJECT: + case 'o': ffi_types[i] = &ffi_type_pointer; ffi_args[i] = &args[i].o; break; - case WL_ARG_NEW_ID: + case 'n': if (flags & WL_CLOSURE_INVOKE_CLIENT) { ffi_types[i] = &ffi_type_pointer; ffi_args[i] = &args[i].o; @@ -1192,16 +891,17 @@ convert_arguments_to_ffi(const char *signature, uint32_t flags, ffi_args[i] = &args[i].n; } break; - case WL_ARG_ARRAY: + case 'a': ffi_types[i] = &ffi_type_pointer; ffi_args[i] = &args[i].a; break; - case WL_ARG_FD: + case 'h': ffi_types[i] = &ffi_type_sint32; ffi_args[i] = &args[i].h; break; default: - wl_abort("unknown type\n"); + wl_log("unknown type\n"); + assert(0); break; } } @@ -1231,18 +931,7 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags, count + 2, &ffi_type_void, ffi_types); implementation = target->implementation; - if (!implementation) { - wl_abort("Implementation of resource %d of %s is NULL\n", - target->id, target->interface->name); - } - - if (!implementation[opcode]) { - wl_abort("listener function for opcode %u of %s is NULL\n", - opcode, target->interface->name); - } ffi_call(&cif, implementation[opcode], NULL, ffi_args); - - wl_closure_clear_fds(closure); } void @@ -1251,8 +940,6 @@ wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher, { dispatcher(target->implementation, target, opcode, closure->message, closure->args); - - wl_closure_clear_fds(closure); } static int @@ -1268,16 +955,15 @@ copy_fds_to_connection(struct wl_closure *closure, count = arg_count_for_signature(signature); for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); - if (arg.type != WL_ARG_FD) + if (arg.type != 'h') continue; fd = closure->args[i].h; if (wl_connection_put_fd(connection, fd)) { wl_log("request could not be marshaled: " - "can't send file descriptor\n"); + "can't send file descriptor"); return -1; } - closure->args[i].h = -1; } return 0; @@ -1299,32 +985,32 @@ buffer_size_for_closure(struct wl_closure *closure) signature = get_next_argument(signature, &arg); switch (arg.type) { - case WL_ARG_FD: + case 'h': break; - case WL_ARG_UINT: - case WL_ARG_INT: - case WL_ARG_FIXED: - case WL_ARG_OBJECT: - case WL_ARG_NEW_ID: + case 'u': + case 'i': + case 'f': + case 'o': + case 'n': buffer_size++; break; - case WL_ARG_STRING: + case 's': if (closure->args[i].s == NULL) { buffer_size++; break; } size = strlen(closure->args[i].s) + 1; - buffer_size += 1 + div_roundup(size, sizeof(uint32_t)); + buffer_size += 1 + DIV_ROUNDUP(size, sizeof(uint32_t)); break; - case WL_ARG_ARRAY: + case 'a': if (closure->args[i].a == NULL) { buffer_size++; break; } size = closure->args[i].a->size; - buffer_size += (1 + div_roundup(size, sizeof(uint32_t))); + buffer_size += (1 + DIV_ROUNDUP(size, sizeof(uint32_t))); break; default: break; @@ -1355,29 +1041,29 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer, for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); - if (arg.type == WL_ARG_FD) + if (arg.type == 'h') continue; - if (p >= end) + if (p + 1 > end) goto overflow; switch (arg.type) { - case WL_ARG_UINT: + case 'u': *p++ = closure->args[i].u; break; - case WL_ARG_INT: + case 'i': *p++ = closure->args[i].i; break; - case WL_ARG_FIXED: + case 'f': *p++ = closure->args[i].f; break; - case WL_ARG_OBJECT: + case 'o': *p++ = closure->args[i].o ? closure->args[i].o->id : 0; break; - case WL_ARG_NEW_ID: + case 'n': *p++ = closure->args[i].n; break; - case WL_ARG_STRING: + case 's': if (closure->args[i].s == NULL) { *p++ = 0; break; @@ -1386,13 +1072,13 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer, size = strlen(closure->args[i].s) + 1; *p++ = size; - if (div_roundup(size, sizeof *p) > (uint32_t)(end - p)) + if (p + DIV_ROUNDUP(size, sizeof *p) > end) goto overflow; memcpy(p, closure->args[i].s, size); - p += div_roundup(size, sizeof *p); + p += DIV_ROUNDUP(size, sizeof *p); break; - case WL_ARG_ARRAY: + case 'a': if (closure->args[i].a == NULL) { *p++ = 0; break; @@ -1401,14 +1087,13 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer, size = closure->args[i].a->size; *p++ = size; - if (div_roundup(size, sizeof *p) > (uint32_t)(end - p)) + if (p + DIV_ROUNDUP(size, sizeof *p) > end) goto overflow; - if (size != 0) - memcpy(p, closure->args[i].a->data, size); - p += div_roundup(size, sizeof *p); + memcpy(p, closure->args[i].a->data, size); + p += DIV_ROUNDUP(size, sizeof *p); break; - case WL_ARG_FD: + default: break; } } @@ -1421,8 +1106,6 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer, return size; overflow: - wl_log("serialize_closure overflow for %s (signature %s)\n", - message->name, message->signature); errno = ERANGE; return -1; } @@ -1439,14 +1122,9 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) return -1; buffer_size = buffer_size_for_closure(closure); - buffer = zalloc(buffer_size * sizeof buffer[0]); - if (buffer == NULL) { - wl_log("wl_closure_send error: buffer allocation failure of " - "size %d\n for %s (signature %s)", - buffer_size * sizeof buffer[0], closure->message->name, - closure->message->signature); + buffer = malloc(buffer_size * sizeof buffer[0]); + if (buffer == NULL) return -1; - } size = serialize_closure(closure, buffer, buffer_size); if (size < 0) { @@ -1473,13 +1151,8 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) buffer_size = buffer_size_for_closure(closure); buffer = malloc(buffer_size * sizeof buffer[0]); - if (buffer == NULL) { - wl_log("wl_closure_queue error: buffer allocation failure of " - "size %d\n for %s (signature %s)", - buffer_size * sizeof buffer[0], closure->message->name, - closure->message->signature); + if (buffer == NULL) return -1; - } size = serialize_closure(closure, buffer, buffer_size); if (size < 0) { @@ -1493,201 +1166,75 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) return result; } -bool -wl_check_env_token(const char *env, const char *token) -{ - const char *ptr = env; - size_t token_len; - - if (env == NULL) - return false; - - token_len = strlen(token); - - // Scan the string for comma-separated tokens and look for a match. - while (true) { - const char *end; - size_t len; - - // Skip over any leading separators. - while (*ptr == ',') - ptr++; - - if (*ptr == '\x00') - return false; - - end = strchr(ptr + 1, ','); - - // If there isn't another separarator, then the rest of the string - // is one token. - if (end == NULL) - return (strcmp(ptr, token) == 0); - - len = end - ptr; - if (len == token_len && memcmp(ptr, token, len) == 0) { - return true; - } - - // Skip to the next token. - ptr += len; - } - - return false; -} - void -wl_closure_print(struct wl_closure *closure, struct wl_object *target, - int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg), - const char *queue_name, int color) +wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) { -#if defined(HAVE_GETTID) - static int include_tid = -1; -#endif // defined(HAVE_GETTID) int i; struct argument_details arg; const char *signature = closure->message->signature; struct timespec tp; unsigned int time; - uint32_t nval; - FILE *f; - char *buffer; - size_t buffer_length; - - f = open_memstream(&buffer, &buffer_length); - if (f == NULL) - return; clock_gettime(CLOCK_REALTIME, &tp); time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); - fprintf(f, "%s[%7u.%03u] ", - color ? WL_DEBUG_COLOR_GREEN : "", - time / 1000, time % 1000); -#if defined(HAVE_GETTID) - if (include_tid < 0) { - include_tid = wl_check_env_token(getenv("WAYLAND_DEBUG"), "thread_id"); - } - - if (include_tid) { - fprintf(f, "%sTID#%d ", - color ? WL_DEBUG_COLOR_CYAN : "", - (int) gettid()); - } -#endif - - if (queue_name) { - fprintf(f, "%s{%s} ", - color ? WL_DEBUG_COLOR_YELLOW : "", - queue_name); - } - - fprintf(f, "%s%s%s%s%s%s%s#%u%s.%s%s(", - color ? WL_DEBUG_COLOR_RED : "", - discarded ? "discarded " : "", - color ? WL_DEBUG_COLOR_RESET : "", + fprintf(stderr, "[%10.3f] %s%s@%u.%s(", + time / 1000.0, send ? " -> " : "", - color ? WL_DEBUG_COLOR_BLUE : "", - target->interface->name, - color ? WL_DEBUG_COLOR_MAGENTA : "", - target->id, - color ? WL_DEBUG_COLOR_CYAN : "", - closure->message->name, - color ? WL_DEBUG_COLOR_RESET : ""); + target->interface->name, target->id, + closure->message->name); for (i = 0; i < closure->count; i++) { signature = get_next_argument(signature, &arg); if (i > 0) - fprintf(f, ", "); + fprintf(stderr, ", "); switch (arg.type) { - case WL_ARG_UINT: - fprintf(f, "%u", closure->args[i].u); + case 'u': + fprintf(stderr, "%u", closure->args[i].u); break; - case WL_ARG_INT: - fprintf(f, "%d", closure->args[i].i); + case 'i': + fprintf(stderr, "%d", closure->args[i].i); break; - case WL_ARG_FIXED: - /* The magic number 390625 is 1e8 / 256 */ - if (closure->args[i].f >= 0) { - fprintf(f, "%d.%08d", - closure->args[i].f / 256, - 390625 * (closure->args[i].f % 256)); - } else { - - fprintf(f, "-%d.%08d", - closure->args[i].f / -256, - -390625 * (closure->args[i].f % 256)); - } + case 'f': + fprintf(stderr, "%f", + wl_fixed_to_double(closure->args[i].f)); break; - case WL_ARG_STRING: - if (closure->args[i].s) - fprintf(f, "\"%s\"", closure->args[i].s); - else - fprintf(f, "nil"); + case 's': + fprintf(stderr, "\"%s\"", closure->args[i].s); break; - case WL_ARG_OBJECT: + case 'o': if (closure->args[i].o) - fprintf(f, "%s#%u", + fprintf(stderr, "%s@%u", closure->args[i].o->interface->name, closure->args[i].o->id); else - fprintf(f, "nil"); + fprintf(stderr, "nil"); break; - case WL_ARG_NEW_ID: - if (n_parse) - nval = n_parse(&closure->args[i]); - else - nval = closure->args[i].n; - - fprintf(f, "new id %s#", + case 'n': + fprintf(stderr, "new id %s@", (closure->message->types[i]) ? closure->message->types[i]->name : "[unknown]"); - if (nval != 0) - fprintf(f, "%u", nval); + if (closure->args[i].n != 0) + fprintf(stderr, "%u", closure->args[i].n); else - fprintf(f, "nil"); + fprintf(stderr, "nil"); break; - case WL_ARG_ARRAY: - fprintf(f, "array[%zu]", closure->args[i].a->size); + case 'a': + fprintf(stderr, "array"); break; - case WL_ARG_FD: - fprintf(f, "fd %d", closure->args[i].h); + case 'h': + fprintf(stderr, "fd %d", closure->args[i].h); break; } } - fprintf(f, ")%s\n", color ? WL_DEBUG_COLOR_RESET : ""); - - if (fclose(f) == 0) { - fprintf(stderr, "%s", buffer); - free(buffer); - } -} - -static int -wl_closure_close_fds(struct wl_closure *closure) -{ - int i; - struct argument_details arg; - const char *signature = closure->message->signature; - - for (i = 0; i < closure->count; i++) { - signature = get_next_argument(signature, &arg); - if (arg.type == WL_ARG_FD && closure->args[i].h != -1) - close(closure->args[i].h); - } - - return 0; + fprintf(stderr, ")\n"); } void wl_closure_destroy(struct wl_closure *closure) { - /* wl_closure_destroy has free() semantics */ - if (!closure) - return; - - wl_closure_close_fds(closure); free(closure); } diff --git a/src/embed.py b/src/embed.py deleted file mode 100644 index abebb157..00000000 --- a/src/embed.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 - -""" -Simple C data embedder - -License: MIT - -Copyright (c) 2020 Simon Ser - -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 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. -""" - -import sys - -if len(sys.argv) != 3: - print('usage: ' + sys.argv[0] + ' ', file=sys.stderr) - sys.exit(1) - -filename = sys.argv[1] -ident = sys.argv[2] - -with open(filename, 'rb') as f: - buf = f.read() - -print('static const char ' + ident + '[] = {\n\t', end='') -for i in range(len(buf)): - ch = buf[i:i+1] - print('0x' + ch.hex() + ', ', end='') -print('\n};') diff --git a/src/event-loop.c b/src/event-loop.c index 89294fd9..a149db92 100644 --- a/src/event-loop.c +++ b/src/event-loop.c @@ -1,26 +1,23 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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: + * 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 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. + * 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 @@ -28,8 +25,6 @@ #include #include #include -#include -#include #include #include #include @@ -38,20 +33,24 @@ #include #include #include -#include "timespec-util.h" -#include "wayland-util.h" +#include #include "wayland-private.h" -#include "wayland-server-core.h" -#include "wayland-server-private.h" +#include "wayland-server.h" #include "wayland-os.h" -/** \cond INTERNAL */ +struct wl_event_loop { + int epoll_fd; + struct wl_list check_list; + struct wl_list idle_list; + struct wl_list destroy_list; -#define TIMER_REMOVED -2 + struct wl_signal destroy_signal; +}; -struct wl_event_loop; -struct wl_event_source_interface; -struct wl_event_source_timer; +struct wl_event_source_interface { + int (*dispatch)(struct wl_event_source *source, + struct epoll_event *ep); +}; struct wl_event_source { struct wl_event_source_interface *interface; @@ -61,38 +60,12 @@ struct wl_event_source { int fd; }; -struct wl_timer_heap { - struct wl_event_source base; - /* pointers to the user-visible event sources */ - struct wl_event_source_timer **data; - int space, active, count; -}; - -struct wl_event_loop { - int epoll_fd; - struct wl_list check_list; - struct wl_list idle_list; - struct wl_list destroy_list; - - struct wl_priv_signal destroy_signal; - - struct wl_timer_heap timers; -}; - -struct wl_event_source_interface { - int (*dispatch)(struct wl_event_source *source, - struct epoll_event *ep); -}; - - struct wl_event_source_fd { struct wl_event_source base; wl_event_loop_fd_func_t func; int fd; }; -/** \endcond */ - static int wl_event_source_fd_dispatch(struct wl_event_source *source, struct epoll_event *ep) @@ -148,30 +121,6 @@ add_source(struct wl_event_loop *loop, return source; } -/** Create a file descriptor event source - * - * \param loop The event loop that will process the new source. - * \param fd The file descriptor to watch. - * \param mask A bitwise-or of which events to watch for: \c WL_EVENT_READABLE, - * \c WL_EVENT_WRITABLE. - * \param func The file descriptor dispatch function. - * \param data User data. - * \return A new file descriptor event source. - * - * The given file descriptor is initially watched for the events given in - * \c mask. This can be changed as needed with wl_event_source_fd_update(). - * - * If it is possible that program execution causes the file descriptor to be - * read while leaving the data in a buffer without actually processing it, - * it may be necessary to register the file descriptor source to be re-checked, - * see wl_event_source_check(). This will ensure that the dispatch function - * gets called even if the file descriptor is not readable or writable - * anymore. This is especially useful with IPC libraries that automatically - * buffer incoming data, possibly as a side-effect of other operations. - * - * \sa wl_event_loop_fd_func_t - * \memberof wl_event_source - */ WL_EXPORT struct wl_event_source * wl_event_loop_add_fd(struct wl_event_loop *loop, int fd, uint32_t mask, @@ -180,38 +129,18 @@ wl_event_loop_add_fd(struct wl_event_loop *loop, { struct wl_event_source_fd *source; - source = zalloc(sizeof *source); + source = malloc(sizeof *source); if (source == NULL) return NULL; source->base.interface = &fd_source_interface; - source->base.fd = wl_os_dupfd_cloexec(fd, 0); + source->base.fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); source->func = func; source->fd = fd; return add_source(loop, &source->base, mask, data); } -/** Update a file descriptor source's event mask - * - * \param source The file descriptor event source to update. - * \param mask The new mask, a bitwise-or of: \c WL_EVENT_READABLE, - * \c WL_EVENT_WRITABLE. - * \return 0 on success, -1 on failure. - * - * This changes which events, readable and/or writable, cause the dispatch - * callback to be called on. - * - * File descriptors are usually writable to begin with, so they do not need to - * be polled for writable until a write actually fails. When a write fails, - * the event mask can be changed to poll for readable and writable, delivering - * a dispatch callback when it is possible to write more. Once all data has - * been written, the mask can be changed to poll only for readable to avoid - * busy-looping on dispatch. - * - * \sa wl_event_loop_add_fd() - * \memberof wl_event_source - */ WL_EXPORT int wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask) { @@ -228,339 +157,32 @@ wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask) return epoll_ctl(loop->epoll_fd, EPOLL_CTL_MOD, source->fd, &ep); } -/** \cond INTERNAL */ - struct wl_event_source_timer { struct wl_event_source base; wl_event_loop_timer_func_t func; - struct wl_event_source_timer *next_due; - struct timespec deadline; - int heap_idx; }; -static int -noop_dispatch(struct wl_event_source *source, - struct epoll_event *ep) { - return 0; -} - -struct wl_event_source_interface timer_heap_source_interface = { - noop_dispatch, -}; - -static bool -time_lt(struct timespec ta, struct timespec tb) -{ - if (ta.tv_sec != tb.tv_sec) { - return ta.tv_sec < tb.tv_sec; - } - return ta.tv_nsec < tb.tv_nsec; -} - -static int -set_timer(int timerfd, struct timespec deadline) { - struct itimerspec its; - - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 0; - its.it_value = deadline; - return timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its, NULL); -} - -static int -clear_timer(int timerfd) -{ - struct itimerspec its; - - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 0; - its.it_value.tv_sec = 0; - its.it_value.tv_nsec = 0; - return timerfd_settime(timerfd, 0, &its, NULL); -} - -static void -wl_timer_heap_init(struct wl_timer_heap *timers, struct wl_event_loop *loop) -{ - timers->base.fd = -1; - timers->base.data = NULL; - wl_list_init(&timers->base.link); - timers->base.interface = &timer_heap_source_interface; - timers->base.loop = loop; - - loop->timers.data = NULL; - loop->timers.active = 0; - loop->timers.space = 0; - loop->timers.count = 0; -} - -static void -wl_timer_heap_release(struct wl_timer_heap *timers) -{ - if (timers->base.fd != -1) { - close(timers->base.fd); - } - free(timers->data); -} - -static int -wl_timer_heap_ensure_timerfd(struct wl_timer_heap *timers) -{ - struct epoll_event ep; - int timer_fd; - - if (timers->base.fd != -1) - return 0; - - memset(&ep, 0, sizeof ep); - ep.events = EPOLLIN; - ep.data.ptr = timers; - - timer_fd = timerfd_create(CLOCK_MONOTONIC, - TFD_CLOEXEC | TFD_NONBLOCK); - if (timer_fd < 0) - return -1; - - if (epoll_ctl(timers->base.loop->epoll_fd, - EPOLL_CTL_ADD, timer_fd, &ep) < 0) { - close(timer_fd); - return -1; - } - - timers->base.fd = timer_fd; - return 0; -} - -static int -wl_timer_heap_reserve(struct wl_timer_heap *timers) -{ - struct wl_event_source_timer **n; - int new_space; - - if (timers->count + 1 > timers->space) { - new_space = timers->space >= 8 ? timers->space * 2 : 8; - n = realloc(timers->data, (size_t)new_space * sizeof(*n)); - if (!n) { - wl_log("Allocation failure when expanding timer list\n"); - return -1; - } - timers->data = n; - timers->space = new_space; - } - - timers->count++; - return 0; -} - -static void -wl_timer_heap_unreserve(struct wl_timer_heap *timers) -{ - struct wl_event_source_timer **n; - - timers->count--; - - if (timers->space >= 16 && timers->space >= 4 * timers->count) { - n = realloc(timers->data, (size_t)timers->space / 2 * sizeof(*n)); - if (!n) { - wl_log("Reallocation failure when shrinking timer list\n"); - return; - } - timers->data = n; - timers->space = timers->space / 2; - } -} - -static int -heap_set(struct wl_event_source_timer **data, - struct wl_event_source_timer *a, - int idx) -{ - int tmp; - - tmp = a->heap_idx; - a->heap_idx = idx; - data[a->heap_idx] = a; - - return tmp; -} - -static void -heap_sift_down(struct wl_event_source_timer **data, - int num_active, - struct wl_event_source_timer *source) -{ - struct wl_event_source_timer *child, *other_child; - int cursor_idx; - struct timespec key; - - cursor_idx = source->heap_idx; - key = source->deadline; - while (1) { - int lchild_idx = cursor_idx * 2 + 1; - - if (lchild_idx >= num_active) { - break; - } - - child = data[lchild_idx]; - if (lchild_idx + 1 < num_active) { - other_child = data[lchild_idx + 1]; - if (time_lt(other_child->deadline, child->deadline)) - child = other_child; - } - - if (time_lt(child->deadline, key)) - cursor_idx = heap_set(data, child, cursor_idx); - else - break; - } - - heap_set(data, source, cursor_idx); -} - -static void -heap_sift_up(struct wl_event_source_timer **data, - struct wl_event_source_timer *source) -{ - int cursor_idx; - struct timespec key; - - cursor_idx = source->heap_idx; - key = source->deadline; - while (cursor_idx > 0) { - struct wl_event_source_timer *parent = - data[(cursor_idx - 1) / 2]; - - if (time_lt(key, parent->deadline)) - cursor_idx = heap_set(data, parent, cursor_idx); - else - break; - } - heap_set(data, source, cursor_idx); -} - -/* requires timer be armed */ -static void -wl_timer_heap_disarm(struct wl_timer_heap *timers, - struct wl_event_source_timer *source) -{ - struct wl_event_source_timer *last_end_evt; - int old_source_idx; - - if (!(source->heap_idx >= 0)) - wl_abort("Timer has already been disarmed\n"); - - old_source_idx = source->heap_idx; - source->heap_idx = -1; - source->deadline.tv_sec = 0; - source->deadline.tv_nsec = 0; - - last_end_evt = timers->data[timers->active - 1]; - timers->data[timers->active - 1] = NULL; - timers->active--; - - if (old_source_idx == timers->active) - return; - - timers->data[old_source_idx] = last_end_evt; - last_end_evt->heap_idx = old_source_idx; - - /* Move the displaced (active) element to its proper place. - * Only one of sift-down and sift-up will have any effect */ - heap_sift_down(timers->data, timers->active, last_end_evt); - heap_sift_up(timers->data, last_end_evt); -} - -/* requires timer be disarmed */ -static void -wl_timer_heap_arm(struct wl_timer_heap *timers, - struct wl_event_source_timer *source, - struct timespec deadline) -{ - if (!(source->heap_idx == -1)) - wl_abort("Timer is already armed\n"); - - source->deadline = deadline; - timers->data[timers->active] = source; - source->heap_idx = timers->active; - timers->active++; - heap_sift_up(timers->data, source); -} - - -static int -wl_timer_heap_dispatch(struct wl_timer_heap *timers) -{ - struct timespec now; - struct wl_event_source_timer *root; - struct wl_event_source_timer *list_cursor = NULL, *list_tail = NULL; - - clock_gettime(CLOCK_MONOTONIC, &now); - - while (timers->active > 0) { - root = timers->data[0]; - if (time_lt(now, root->deadline)) - break; - - wl_timer_heap_disarm(timers, root); - - if (list_cursor == NULL) - list_cursor = root; - else - list_tail->next_due = root; - list_tail = root; - } - if (list_tail) - list_tail->next_due = NULL; - - if (timers->active > 0) { - if (set_timer(timers->base.fd, timers->data[0]->deadline) < 0) - return -1; - } else { - if (clear_timer(timers->base.fd) < 0) - return -1; - } - - /* Execute precisely the functions for events before `now`, in order. - * Because wl_event_loop_dispatch ignores return codes, do the same - * here as well */ - for (; list_cursor; list_cursor = list_cursor->next_due) { - if (list_cursor->base.fd != TIMER_REMOVED) - list_cursor->func(list_cursor->base.data); - } - - return 0; -} - static int wl_event_source_timer_dispatch(struct wl_event_source *source, struct epoll_event *ep) { - struct wl_event_source_timer *timer; + struct wl_event_source_timer *timer_source = + (struct wl_event_source_timer *) source; + uint64_t expires; + int len; - timer = wl_container_of(source, timer, base); - return timer->func(timer->base.data); + len = read(source->fd, &expires, sizeof expires); + if (!(len == -1 && errno == EAGAIN) && len != sizeof expires) + /* Is there anything we can do here? Will this ever happen? */ + wl_log("timerfd read error: %m\n"); + + return timer_source->func(timer_source->base.data); } struct wl_event_source_interface timer_source_interface = { wl_event_source_timer_dispatch, }; -/** \endcond */ - -/** Create a timer event source - * - * \param loop The event loop that will process the new source. - * \param func The timer dispatch function. - * \param data User data. - * \return A new timer event source. - * - * The timer is initially disarmed. It needs to be armed with a call to - * wl_event_source_timer_update() before it can trigger a dispatch call. - * - * \sa wl_event_loop_timer_func_t - * \memberof wl_event_source - */ WL_EXPORT struct wl_event_source * wl_event_loop_add_timer(struct wl_event_loop *loop, wl_event_loop_timer_func_t func, @@ -568,112 +190,42 @@ wl_event_loop_add_timer(struct wl_event_loop *loop, { struct wl_event_source_timer *source; - if (wl_timer_heap_ensure_timerfd(&loop->timers) < 0) - return NULL; - - source = zalloc(sizeof *source); + source = malloc(sizeof *source); if (source == NULL) return NULL; source->base.interface = &timer_source_interface; - source->base.fd = -1; + source->base.fd = timerfd_create(CLOCK_MONOTONIC, + TFD_CLOEXEC | TFD_NONBLOCK); source->func = func; - source->base.loop = loop; - source->base.data = data; - wl_list_init(&source->base.link); - source->next_due = NULL; - source->deadline.tv_sec = 0; - source->deadline.tv_nsec = 0; - source->heap_idx = -1; - if (wl_timer_heap_reserve(&loop->timers) < 0) { - free(source); - return NULL; - } - - return &source->base; + return add_source(loop, &source->base, WL_EVENT_READABLE, data); } -/** Arm or disarm a timer - * - * \param source The timer event source to modify. - * \param ms_delay The timeout in milliseconds. - * \return 0 on success, -1 on failure. - * - * If the timeout is zero, the timer is disarmed. - * - * If the timeout is non-zero, the timer is set to expire after the given - * timeout in milliseconds. When the timer expires, the dispatch function - * set with wl_event_loop_add_timer() is called once from - * wl_event_loop_dispatch(). If another dispatch is desired after another - * expiry, wl_event_source_timer_update() needs to be called again. - * - * \memberof wl_event_source - */ WL_EXPORT int wl_event_source_timer_update(struct wl_event_source *source, int ms_delay) { - struct wl_event_source_timer *tsource = - wl_container_of(source, tsource, base); - struct wl_timer_heap *timers = &tsource->base.loop->timers; + struct itimerspec its; - if (ms_delay > 0) { - struct timespec deadline; - - clock_gettime(CLOCK_MONOTONIC, &deadline); - - deadline.tv_nsec += (ms_delay % 1000) * 1000000L; - deadline.tv_sec += ms_delay / 1000; - if (deadline.tv_nsec >= 1000000000L) { - deadline.tv_nsec -= 1000000000L; - deadline.tv_sec += 1; - } - - if (tsource->heap_idx == -1) { - wl_timer_heap_arm(timers, tsource, deadline); - } else if (time_lt(deadline, tsource->deadline)) { - tsource->deadline = deadline; - heap_sift_up(timers->data, tsource); - } else { - tsource->deadline = deadline; - heap_sift_down(timers->data, timers->active, tsource); - } - - if (tsource->heap_idx == 0) { - /* Only update the timerfd if the new deadline is - * the earliest */ - if (set_timer(timers->base.fd, deadline) < 0) - return -1; - } - } else { - if (tsource->heap_idx == -1) - return 0; - wl_timer_heap_disarm(timers, tsource); - - if (timers->active == 0) { - /* Only update the timerfd if this was the last - * active timer */ - if (clear_timer(timers->base.fd) < 0) - return -1; - } - } + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = ms_delay / 1000; + its.it_value.tv_nsec = (ms_delay % 1000) * 1000 * 1000; + if (timerfd_settime(source->fd, 0, &its, NULL) < 0) + return -1; return 0; } -/** \cond INTERNAL */ - struct wl_event_source_signal { struct wl_event_source base; int signal_number; wl_event_loop_signal_func_t func; }; -/** \endcond */ - static int wl_event_source_signal_dispatch(struct wl_event_source *source, - struct epoll_event *ep) + struct epoll_event *ep) { struct wl_event_source_signal *signal_source = (struct wl_event_source_signal *) source; @@ -683,7 +235,7 @@ wl_event_source_signal_dispatch(struct wl_event_source *source, len = read(source->fd, &signal_info, sizeof signal_info); if (!(len == -1 && errno == EAGAIN) && len != sizeof signal_info) /* Is there anything we can do here? Will this ever happen? */ - wl_log("signalfd read error: %s\n", strerror(errno)); + wl_log("signalfd read error: %m\n"); return signal_source->func(signal_source->signal_number, signal_source->base.data); @@ -693,35 +245,16 @@ struct wl_event_source_interface signal_source_interface = { wl_event_source_signal_dispatch, }; -/** Create a POSIX signal event source - * - * \param loop The event loop that will process the new source. - * \param signal_number Number of the signal to watch for. - * \param func The signal dispatch function. - * \param data User data. - * \return A new signal event source. - * - * This function blocks the normal delivery of the given signal in the calling - * thread, and creates a "watch" for it. Signal delivery no longer happens - * asynchronously, but by wl_event_loop_dispatch() calling the dispatch - * callback function \c func. - * - * It is the caller's responsibility to ensure that all other threads have - * also blocked the signal. - * - * \sa wl_event_loop_signal_func_t - * \memberof wl_event_source - */ WL_EXPORT struct wl_event_source * wl_event_loop_add_signal(struct wl_event_loop *loop, - int signal_number, - wl_event_loop_signal_func_t func, - void *data) + int signal_number, + wl_event_loop_signal_func_t func, + void *data) { struct wl_event_source_signal *source; sigset_t mask; - source = zalloc(sizeof *source); + source = malloc(sizeof *source); if (source == NULL) return NULL; @@ -738,39 +271,15 @@ wl_event_loop_add_signal(struct wl_event_loop *loop, return add_source(loop, &source->base, WL_EVENT_READABLE, data); } -/** \cond INTERNAL */ - struct wl_event_source_idle { struct wl_event_source base; wl_event_loop_idle_func_t func; }; -/** \endcond */ - struct wl_event_source_interface idle_source_interface = { NULL, }; -/** Create an idle task - * - * \param loop The event loop that will process the new task. - * \param func The idle task dispatch function. - * \param data User data. - * \return A new idle task (an event source). - * - * Idle tasks are dispatched before wl_event_loop_dispatch() goes to sleep. - * See wl_event_loop_dispatch() for more details. - * - * Idle tasks fire once, and are automatically destroyed right after the - * callback function has been called. - * - * An idle task can be cancelled before the callback has been called by - * wl_event_source_remove(). Calling wl_event_source_remove() after or from - * within the callback results in undefined behaviour. - * - * \sa wl_event_loop_idle_func_t - * \memberof wl_event_source - */ WL_EXPORT struct wl_event_source * wl_event_loop_add_idle(struct wl_event_loop *loop, wl_event_loop_idle_func_t func, @@ -778,7 +287,7 @@ wl_event_loop_add_idle(struct wl_event_loop *loop, { struct wl_event_source_idle *source; - source = zalloc(sizeof *source); + source = malloc(sizeof *source); if (source == NULL) return NULL; @@ -794,40 +303,12 @@ wl_event_loop_add_idle(struct wl_event_loop *loop, return &source->base; } -/** Mark event source to be re-checked - * - * \param source The event source to be re-checked. - * - * This function permanently marks the event source to be re-checked after - * the normal dispatch of sources in wl_event_loop_dispatch(). Re-checking - * will keep iterating over all such event sources until the dispatch - * function for them all returns zero. - * - * Re-checking is used on sources that may become ready to dispatch as a - * side-effect of dispatching themselves or other event sources, including idle - * sources. Re-checking ensures all the incoming events have been fully drained - * before wl_event_loop_dispatch() returns. - * - * \memberof wl_event_source - */ WL_EXPORT void wl_event_source_check(struct wl_event_source *source) { wl_list_insert(source->loop->check_list.prev, &source->link); } -/** Remove an event source from its event loop - * - * \param source The event source to be removed. - * \return Zero. - * - * The event source is removed from the event loop it was created for, - * and is effectively destroyed. This invalidates \c source . - * The dispatch function of the source will no longer be called through this - * source. - * - * \memberof wl_event_source - */ WL_EXPORT int wl_event_source_remove(struct wl_event_source *source) { @@ -841,17 +322,6 @@ wl_event_source_remove(struct wl_event_source *source) source->fd = -1; } - if (source->interface == &timer_source_interface && - source->fd != TIMER_REMOVED) { - /* Disarm the timer (and the loop's timerfd, if necessary), - * before removing its space in the loop timer heap */ - wl_event_source_timer_update(source, 0); - wl_timer_heap_unreserve(&loop->timers); - /* Set the fd field to to indicate that the timer should NOT - * be dispatched in `wl_event_loop_dispatch` */ - source->fd = TIMER_REMOVED; - } - wl_list_remove(&source->link); wl_list_insert(&loop->destroy_list, &source->link); @@ -869,26 +339,12 @@ wl_event_loop_process_destroy_list(struct wl_event_loop *loop) wl_list_init(&loop->destroy_list); } -/** Create a new event loop context - * - * \return A new event loop context object. - * - * This creates a new event loop context. Initially this context is empty. - * Event sources need to be explicitly added to it. - * - * Normally the event loop is run by calling wl_event_loop_dispatch() in - * a loop until the program terminates. Alternatively, an event loop can be - * embedded in another event loop by its file descriptor, see - * wl_event_loop_get_fd(). - * - * \memberof wl_event_loop - */ WL_EXPORT struct wl_event_loop * wl_event_loop_create(void) { struct wl_event_loop *loop; - loop = zalloc(sizeof *loop); + loop = malloc(sizeof *loop); if (loop == NULL) return NULL; @@ -901,158 +357,62 @@ wl_event_loop_create(void) wl_list_init(&loop->idle_list); wl_list_init(&loop->destroy_list); - wl_priv_signal_init(&loop->destroy_signal); - - wl_timer_heap_init(&loop->timers, loop); + wl_signal_init(&loop->destroy_signal); return loop; } -/** Destroy an event loop context - * - * \param loop The event loop to be destroyed. - * - * This emits the event loop destroy signal, closes the event loop file - * descriptor, and frees \c loop. - * - * If the event loop has existing sources, those cannot be safely removed - * afterwards. Therefore one must call wl_event_source_remove() on all - * event sources before destroying the event loop context. - * - * \memberof wl_event_loop - */ WL_EXPORT void wl_event_loop_destroy(struct wl_event_loop *loop) { - wl_priv_signal_final_emit(&loop->destroy_signal, loop); + wl_signal_emit(&loop->destroy_signal, loop); wl_event_loop_process_destroy_list(loop); - wl_timer_heap_release(&loop->timers); close(loop->epoll_fd); free(loop); } -static bool +static int post_dispatch_check(struct wl_event_loop *loop) { struct epoll_event ep; struct wl_event_source *source, *next; - bool needs_recheck = false; + int n; ep.events = 0; - wl_list_for_each_safe(source, next, &loop->check_list, link) { - int dispatch_result; + n = 0; + wl_list_for_each_safe(source, next, &loop->check_list, link) + n += source->interface->dispatch(source, &ep); - dispatch_result = source->interface->dispatch(source, &ep); - if (dispatch_result < 0) { - wl_log("Source dispatch function returned negative value!\n"); - wl_log("This would previously accidentally suppress a follow-up dispatch\n"); - } - needs_recheck |= dispatch_result != 0; - } - - return needs_recheck; + return n; } -/** Dispatch the idle sources - * - * \param loop The event loop whose idle sources are dispatched. - * - * \sa wl_event_loop_add_idle() - * \memberof wl_event_loop - */ WL_EXPORT void wl_event_loop_dispatch_idle(struct wl_event_loop *loop) { struct wl_event_source_idle *source; while (!wl_list_empty(&loop->idle_list)) { - source = wl_container_of(loop->idle_list.next, - source, base.link); + source = container_of(loop->idle_list.next, + struct wl_event_source_idle, base.link); source->func(source->base.data); wl_event_source_remove(&source->base); } } -/** Wait for events and dispatch them - * - * \param loop The event loop whose sources to wait for. - * \param timeout The polling timeout in milliseconds. - * \return 0 for success, -1 for polling (or timer update) error. - * - * All the associated event sources are polled. This function blocks until - * any event source delivers an event (idle sources excluded), or the timeout - * expires. A timeout of -1 disables the timeout, causing the function to block - * indefinitely. A timeout of zero causes the poll to always return immediately. - * - * All idle sources are dispatched before blocking. An idle source is destroyed - * when it is dispatched. After blocking, all other ready sources are - * dispatched. Then, idle sources are dispatched again, in case the dispatched - * events created idle sources. Finally, all sources marked with - * wl_event_source_check() are dispatched in a loop until their dispatch - * functions all return zero. - * - * \memberof wl_event_loop - */ WL_EXPORT int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout) { struct epoll_event ep[32]; struct wl_event_source *source; - int i, count; - bool has_timers = false; - bool use_timeout = timeout > 0; - struct timespec now; - struct timespec deadline = {0}; - struct timespec result; + int i, count, n; wl_event_loop_dispatch_idle(loop); - if (use_timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_add_msec(&deadline, &now, timeout); - } - - while (true) { - count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); - if (count >= 0) - break; /* have events or timeout */ - else if (count < 0 && errno != EINTR && errno != EAGAIN) - break; /* have error */ - - if (use_timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_sub(&result, &deadline, &now); - timeout = timespec_to_msec(&result); - if (timeout <= 0) { - /* too late */ - count = 0; - break; - } - } - } - + count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); if (count < 0) return -1; - for (i = 0; i < count; i++) { - source = ep[i].data.ptr; - if (source == &loop->timers.base) { - has_timers = true; - break; - } - } - - if (has_timers) { - /* Dispatch timer sources before non-timer sources, so that - * the non-timer sources can not cancel (by calling - * `wl_event_source_timer_update`) the dispatching of the timers - * (Note that timer sources also can't cancel pending non-timer - * sources, since epoll_wait has already been called) */ - if (wl_timer_heap_dispatch(&loop->timers) < 0) - return -1; - } - for (i = 0; i < count; i++) { source = ep[i].data.ptr; if (source->fd != -1) @@ -1061,62 +421,30 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout) wl_event_loop_process_destroy_list(loop); - wl_event_loop_dispatch_idle(loop); - - while (post_dispatch_check(loop)); - + do { + n = post_dispatch_check(loop); + } while (n > 0); + return 0; } -/** Get the event loop file descriptor - * - * \param loop The event loop context. - * \return The aggregate file descriptor. - * - * This function returns the aggregate file descriptor, that represents all - * the event sources (idle sources excluded) associated with the given event - * loop context. When any event source makes an event available, it will be - * reflected in the aggregate file descriptor. - * - * When the aggregate file descriptor delivers an event, one can call - * wl_event_loop_dispatch() on the event loop context to dispatch all the - * available events. - * - * \memberof wl_event_loop - */ WL_EXPORT int wl_event_loop_get_fd(struct wl_event_loop *loop) { return loop->epoll_fd; } -/** Register a destroy listener for an event loop context - * - * \param loop The event loop context whose destruction to listen for. - * \param listener The listener with the callback to be called. - * - * \sa wl_listener - * \memberof wl_event_loop - */ WL_EXPORT void wl_event_loop_add_destroy_listener(struct wl_event_loop *loop, struct wl_listener *listener) { - wl_priv_signal_add(&loop->destroy_signal, listener); + wl_signal_add(&loop->destroy_signal, listener); } -/** Get the listener struct for the specified callback - * - * \param loop The event loop context to inspect. - * \param notify The destroy callback to find. - * \return The wl_listener registered to the event loop context with - * the given callback pointer. - * - * \memberof wl_event_loop - */ WL_EXPORT struct wl_listener * wl_event_loop_get_destroy_listener(struct wl_event_loop *loop, wl_notify_func_t notify) { - return wl_priv_signal_get(&loop->destroy_signal, notify); + return wl_signal_get(&loop->destroy_signal, notify); } + diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index b3b9ea57..00000000 --- a/src/meson.build +++ /dev/null @@ -1,281 +0,0 @@ -if not (get_option('scanner') or get_option('libraries')) - error('Either -Dscanner=true or -Dlibraries=true is required') -endif - -wayland_version_h = configuration_data() -wayland_version_h.set('WAYLAND_VERSION', meson.project_version()) -wayland_version_h.set('WAYLAND_VERSION_MAJOR', wayland_version[0].to_int()) -wayland_version_h.set('WAYLAND_VERSION_MINOR', wayland_version[1].to_int()) -wayland_version_h.set('WAYLAND_VERSION_MICRO', wayland_version[2].to_int()) -configure_file( - input: 'wayland-version.h.in', - output: 'wayland-version.h', - configuration: wayland_version_h, - install: get_option('libraries'), - install_dir: join_paths(get_option('prefix'), get_option('includedir')) -) - - -wayland_util = static_library( - 'wayland-util', - sources: 'wayland-util.c' -) - -wayland_util_dep = declare_dependency( - link_with: wayland_util, - include_directories: include_directories('.') -) - -if get_option('scanner') - # wayland-scanner - - scanner_deps = [ dependency('expat') ] - scanner_args = [ '-include', 'config.h' ] - - if get_option('dtd_validation') - scanner_deps += dependency('libxml-2.0') - scanner_args += '-DHAVE_LIBXML=1' - endif - - prog_embed = find_program('embed.py', native: true) - - embed_dtd = custom_target( - 'wayland.dtd.h', - input: '../protocol/wayland.dtd', - output: 'wayland.dtd.h', - command: [ prog_embed, '@INPUT@', 'wayland_dtd' ], - capture: true - ) - - wayland_scanner_sources = [ 'scanner.c', embed_dtd ] - wayland_scanner_includes = [ root_inc, protocol_inc ] - - wayland_scanner = executable( - 'wayland-scanner', - wayland_scanner_sources, - c_args: scanner_args, - include_directories: wayland_scanner_includes, - dependencies: [ scanner_deps, wayland_util_dep, ], - install: true - ) - - pkgconfig.generate( - name: 'Wayland Scanner', - description: 'Wayland scanner', - version: meson.project_version(), - variables: [ - 'datarootdir=' + join_paths('${prefix}', get_option('datadir')), - 'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name()), - 'wayland_scanner=${bindir}/wayland-scanner' - ], - filebase: 'wayland-scanner' - ) - - if meson.can_run_host_binaries() - meson.override_find_program('wayland-scanner', wayland_scanner) - meson.override_dependency('wayland-scanner', declare_dependency( - variables: { 'wayland_scanner': 'wayland-scanner' }, - )) - endif -endif - -if meson.is_cross_build() or not get_option('scanner') - scanner_dep = dependency('wayland-scanner', native: true, version: meson.project_version()) - wayland_scanner_for_build = find_program(scanner_dep.get_variable(pkgconfig: 'wayland_scanner')) -else - wayland_scanner_for_build = wayland_scanner -endif - -if get_option('libraries') - # wayland libraries - - mathlib_dep = cc.find_library('m', required: false) - threads_dep = dependency('threads', required: false) - - wayland_private = static_library( - 'wayland-private', - sources: [ - 'connection.c', - 'wayland-os.c' - ], - dependencies: [ epoll_dep, ffi_dep, rt_dep ] - ) - - wayland_private_dep = declare_dependency( - link_with: wayland_private, - include_directories: include_directories('.') - ) - - generated_headers = [ - { - 'scanner_args': ['server-header'], - 'output': 'wayland-server-protocol.h', - 'install': true, - }, - { - 'scanner_args': ['server-header', '-c'], - 'output': 'wayland-server-protocol-core.h', - 'install': false, - }, - { - 'scanner_args': ['client-header'], - 'output': 'wayland-client-protocol.h', - 'install': true, - }, - { - 'scanner_args': ['client-header', '-c'], - 'output': 'wayland-client-protocol-core.h', - 'install': false, - }, - ] - - foreach gen: generated_headers - scanner_args = gen['scanner_args'] - output_file = gen['output'] - install_file = gen['install'] - install_dir = join_paths(get_option('prefix'), get_option('includedir')) - target_name = output_file.underscorify() - - target = custom_target( - target_name, - command: [ - wayland_scanner_for_build, '-s', scanner_args, - '@INPUT@', '@OUTPUT@' - ], - input: wayland_protocol_xml, - output: output_file, - install: install_file, - install_dir: install_dir - ) - - set_variable(target_name, target) - endforeach - - wayland_protocol_c = custom_target( - 'protocol source', - command: [ - wayland_scanner_for_build, '-s', 'public-code', '@INPUT@', '@OUTPUT@' - ], - input: wayland_protocol_xml, - output: 'wayland-protocol.c' - ) - - if wayland_version[0] != '1' - # The versioning used for the shared libraries assumes that the major - # version of Wayland as a whole will increase to 2 if and only if there - # is an ABI break, at which point we should probably bump the SONAME of - # all libraries to .so.2. For more details see - # https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/177 - error('We probably need to bump the SONAME of libwayland-server and -client') - endif - - wayland_server = library( - 'wayland-server', - sources: [ - wayland_server_protocol_core_h, - wayland_server_protocol_h, - wayland_protocol_c, - 'wayland-server.c', - 'wayland-shm.c', - 'event-loop.c' - ], - # To avoid an unnecessary SONAME bump, wayland 1.x.y produces - # libwayland-server.so.0.x.y. - version: '.'.join(['0', wayland_version[1], wayland_version[2]]), - dependencies: [ - epoll_dep, - ffi_dep, - wayland_private_dep, - wayland_util_dep, - mathlib_dep, - threads_dep, - rt_dep - ], - include_directories: root_inc, - install: true - ) - - wayland_server_dep = declare_dependency( - link_with: wayland_server, - include_directories: [ root_inc, include_directories('.') ], - dependencies: [ epoll_dep, ffi_dep, mathlib_dep, threads_dep ], - sources: [ - wayland_server_protocol_core_h, - wayland_server_protocol_h - ] - ) - - pkgconfig.generate( - wayland_server, - name: 'Wayland Server', - description: 'Server side implementation of the Wayland protocol', - version: meson.project_version(), - filebase: 'wayland-server', - libraries: mathlib_dep, - variables: [ - 'datarootdir=' + join_paths('${prefix}', get_option('datadir')), - 'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name()) - ] - ) - - if meson.version().version_compare('>= 0.54.0') - meson.override_dependency('wayland-server', wayland_server_dep) - endif - - wayland_client = library( - 'wayland-client', - sources: [ - wayland_client_protocol_core_h, - wayland_client_protocol_h, - wayland_protocol_c, - 'wayland-client.c' - ], - # To avoid an unnecessary SONAME bump, wayland 1.x.y produces - # libwayland-client.so.0.x.y. - version: '.'.join(['0', wayland_version[1], wayland_version[2]]), - dependencies: [ - epoll_dep, - ffi_dep, - wayland_private_dep, - wayland_util_dep, - mathlib_dep, - threads_dep - ], - include_directories: root_inc, - install: true - ) - - pkgconfig.generate( - wayland_client, - name: 'Wayland Client', - description: 'Wayland client side library', - version: meson.project_version(), - filebase: 'wayland-client', - libraries: mathlib_dep, - variables: [ - 'datarootdir=' + join_paths('${prefix}', get_option('datadir')), - 'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name()) - ] - ) - - wayland_client_dep = declare_dependency( - link_with: wayland_client, - include_directories: [ root_inc, include_directories('.') ], - sources: [ - wayland_client_protocol_core_h, - wayland_client_protocol_h - ] - ) - - if meson.version().version_compare('>= 0.54.0') - meson.override_dependency('wayland-client', wayland_client_dep) - endif - - install_headers([ - 'wayland-util.h', - 'wayland-server.h', - 'wayland-server-core.h', - 'wayland-client.h', - 'wayland-client-core.h', - ]) -endif diff --git a/src/scanner.c b/src/scanner.c index cd5f7fea..72fd3e83 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -1,152 +1,51 @@ /* * Copyright © 2008-2011 Kristian Høgsberg * Copyright © 2011 Intel Corporation - * Copyright © 2015 Red Hat, Inc. * - * 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: + * 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 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. + * 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 "wayland-version.h" - -#include #include #include -#include #include #include #include -#include -#include -#include - -#if HAVE_LIBXML -#include - -/* Embedded wayland.dtd file */ -/* static const char wayland_dtd[]; wayland.dtd */ -#include "wayland.dtd.h" -#endif - -/* Expat must be included after libxml as both want to declare XMLCALL; see - * the Git commit that 'git blame' for this comment points to for more. */ #include #include "wayland-util.h" -#define PROGRAM_NAME "wayland-scanner" - enum side { CLIENT, SERVER, }; -enum visibility { - PRIVATE, - PUBLIC, -}; - static int usage(int ret) { - fprintf(stderr, "usage: %s [OPTION] [client-header|server-header|enum-header|private-code|public-code]" - " [input_file output_file]\n", PROGRAM_NAME); + fprintf(stderr, "usage: ./scanner [client-header|server-header|code]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Converts XML protocol descriptions supplied on " - "stdin or input file to client\n" - "headers, server headers, or protocol marshalling code.\n\n" - "Use \"public-code\" only if the marshalling code will be public - " - "aka DSO will export it while other components will be using it.\n" - "Using \"private-code\" is strongly recommended.\n\n"); - fprintf(stderr, "options:\n"); - fprintf(stderr, " -h, --help display this help and exit.\n" - " -v, --version print the wayland library version that\n" - " the scanner was built against.\n" - " -c, --include-core-only include the core version of the headers,\n" - " that is e.g. wayland-client-core.h instead\n" - " of wayland-client.h.\n" - " -s, --strict exit immediately with an error if DTD\n" - " verification fails.\n"); + "stdin to client headers,\n" + "server headers, or protocol marshalling code.\n"); exit(ret); } -static int -scanner_version(int ret) -{ - fprintf(stderr, "%s %s\n", PROGRAM_NAME, WAYLAND_VERSION); - exit(ret); -} - -static bool -is_dtd_valid(FILE *input, const char *filename) -{ - bool rc = true; -#if HAVE_LIBXML - xmlParserCtxtPtr ctx = NULL; - xmlDocPtr doc = NULL; - xmlDtdPtr dtd = NULL; - xmlValidCtxtPtr dtdctx; - xmlParserInputBufferPtr buffer; - int fd = fileno(input); - - dtdctx = xmlNewValidCtxt(); - ctx = xmlNewParserCtxt(); - if (!ctx || !dtdctx) - abort(); - - buffer = xmlParserInputBufferCreateMem(wayland_dtd, - sizeof(wayland_dtd), - XML_CHAR_ENCODING_UTF8); - if (!buffer) { - fprintf(stderr, "Failed to init buffer for DTD.\n"); - abort(); - } - - dtd = xmlIOParseDTD(NULL, buffer, XML_CHAR_ENCODING_UTF8); - if (!dtd) { - fprintf(stderr, "Failed to parse DTD.\n"); - abort(); - } - - doc = xmlCtxtReadFd(ctx, fd, filename, NULL, 0); - if (!doc) { - fprintf(stderr, "Failed to read XML\n"); - abort(); - } - - rc = xmlValidateDtd(dtdctx, doc, dtd); - xmlFreeDoc(doc); - xmlFreeParserCtxt(ctx); - xmlFreeDtd(dtd); - xmlFreeValidCtxt(dtdctx); - /* xmlIOParseDTD consumes buffer */ - - if (lseek(fd, 0, SEEK_SET) != 0) { - fprintf(stderr, "Failed to reset fd, output would be garbage.\n"); - abort(); - } -#endif - return rc; -} - #define XML_BUFFER_SIZE 4096 struct location { @@ -167,7 +66,6 @@ struct protocol { int null_run_length; char *copyright; struct description *description; - bool core_headers; }; struct interface { @@ -175,7 +73,7 @@ struct interface { char *name; char *uppercase_name; int version; - int since, deprecated_since; + int since; struct wl_list request_list; struct wl_list event_list; struct wl_list enumeration_list; @@ -194,7 +92,7 @@ struct message { int type_index; int all_null; int destructor; - int since, deprecated_since; + int since; struct description *description; }; @@ -216,7 +114,6 @@ struct arg { char *interface_name; struct wl_list link; char *summary; - char *enumeration_name; }; struct enumeration { @@ -225,8 +122,6 @@ struct enumeration { struct wl_list entry_list; struct wl_list link; struct description *description; - bool bitfield; - int since; }; struct entry { @@ -234,9 +129,7 @@ struct entry { char *uppercase_name; char *value; char *summary; - int since, deprecated_since; struct wl_list link; - struct description *description; }; struct parse_context { @@ -246,22 +139,16 @@ struct parse_context { struct interface *interface; struct message *message; struct enumeration *enumeration; - struct entry *entry; struct description *description; char character_data[8192]; unsigned int character_data_length; }; -enum identifier_role { - STANDALONE_IDENT, - TRAILING_IDENT -}; - static void * fail_on_null(void *p) { if (p == NULL) { - fprintf(stderr, "%s: out of memory\n", PROGRAM_NAME); + fprintf(stderr, "wayland-scanner: out of memory\n"); exit(EXIT_FAILURE); } @@ -269,15 +156,9 @@ fail_on_null(void *p) } static void * -zalloc(size_t s) +xmalloc(size_t s) { - return calloc(s, 1); -} - -static void * -xzalloc(size_t s) -{ - return fail_on_null(zalloc(s)); + return fail_on_null(malloc(s)); } static char * @@ -317,7 +198,7 @@ static const char *indent(int n) } static void -desc_dump(char *desc, const char *fmt, ...) WL_PRINTF(2, 3); +desc_dump(char *desc, const char *fmt, ...) __attribute__((format(printf,2,3))); static void desc_dump(char *desc, const char *fmt, ...) @@ -380,7 +261,7 @@ desc_dump(char *desc, const char *fmt, ...) putchar('\n'); } -static void __attribute__ ((noreturn)) +static void fail(struct location *loc, const char *msg, ...) { va_list ap; @@ -407,313 +288,19 @@ warn(struct location *loc, const char *msg, ...) va_end(ap); } -static bool +static int is_nullable_type(struct arg *arg) { switch (arg->type) { - /* Strings and objects are possibly nullable */ + /* Strings, objects, and arrays are possibly nullable */ case STRING: case OBJECT: - return true; + case NEW_ID: + case ARRAY: + return 1; default: - return false; - } -} - -static struct message * -create_message(struct location loc, const char *name) -{ - struct message *message; - - message = xzalloc(sizeof *message); - message->loc = loc; - message->name = xstrdup(name); - message->uppercase_name = uppercase_dup(name); - wl_list_init(&message->arg_list); - - return message; -} - -static void -free_arg(struct arg *arg) -{ - free(arg->name); - free(arg->interface_name); - free(arg->summary); - free(arg->enumeration_name); - free(arg); -} - -static struct arg * -create_arg(const char *name) -{ - struct arg *arg; - - arg = xzalloc(sizeof *arg); - arg->name = xstrdup(name); - - return arg; -} - -static bool -set_arg_type(struct arg *arg, const char *type) -{ - if (strcmp(type, "int") == 0) - arg->type = INT; - else if (strcmp(type, "uint") == 0) - arg->type = UNSIGNED; - else if (strcmp(type, "fixed") == 0) - arg->type = FIXED; - else if (strcmp(type, "string") == 0) - arg->type = STRING; - else if (strcmp(type, "array") == 0) - arg->type = ARRAY; - else if (strcmp(type, "fd") == 0) - arg->type = FD; - else if (strcmp(type, "new_id") == 0) - arg->type = NEW_ID; - else if (strcmp(type, "object") == 0) - arg->type = OBJECT; - else - return false; - - return true; -} - -static void -free_description(struct description *desc) -{ - if (!desc) - return; - - free(desc->summary); - free(desc->text); - - free(desc); -} - -static void -free_message(struct message *message) -{ - struct arg *a, *a_next; - - free(message->name); - free(message->uppercase_name); - free_description(message->description); - - wl_list_for_each_safe(a, a_next, &message->arg_list, link) - free_arg(a); - - free(message); -} - -static struct enumeration * -create_enumeration(const char *name) -{ - struct enumeration *enumeration; - - enumeration = xzalloc(sizeof *enumeration); - enumeration->name = xstrdup(name); - enumeration->uppercase_name = uppercase_dup(name); - enumeration->since = 1; - - wl_list_init(&enumeration->entry_list); - - return enumeration; -} - -static struct entry * -create_entry(const char *name, const char *value) -{ - struct entry *entry; - - entry = xzalloc(sizeof *entry); - entry->name = xstrdup(name); - entry->uppercase_name = uppercase_dup(name); - entry->value = xstrdup(value); - - return entry; -} - -static void -free_entry(struct entry *entry) -{ - free(entry->name); - free(entry->uppercase_name); - free(entry->value); - free(entry->summary); - free_description(entry->description); - - free(entry); -} - -static void -free_enumeration(struct enumeration *enumeration) -{ - struct entry *e, *e_next; - - free(enumeration->name); - free(enumeration->uppercase_name); - free_description(enumeration->description); - - wl_list_for_each_safe(e, e_next, &enumeration->entry_list, link) - free_entry(e); - - free(enumeration); -} - -static struct interface * -create_interface(struct location loc, const char *name, int version) -{ - struct interface *interface; - - interface = xzalloc(sizeof *interface); - interface->loc = loc; - interface->name = xstrdup(name); - interface->uppercase_name = uppercase_dup(name); - interface->version = version; - interface->since = 1; - wl_list_init(&interface->request_list); - wl_list_init(&interface->event_list); - wl_list_init(&interface->enumeration_list); - - return interface; -} - -static void -free_interface(struct interface *interface) -{ - struct message *m, *next_m; - struct enumeration *e, *next_e; - - free(interface->name); - free(interface->uppercase_name); - free_description(interface->description); - - wl_list_for_each_safe(m, next_m, &interface->request_list, link) - free_message(m); - wl_list_for_each_safe(m, next_m, &interface->event_list, link) - free_message(m); - wl_list_for_each_safe(e, next_e, &interface->enumeration_list, link) - free_enumeration(e); - - free(interface); -} - -/* Convert string to unsigned integer - * - * Parses a non-negative base-10 number from the given string. If the - * specified string is blank, contains non-numerical characters, is out - * of range, or results in a negative number, -1 is returned to indicate - * an error. - * - * Upon error, this routine does not modify or set errno. - * - * Returns -1 on error, or a non-negative integer on success - */ -static int -strtouint(const char *str) -{ - long int ret; - char *end; - int prev_errno = errno; - - errno = 0; - ret = strtol(str, &end, 10); - if (errno != 0 || end == str || *end != '\0') - return -1; - - /* check range */ - if (ret < 0 || ret > INT_MAX) { - return -1; - } - - errno = prev_errno; - return (int)ret; -} - -/* Check that the provided string will produce valid "C" identifiers. - * - * If the string will form the prefix of an identifier in the - * generated C code, then it must match [_a-zA-Z][_0-9a-zA-Z]*. - * - * If the string will form the suffix of an identifier, then - * it must match [_0-9a-zA-Z]+. - * - * Unicode characters or escape sequences are not permitted, - * since not all C compilers support them. - * - * If the above conditions are not met, then fail() - */ -static void -validate_identifier(struct location *loc, - const char *str, - enum identifier_role role) -{ - const char *scan; - - if (!*str) { - fail(loc, "element name is empty"); - } - - for (scan = str; *scan; scan++) { - char c = *scan; - - /* we do not use the locale-dependent `isalpha` */ - bool is_alpha = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); - bool is_digit = c >= '0' && c <= '9'; - bool leading_char = (scan == str) && role == STANDALONE_IDENT; - - if (is_alpha || c == '_' || (!leading_char && is_digit)) - continue; - - if (role == TRAILING_IDENT) - fail(loc, - "'%s' is not a valid trailing identifier part", str); - else - fail(loc, - "'%s' is not a valid standalone identifier", str); - } -} - -static int -version_from_since(struct parse_context *ctx, const char *since) -{ - int version; - - if (since != NULL) { - version = strtouint(since); - if (version == -1) { - fail(&ctx->loc, "invalid integer (%s)\n", since); - } else if (version > ctx->interface->version) { - fail(&ctx->loc, "since (%u) larger than version (%u)\n", - version, ctx->interface->version); - } - } else { - version = 1; - } - - - return version; -} - -static int -version_from_deprecated_since(struct parse_context *ctx, const char *deprecated_since) -{ - int version; - - if (deprecated_since == NULL) return 0; - - version = strtouint(deprecated_since); - if (version == -1) { - fail(&ctx->loc, "invalid integer (%s)\n", deprecated_since); - } else if (version > ctx->interface->version) { - fail(&ctx->loc, "deprecated-since (%u) larger than version (%u)\n", - version, ctx->interface->version); } - - return version; } static void @@ -725,29 +312,27 @@ start_element(void *data, const char *element_name, const char **atts) struct arg *arg; struct enumeration *enumeration; struct entry *entry; - struct description *description = NULL; - const char *name = NULL; - const char *type = NULL; - const char *interface_name = NULL; - const char *value = NULL; - const char *summary = NULL; - const char *since = NULL; - const char *deprecated_since = NULL; - const char *allow_null = NULL; - const char *enumeration_name = NULL; - const char *bitfield = NULL; - const char *frozen = NULL; - int i, version = 0; + struct description *description; + const char *name, *type, *interface_name, *value, *summary, *since; + const char *allow_null; + char *end; + int i, version; ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); + name = NULL; + type = NULL; + version = 0; + interface_name = NULL; + value = NULL; + summary = NULL; + description = NULL; + since = NULL; + allow_null = NULL; for (i = 0; atts[i]; i += 2) { if (strcmp(atts[i], "name") == 0) name = atts[i + 1]; - if (strcmp(atts[i], "version") == 0) { - version = strtouint(atts[i + 1]); - if (version == -1) - fail(&ctx->loc, "wrong version (%s)", atts[i + 1]); - } + if (strcmp(atts[i], "version") == 0) + version = atoi(atts[i + 1]); if (strcmp(atts[i], "type") == 0) type = atts[i + 1]; if (strcmp(atts[i], "value") == 0) @@ -758,16 +343,8 @@ start_element(void *data, const char *element_name, const char **atts) summary = atts[i + 1]; if (strcmp(atts[i], "since") == 0) since = atts[i + 1]; - if (strcmp(atts[i], "deprecated-since") == 0) - deprecated_since = atts[i + 1]; if (strcmp(atts[i], "allow-null") == 0) allow_null = atts[i + 1]; - if (strcmp(atts[i], "enum") == 0) - enumeration_name = atts[i + 1]; - if (strcmp(atts[i], "bitfield") == 0) - bitfield = atts[i + 1]; - if (strcmp(atts[i], "frozen") == 0) - frozen = atts[i + 1]; } ctx->character_data_length = 0; @@ -775,11 +352,11 @@ start_element(void *data, const char *element_name, const char **atts) if (name == NULL) fail(&ctx->loc, "no protocol name given"); - validate_identifier(&ctx->loc, name, STANDALONE_IDENT); ctx->protocol->name = xstrdup(name); ctx->protocol->uppercase_name = uppercase_dup(name); + ctx->protocol->description = NULL; } else if (strcmp(element_name, "copyright") == 0) { - + } else if (strcmp(element_name, "interface") == 0) { if (name == NULL) fail(&ctx->loc, "no interface name given"); @@ -787,32 +364,32 @@ start_element(void *data, const char *element_name, const char **atts) if (version == 0) fail(&ctx->loc, "no interface version given"); - if (frozen) { - if (strcmp(frozen, "true") == 0) { - if (version != 1) { - fail(&ctx->loc, - "frozen interface must have version 1"); - } - } else if (strcmp(frozen, "false") != 0) { - fail(&ctx->loc, - "invalid value (%s) frozen attribute " - "(only true/false are accepted)", - frozen); - } - } - - validate_identifier(&ctx->loc, name, STANDALONE_IDENT); - interface = create_interface(ctx->loc, name, version); - ctx->interface = interface; + interface = xmalloc(sizeof *interface); + interface->loc = ctx->loc; + interface->name = xstrdup(name); + interface->uppercase_name = uppercase_dup(name); + interface->version = version; + interface->description = NULL; + interface->since = 1; + wl_list_init(&interface->request_list); + wl_list_init(&interface->event_list); + wl_list_init(&interface->enumeration_list); wl_list_insert(ctx->protocol->interface_list.prev, &interface->link); + ctx->interface = interface; } else if (strcmp(element_name, "request") == 0 || strcmp(element_name, "event") == 0) { if (name == NULL) fail(&ctx->loc, "no request name given"); - validate_identifier(&ctx->loc, name, STANDALONE_IDENT); - message = create_message(ctx->loc, name); + message = xmalloc(sizeof *message); + message->loc = ctx->loc; + message->name = xstrdup(name); + message->uppercase_name = uppercase_dup(name); + wl_list_init(&message->arg_list); + message->arg_count = 0; + message->new_id_count = 0; + message->description = NULL; if (strcmp(element_name, "request") == 0) wl_list_insert(ctx->interface->request_list.prev, @@ -823,20 +400,24 @@ start_element(void *data, const char *element_name, const char **atts) if (type != NULL && strcmp(type, "destructor") == 0) message->destructor = 1; + else + message->destructor = 0; + + if (since != NULL) { + errno = 0; + version = strtol(since, &end, 0); + if (errno == EINVAL || end == since || *end != '\0') + fail(&ctx->loc, + "invalid integer (%s)\n", since); + } else { + version = 1; + } - version = version_from_since(ctx, since); if (version < ctx->interface->since) warn(&ctx->loc, "since version not increasing\n"); ctx->interface->since = version; message->since = version; - version = version_from_deprecated_since(ctx, deprecated_since); - if (version > 0 && version <= message->since) - fail(&ctx->loc, "deprecated-since version (%d) smaller " - "or equal to since version (%u)\n", - version, message->since); - message->deprecated_since = version; - if (strcmp(name, "destroy") == 0 && !message->destructor) fail(&ctx->loc, "destroy request should be destructor type"); @@ -845,22 +426,40 @@ start_element(void *data, const char *element_name, const char **atts) if (name == NULL) fail(&ctx->loc, "no argument name given"); - validate_identifier(&ctx->loc, name, STANDALONE_IDENT); - arg = create_arg(name); - if (!set_arg_type(arg, type)) + arg = xmalloc(sizeof *arg); + arg->name = xstrdup(name); + + if (strcmp(type, "int") == 0) + arg->type = INT; + else if (strcmp(type, "uint") == 0) + arg->type = UNSIGNED; + else if (strcmp(type, "fixed") == 0) + arg->type = FIXED; + else if (strcmp(type, "string") == 0) + arg->type = STRING; + else if (strcmp(type, "array") == 0) + arg->type = ARRAY; + else if (strcmp(type, "fd") == 0) + arg->type = FD; + else if (strcmp(type, "new_id") == 0) { + arg->type = NEW_ID; + } else if (strcmp(type, "object") == 0) { + arg->type = OBJECT; + } else { fail(&ctx->loc, "unknown type (%s)", type); + } switch (arg->type) { case NEW_ID: ctx->message->new_id_count++; - /* fallthrough */ + + /* Fall through to OBJECT case. */ + case OBJECT: - if (interface_name) { - validate_identifier(&ctx->loc, - interface_name, - STANDALONE_IDENT); + if (interface_name) arg->interface_name = xstrdup(interface_name); - } + else + arg->interface_name = NULL; break; default: if (interface_name != NULL) @@ -868,24 +467,17 @@ start_element(void *data, const char *element_name, const char **atts) break; } - if (allow_null) { - if (strcmp(allow_null, "true") == 0) - arg->nullable = 1; - else if (strcmp(allow_null, "false") != 0) - fail(&ctx->loc, - "invalid value for allow-null attribute (%s)", - allow_null); - - if (!is_nullable_type(arg)) - fail(&ctx->loc, - "allow-null is only valid for objects, strings, and arrays"); - } - - if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0) - arg->enumeration_name = NULL; + if (allow_null == NULL || strcmp(allow_null, "false") == 0) + arg->nullable = 0; + else if (strcmp(allow_null, "true") == 0) + arg->nullable = 1; else - arg->enumeration_name = xstrdup(enumeration_name); + fail(&ctx->loc, "invalid value for allow-null attribute (%s)", allow_null); + if (allow_null != NULL && !is_nullable_type(arg)) + fail(&ctx->loc, "allow-null is only valid for objects, strings, and arrays"); + + arg->summary = NULL; if (summary) arg->summary = xstrdup(summary); @@ -895,17 +487,11 @@ start_element(void *data, const char *element_name, const char **atts) if (name == NULL) fail(&ctx->loc, "no enum name given"); - validate_identifier(&ctx->loc, name, TRAILING_IDENT); - enumeration = create_enumeration(name); - - if (bitfield == NULL || strcmp(bitfield, "false") == 0) - enumeration->bitfield = false; - else if (strcmp(bitfield, "true") == 0) - enumeration->bitfield = true; - else - fail(&ctx->loc, - "invalid value (%s) for bitfield attribute (only true/false are accepted)", - bitfield); + enumeration = xmalloc(sizeof *enumeration); + enumeration->name = xstrdup(name); + enumeration->uppercase_name = uppercase_dup(name); + enumeration->description = NULL; + wl_list_init(&enumeration->entry_list); wl_list_insert(ctx->interface->enumeration_list.prev, &enumeration->link); @@ -915,40 +501,25 @@ start_element(void *data, const char *element_name, const char **atts) if (name == NULL) fail(&ctx->loc, "no entry name given"); - validate_identifier(&ctx->loc, name, TRAILING_IDENT); - entry = create_entry(name, value); - - version = version_from_since(ctx, since); - if (version < ctx->enumeration->since) - warn(&ctx->loc, "since version not increasing\n"); - ctx->enumeration->since = version; - entry->since = version; - - version = version_from_deprecated_since(ctx, deprecated_since); - if (version > 0 && version <= entry->since) - fail(&ctx->loc, "deprecated-since version (%d) smaller " - "or equal to since version (%u)\n", - version, entry->since); - entry->deprecated_since = version; - + entry = xmalloc(sizeof *entry); + entry->name = xstrdup(name); + entry->uppercase_name = uppercase_dup(name); + entry->value = xstrdup(value); if (summary) entry->summary = xstrdup(summary); else entry->summary = NULL; wl_list_insert(ctx->enumeration->entry_list.prev, &entry->link); - ctx->entry = entry; } else if (strcmp(element_name, "description") == 0) { if (summary == NULL) fail(&ctx->loc, "description without summary"); - description = xzalloc(sizeof *description); + description = xmalloc(sizeof *description); description->summary = xstrdup(summary); if (ctx->message) ctx->message->description = description; - else if (ctx->entry) - ctx->entry->description = description; else if (ctx->enumeration) ctx->enumeration->description = description; else if (ctx->interface) @@ -959,88 +530,6 @@ start_element(void *data, const char *element_name, const char **atts) } } -static struct enumeration * -find_enumeration(struct protocol *protocol, - struct interface *interface, - char *enum_attribute) -{ - struct interface *i; - struct enumeration *e; - char *enum_name; - uint32_t idx = 0, j; - - for (j = 0; j + 1 < strlen(enum_attribute); j++) { - if (enum_attribute[j] == '.') { - idx = j; - } - } - - if (idx > 0) { - enum_name = enum_attribute + idx + 1; - - wl_list_for_each(i, &protocol->interface_list, link) - if (strncmp(i->name, enum_attribute, idx) == 0) - wl_list_for_each(e, &i->enumeration_list, link) - if (strcmp(e->name, enum_name) == 0) - return e; - } else if (interface) { - enum_name = enum_attribute; - - wl_list_for_each(e, &interface->enumeration_list, link) - if (strcmp(e->name, enum_name) == 0) - return e; - } - - return NULL; -} - -static void -verify_arguments(struct parse_context *ctx, - struct interface *interface, - struct wl_list *messages, - struct wl_list *enumerations) -{ - struct message *m; - wl_list_for_each(m, messages, link) { - struct arg *a; - wl_list_for_each(a, &m->arg_list, link) { - struct enumeration *e; - - if (!a->enumeration_name) - continue; - - - e = find_enumeration(ctx->protocol, interface, - a->enumeration_name); - - switch (a->type) { - case INT: - if (e && e->bitfield) - fail(&ctx->loc, - "bitfield-style enum must only be referenced by uint"); - break; - case UNSIGNED: - break; - default: - fail(&ctx->loc, - "enumeration-style argument has wrong type"); - } - } - } - -} - -#ifndef HAVE_STRNDUP -char * -strndup(const char *s, size_t size) -{ - char *r = malloc(size + 1); - strncpy(r, s, size); - r[size] = '\0'; - return r; -} -#endif - static void end_element(void *data, const XML_Char *name) { @@ -1059,20 +548,7 @@ end_element(void *data, const XML_Char *name) strcmp(name, "event") == 0) { ctx->message = NULL; } else if (strcmp(name, "enum") == 0) { - if (wl_list_empty(&ctx->enumeration->entry_list)) { - fail(&ctx->loc, "enumeration %s was empty", - ctx->enumeration->name); - } ctx->enumeration = NULL; - } else if (strcmp(name, "entry") == 0) { - ctx->entry = NULL; - } else if (strcmp(name, "protocol") == 0) { - struct interface *i; - - wl_list_for_each(i, &ctx->protocol->interface_list, link) { - verify_arguments(ctx, i, &i->request_list, &i->enumeration_list); - verify_arguments(ctx, i, &i->event_list, &i->enumeration_list); - } } } @@ -1090,34 +566,6 @@ character_data(void *data, const XML_Char *s, int len) ctx->character_data_length += len; } -static void -format_text_to_comment(const char *text, bool standalone_comment) -{ - int bol = 1, start = 0, i, length; - bool comment_started = !standalone_comment; - - length = strlen(text); - for (i = 0; i <= length; i++) { - if (bol && (text[i] == ' ' || text[i] == '\t')) { - continue; - } else if (bol) { - bol = 0; - start = i; - } - if (text[i] == '\n' || - (text[i] == '\0' && !(start == i))) { - printf("%s%s%.*s\n", - comment_started ? " *" : "/*", - i > start ? " " : "", - i - start, text + start); - bol = 1; - comment_started = true; - } - } - if (comment_started && standalone_comment) - printf(" */\n\n"); -} - static void emit_opcodes(struct wl_list *message_list, struct interface *interface) { @@ -1129,7 +577,7 @@ emit_opcodes(struct wl_list *message_list, struct interface *interface) opcode = 0; wl_list_for_each(m, message_list, link) - printf("#define %s_%s %d\n", + printf("#define %s_%s\t%d\n", interface->uppercase_name, m->uppercase_name, opcode++); printf("\n"); @@ -1140,11 +588,9 @@ emit_opcode_versions(struct wl_list *message_list, struct interface *interface) { struct message *m; - wl_list_for_each(m, message_list, link) { - printf("/**\n * @ingroup iface_%s\n */\n", interface->name); - printf("#define %s_%s_SINCE_VERSION %d\n", + wl_list_for_each(m, message_list, link) + printf("#define %s_%s_SINCE_VERSION\t%d\n", interface->uppercase_name, m->uppercase_name, m->since); - } printf("\n"); } @@ -1184,7 +630,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) struct arg *a, *ret; int has_destructor, has_destroy; - printf("/** @ingroup iface_%s */\n", interface->name); printf("static inline void\n" "%s_set_user_data(struct %s *%s, void *user_data)\n" "{\n" @@ -1193,7 +638,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) interface->name, interface->name, interface->name, interface->name); - printf("/** @ingroup iface_%s */\n", interface->name); printf("static inline void *\n" "%s_get_user_data(struct %s *%s)\n" "{\n" @@ -1202,14 +646,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) interface->name, interface->name, interface->name, interface->name); - printf("static inline uint32_t\n" - "%s_get_version(struct %s *%s)\n" - "{\n" - "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n" - "}\n\n", - interface->name, interface->name, interface->name, - interface->name); - has_destructor = 0; has_destroy = 0; wl_list_for_each(m, message_list, link) { @@ -1227,8 +663,7 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) exit(EXIT_FAILURE); } - if (!has_destroy && strcmp(interface->name, "wl_display") != 0) { - printf("/** @ingroup iface_%s */\n", interface->name); + if (!has_destroy && strcmp(interface->name, "wl_display") != 0) printf("static inline void\n" "%s_destroy(struct %s *%s)\n" "{\n" @@ -1237,7 +672,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) "}\n\n", interface->name, interface->name, interface->name, interface->name); - } if (wl_list_empty(message_list)) return; @@ -1257,11 +691,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) ret = a; } - printf("/**\n" - " * @ingroup iface_%s\n", interface->name); - if (m->description && m->description->text) - format_text_to_comment(m->description->text, false); - printf(" */\n"); if (ret && ret->interface_name == NULL) printf("static inline void *\n"); else if (ret) @@ -1288,40 +717,28 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) printf(")\n" "{\n"); - printf("\t"); if (ret) { - printf("struct wl_proxy *%s;\n\n" - "\t%s = ", ret->name, ret->name); - } - printf("wl_proxy_marshal_flags(" - "(struct wl_proxy *) %s,\n" - "\t\t\t %s_%s", - interface->name, - interface->uppercase_name, - m->uppercase_name); + printf("\tstruct wl_proxy *%s;\n\n" + "\t%s = wl_proxy_marshal_constructor(" + "(struct wl_proxy *) %s,\n" + "\t\t\t %s_%s, ", + ret->name, ret->name, + interface->name, + interface->uppercase_name, + m->uppercase_name); - if (ret) { - if (ret->interface_name) { - /* Normal factory case, an arg has type="new_id" and - * an interface is provided */ - printf(", &%s_interface", ret->interface_name); - } else { - /* an arg has type ="new_id" but interface is not - * provided, such as in wl_registry.bind */ - printf(", interface"); - } + if (ret->interface_name == NULL) + printf("interface"); + else + printf("&%s_interface", ret->interface_name); } else { - /* No args have type="new_id" */ - printf(", NULL"); + printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n" + "\t\t\t %s_%s", + interface->name, + interface->uppercase_name, + m->uppercase_name); } - if (ret && ret->interface_name == NULL) - printf(", version"); - else - printf(", wl_proxy_get_version((struct wl_proxy *) %s)", - interface->name); - printf(", %s", m->destructor ? "WL_MARSHAL_FLAG_DESTROY" : "0"); - wl_list_for_each(a, &m->arg_list, link) { if (a->type == NEW_ID) { if (a->interface_name == NULL) @@ -1333,6 +750,11 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) } printf(");\n"); + if (m->destructor) + printf("\n\twl_proxy_destroy(" + "(struct wl_proxy *) %s);\n", + interface->name); + if (ret && ret->interface_name == NULL) printf("\n\treturn (void *) %s;\n", ret->name); else if (ret) @@ -1354,17 +776,6 @@ emit_event_wrappers(struct wl_list *message_list, struct interface *interface) return; wl_list_for_each(m, message_list, link) { - printf("/**\n" - " * @ingroup iface_%s\n" - " * Sends an %s event to the client owning the resource.\n", - interface->name, - m->name); - printf(" * @param resource_ The client's resource\n"); - wl_list_for_each(a, &m->arg_list, link) { - if (a->summary) - printf(" * @param %s %s\n", a->name, a->summary); - } - printf(" */\n"); printf("static inline void\n" "%s_send_%s(struct wl_resource *resource_", interface->name, m->name); @@ -1396,59 +807,7 @@ emit_event_wrappers(struct wl_list *message_list, struct interface *interface) } static void -emit_validator(struct interface *interface, struct enumeration *e) -{ - struct entry *entry; - - printf("#ifndef %s_%s_ENUM_IS_VALID\n", - interface->uppercase_name, e->uppercase_name); - printf("#define %s_%s_ENUM_IS_VALID\n", - interface->uppercase_name, e->uppercase_name); - - printf("/**\n" - " * @ingroup iface_%s\n" - " * Validate a %s %s value.\n" - " *\n" - " * @return true on success, false on error.\n" - " * @ref %s_%s\n" - " */\n" - "static inline bool\n" - "%s_%s_is_valid(uint32_t value, uint32_t version) {\n", - interface->name, interface->name, e->name, - interface->name, e->name, - interface->name, e->name); - - if (e->bitfield) { - printf(" uint32_t valid = 0;\n"); - wl_list_for_each(entry, &e->entry_list, link) { - printf(" if (version >= %d)\n" - " valid |= %s_%s_%s;\n", - entry->since, - interface->uppercase_name, e->uppercase_name, - entry->uppercase_name); - } - printf(" return (value & ~valid) == 0;\n"); - } else { - printf(" switch (value) {\n"); - wl_list_for_each(entry, &e->entry_list, link) { - printf(" case %s%s_%s_%s:\n" - " return version >= %d;\n", - entry->value[0] == '-' ? "(uint32_t)" : "", - interface->uppercase_name, e->uppercase_name, - entry->uppercase_name, entry->since); - } - printf(" default:\n" - " return false;\n" - " }\n"); - } - printf("}\n"); - - printf("#endif /* %s_%s_ENUM_IS_VALID */\n\n", - interface->uppercase_name, e->uppercase_name); -} - -static void -emit_enumerations(struct interface *interface, bool with_validators) +emit_enumerations(struct interface *interface) { struct enumeration *e; struct entry *entry; @@ -1463,56 +822,31 @@ emit_enumerations(struct interface *interface, bool with_validators) if (desc) { printf("/**\n"); - printf(" * @ingroup iface_%s\n", interface->name); - format_text_to_comment(desc->summary, false); - if (desc->text) - format_text_to_comment(desc->text, false); + desc_dump(desc->summary, + " * %s_%s - ", + interface->name, e->name); + wl_list_for_each(entry, &e->entry_list, link) { + desc_dump(entry->summary, + " * @%s_%s_%s: ", + interface->uppercase_name, + e->uppercase_name, + entry->uppercase_name); + } + if (desc->text) { + printf(" *\n"); + desc_dump(desc->text, " * "); + } printf(" */\n"); } printf("enum %s_%s {\n", interface->name, e->name); - wl_list_for_each(entry, &e->entry_list, link) { - desc = entry->description; - if (entry->summary || entry->since > 1 || desc) { - printf("\t/**\n"); - if (entry->summary) - printf("\t * %s\n", entry->summary); - if (desc) { - printf("\t * %s\n", desc->summary); - printf("\t *\n"); - if (desc->text) - desc_dump(desc->text, "\t * "); - } - if (entry->since > 1) - printf("\t * @since %d\n", entry->since); - if (entry->deprecated_since > 0) - printf("\t * @deprecated Deprecated since version %d\n", - entry->deprecated_since); - printf("\t */\n"); - } + wl_list_for_each(entry, &e->entry_list, link) printf("\t%s_%s_%s = %s,\n", interface->uppercase_name, e->uppercase_name, entry->uppercase_name, entry->value); - } printf("};\n"); - - wl_list_for_each(entry, &e->entry_list, link) { - if (entry->since == 1) - continue; - - printf("/**\n * @ingroup iface_%s\n */\n", interface->name); - printf("#define %s_%s_%s_SINCE_VERSION %d\n", - interface->uppercase_name, - e->uppercase_name, entry->uppercase_name, - entry->since); - - } - printf("#endif /* %s_%s_ENUM */\n\n", interface->uppercase_name, e->uppercase_name); - - if (with_validators) - emit_validator(interface, e); } } @@ -1526,11 +860,20 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid if (wl_list_empty(message_list)) return; - printf("/**\n"); - printf(" * @ingroup iface_%s\n", interface->name); - printf(" * @struct %s_%s\n", interface->name, - (side == SERVER) ? "interface" : "listener"); - printf(" */\n"); + if (interface->description) { + struct description *desc = interface->description; + printf("/**\n"); + desc_dump(desc->summary, " * %s - ", interface->name); + wl_list_for_each(m, message_list, link) { + struct description *mdesc = m->description; + desc_dump(mdesc ? mdesc->summary : "(none)", + " * @%s: ", + m->name); + } + printf(" *\n"); + desc_dump(desc->text, " * "); + printf(" */\n"); + } printf("struct %s_%s {\n", interface->name, (side == SERVER) ? "interface" : "listener"); @@ -1538,27 +881,26 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid struct description *mdesc = m->description; printf("\t/**\n"); + desc_dump(mdesc ? mdesc->summary : "(none)", + "\t * %s - ", m->name); + wl_list_for_each(a, &m->arg_list, link) { + + if (side == SERVER && a->type == NEW_ID && + a->interface_name == NULL) + printf("\t * @interface: name of the objects interface\n" + "\t * @version: version of the objects interface\n"); + + + desc_dump(a->summary ? a->summary : "(none)", + "\t * @%s: ", a->name); + } if (mdesc) { - if (mdesc->summary) - printf("\t * %s\n", mdesc->summary); printf("\t *\n"); desc_dump(mdesc->text, "\t * "); } - wl_list_for_each(a, &m->arg_list, link) { - if (side == SERVER && a->type == NEW_ID && - a->interface_name == NULL) - printf("\t * @param interface name of the objects interface\n" - "\t * @param version version of the objects interface\n"); - - if (a->summary) - printf("\t * @param %s %s\n", a->name, - a->summary); + if (m->since > 1) { + printf("\t * @since: %d\n", m->since); } - if (m->since > 1) - printf("\t * @since %d\n", m->since); - if (m->deprecated_since > 0) - printf("\t * @deprecated Deprecated since version %d\n", - m->deprecated_since); printf("\t */\n"); printf("\tvoid (*%s)(", m->name); @@ -1597,9 +939,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid printf("};\n\n"); if (side == CLIENT) { - printf("/**\n" - " * @ingroup iface_%s\n" - " */\n", interface->name); printf("static inline int\n" "%s_add_listener(struct %s *%s,\n" "%sconst struct %s_listener *listener, void *data)\n" @@ -1615,6 +954,88 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid } } +static void +format_copyright(const char *copyright) +{ + int bol = 1, start = 0, i; + + for (i = 0; copyright[i]; i++) { + if (bol && (copyright[i] == ' ' || copyright[i] == '\t')) { + continue; + } else if (bol) { + bol = 0; + start = i; + } + + if (copyright[i] == '\n' || copyright[i] == '\0') { + printf("%s %.*s\n", + i == 0 ? "/*" : " *", + i - start, copyright + start); + bol = 1; + } + } + printf(" */\n\n"); +} + +static void +emit_header(struct protocol *protocol, enum side side) +{ + struct interface *i; + const char *s = (side == SERVER) ? "SERVER" : "CLIENT"; + + if (protocol->copyright) + format_copyright(protocol->copyright); + + printf("#ifndef %s_%s_PROTOCOL_H\n" + "#define %s_%s_PROTOCOL_H\n" + "\n" + "#ifdef __cplusplus\n" + "extern \"C\" {\n" + "#endif\n" + "\n" + "#include \n" + "#include \n" + "#include \"%s\"\n\n" + "struct wl_client;\n" + "struct wl_resource;\n\n", + protocol->uppercase_name, s, + protocol->uppercase_name, s, + (side == SERVER) ? "wayland-util.h" : "wayland-client.h"); + + wl_list_for_each(i, &protocol->interface_list, link) + printf("struct %s;\n", i->name); + printf("\n"); + + wl_list_for_each(i, &protocol->interface_list, link) { + printf("extern const struct wl_interface " + "%s_interface;\n", + i->name); + } + printf("\n"); + + wl_list_for_each(i, &protocol->interface_list, link) { + + emit_enumerations(i); + + if (side == SERVER) { + emit_structs(&i->request_list, i, side); + emit_opcodes(&i->event_list, i); + emit_opcode_versions(&i->event_list, i); + emit_event_wrappers(&i->event_list, i); + } else { + emit_structs(&i->event_list, i, side); + emit_opcodes(&i->request_list, i); + emit_stubs(&i->request_list, i); + } + } + + printf("#ifdef __cplusplus\n" + "}\n" + "#endif\n" + "\n" + "#endif\n"); +} + static void emit_types_forward_declarations(struct protocol *protocol, struct wl_list *message_list, @@ -1650,200 +1071,6 @@ emit_types_forward_declarations(struct protocol *protocol, } } -static int -cmp_names(const void *p1, const void *p2) -{ - const char * const *s1 = p1, * const *s2 = p2; - - return strcmp(*s1, *s2); -} - -static const char * -get_include_name(bool core, enum side side) -{ - if (side == SERVER) - return core ? "wayland-server-core.h" : "wayland-server.h"; - else - return core ? "wayland-client-core.h" : "wayland-client.h"; -} - -static void -emit_mainpage_blurb(const struct protocol *protocol, enum side side) -{ - struct interface *i; - - printf("/**\n" - " * @page page_%s The %s protocol\n", - protocol->name, protocol->name); - - if (protocol->description) { - if (protocol->description->summary) { - printf(" * %s\n" - " *\n", protocol->description->summary); - } - - if (protocol->description->text) { - printf(" * @section page_desc_%s Description\n", protocol->name); - format_text_to_comment(protocol->description->text, false); - printf(" *\n"); - } - } - - printf(" * @section page_ifaces_%s Interfaces\n", protocol->name); - wl_list_for_each(i, &protocol->interface_list, link) { - printf(" * - @subpage page_iface_%s - %s\n", - i->name, - i->description && i->description->summary ? i->description->summary : ""); - } - - if (protocol->copyright) { - printf(" * @section page_copyright_%s Copyright\n", - protocol->name); - printf(" *
\n");
-		format_text_to_comment(protocol->copyright, false);
-		printf(" * 
\n"); - } - - printf(" */\n"); -} - -static void -emit_header(struct protocol *protocol, enum side side) -{ - struct interface *i, *i_next; - struct wl_array types; - const char *s = (side == SERVER) ? "SERVER" : "CLIENT"; - char **p, *prev; - - printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION); - - printf("#ifndef %s_%s_PROTOCOL_H\n" - "#define %s_%s_PROTOCOL_H\n" - "\n" - "#include \n" - "#include \n" - "#include \"%s\"\n\n" - "#ifdef __cplusplus\n" - "extern \"C\" {\n" - "#endif\n\n", - protocol->uppercase_name, s, - protocol->uppercase_name, s, - get_include_name(protocol->core_headers, side)); - if (side == SERVER) - printf("struct wl_client;\n" - "struct wl_resource;\n\n"); - - emit_mainpage_blurb(protocol, side); - - wl_array_init(&types); - wl_list_for_each(i, &protocol->interface_list, link) { - emit_types_forward_declarations(protocol, &i->request_list, &types); - emit_types_forward_declarations(protocol, &i->event_list, &types); - } - - wl_list_for_each(i, &protocol->interface_list, link) { - p = fail_on_null(wl_array_add(&types, sizeof *p)); - *p = i->name; - } - - if (types.size > 0) - qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names); - - prev = NULL; - wl_array_for_each(p, &types) { - if (prev && strcmp(*p, prev) == 0) - continue; - printf("struct %s;\n", *p); - prev = *p; - } - wl_array_release(&types); - printf("\n"); - - wl_list_for_each(i, &protocol->interface_list, link) { - printf("#ifndef %s_INTERFACE\n", i->uppercase_name); - printf("#define %s_INTERFACE\n", i->uppercase_name); - printf("/**\n" - " * @page page_iface_%s %s\n", - i->name, i->name); - if (i->description && i->description->text) { - printf(" * @section page_iface_%s_desc Description\n", - i->name); - format_text_to_comment(i->description->text, false); - } - printf(" * @section page_iface_%s_api API\n" - " * See @ref iface_%s.\n" - " */\n", - i->name, i->name); - printf("/**\n" - " * @defgroup iface_%s The %s interface\n", - i->name, i->name); - if (i->description && i->description->text) - format_text_to_comment(i->description->text, false); - printf(" */\n"); - printf("extern const struct wl_interface " - "%s_interface;\n", i->name); - printf("#endif\n"); - } - - printf("\n"); - - wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) { - - emit_enumerations(i, side == SERVER); - - if (side == SERVER) { - emit_structs(&i->request_list, i, side); - emit_opcodes(&i->event_list, i); - emit_opcode_versions(&i->event_list, i); - emit_opcode_versions(&i->request_list, i); - emit_event_wrappers(&i->event_list, i); - } else { - emit_structs(&i->event_list, i, side); - emit_opcodes(&i->request_list, i); - emit_opcode_versions(&i->event_list, i); - emit_opcode_versions(&i->request_list, i); - emit_stubs(&i->request_list, i); - } - - free_interface(i); - } - - printf("#ifdef __cplusplus\n" - "}\n" - "#endif\n" - "\n" - "#endif\n"); -} - -static void -emit_enum_header(struct protocol *protocol) -{ - struct interface *i, *i_next; - - printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION); - - printf("#ifndef %s_ENUM_PROTOCOL_H\n" - "#define %s_ENUM_PROTOCOL_H\n" - "\n" - "#ifdef __cplusplus\n" - "extern \"C\" {\n" - "#endif\n\n", - protocol->uppercase_name, - protocol->uppercase_name); - - wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) { - emit_enumerations(i, false); - - free_interface(i); - } - - printf("#ifdef __cplusplus\n" - "}\n" - "#endif\n" - "\n" - "#endif\n"); -} - static void emit_null_run(struct protocol *protocol) { @@ -1888,7 +1115,7 @@ emit_types(struct protocol *protocol, struct wl_list *message_list) } static void -emit_messages(const char *name, struct wl_list *message_list, +emit_messages(struct wl_list *message_list, struct interface *interface, const char *suffix) { struct message *m; @@ -1941,57 +1168,40 @@ emit_messages(const char *name, struct wl_list *message_list, break; } } - printf("\", %s_types + %d },\n", name, m->type_index); + printf("\", types + %d },\n", m->type_index); } printf("};\n\n"); } +static int +cmp_names(const void *p1, const void *p2) +{ + const char * const *s1 = p1, * const *s2 = p2; + + return strcmp(*s1, *s2); +} static void -emit_code(struct protocol *protocol, enum visibility vis) +emit_code(struct protocol *protocol) { - const char *symbol_visibility; - struct interface *i, *next; + struct interface *i; struct wl_array types; char **p, *prev; - printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION); - if (protocol->copyright) - format_text_to_comment(protocol->copyright, true); + format_copyright(protocol->copyright); - printf("#include \n" - "#include \n" + printf("#include \n" "#include \n" "#include \"wayland-util.h\"\n\n"); - /* When building a shared library symbols must be exported, otherwise - * we want to have the symbols hidden. */ - if (vis == PRIVATE) { - symbol_visibility = "WL_PRIVATE"; - printf("#ifndef __has_attribute\n" - "# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */\n" - "#endif\n\n"); - - printf("#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n" - "#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n" - "#else\n" - "#define WL_PRIVATE\n" - "#endif\n\n"); - } else { - symbol_visibility = "WL_EXPORT"; - } - wl_array_init(&types); wl_list_for_each(i, &protocol->interface_list, link) { emit_types_forward_declarations(protocol, &i->request_list, &types); emit_types_forward_declarations(protocol, &i->event_list, &types); } - - if (types.size > 0) - qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names); - + qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names); prev = NULL; wl_array_for_each(p, &types) { if (prev && strcmp(*p, prev) == 0) @@ -2002,7 +1212,7 @@ emit_code(struct protocol *protocol, enum visibility vis) wl_array_release(&types); printf("\n"); - printf("static const struct wl_interface *%s_types[] = {\n", protocol->name); + printf("static const struct wl_interface *types[] = {\n"); emit_null_run(protocol); wl_list_for_each(i, &protocol->interface_list, link) { emit_types(protocol, &i->request_list); @@ -2010,15 +1220,15 @@ emit_code(struct protocol *protocol, enum visibility vis) } printf("};\n\n"); - wl_list_for_each_safe(i, next, &protocol->interface_list, link) { + wl_list_for_each(i, &protocol->interface_list, link) { - emit_messages(protocol->name, &i->request_list, i, "requests"); - emit_messages(protocol->name, &i->event_list, i, "events"); + emit_messages(&i->request_list, i, "requests"); + emit_messages(&i->event_list, i, "events"); - printf("%s const struct wl_interface " + printf("WL_EXPORT const struct wl_interface " "%s_interface = {\n" "\t\"%s\", %d,\n", - symbol_visibility, i->name, i->name, i->version); + i->name, i->name, i->version); if (!wl_list_empty(&i->request_list)) printf("\t%d, %s_requests,\n", @@ -2033,151 +1243,46 @@ emit_code(struct protocol *protocol, enum visibility vis) printf("\t0, NULL,\n"); printf("};\n\n"); - - /* we won't need it any further */ - free_interface(i); } } -static void -free_protocol(struct protocol *protocol) -{ - free(protocol->name); - free(protocol->uppercase_name); - free(protocol->copyright); - free_description(protocol->description); -} - int main(int argc, char *argv[]) { struct parse_context ctx; struct protocol protocol; - FILE *input = stdin; - char *input_filename = NULL; int len; void *buf; - bool help = false; - bool core_headers = false; - bool version = false; - bool strict = false; - bool fail = false; - int opt; enum { CLIENT_HEADER, SERVER_HEADER, - ENUM_HEADER, - PRIVATE_CODE, - PUBLIC_CODE, CODE, } mode; - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { "include-core-only", no_argument, NULL, 'c' }, - { "strict", no_argument, NULL, 's' }, - { 0, 0, NULL, 0 } - }; - - while (1) { - opt = getopt_long(argc, argv, "hvcs", options, NULL); - - if (opt == -1) - break; - - switch (opt) { - case 'h': - help = true; - break; - case 'v': - version = true; - break; - case 'c': - core_headers = true; - break; - case 's': - strict = true; - break; - default: - fail = true; - break; - } - } - - argv += optind; - argc -= optind; - - if (help) - usage(EXIT_SUCCESS); - else if (version) - scanner_version(EXIT_SUCCESS); - else if ((argc != 1 && argc != 3) || fail) + if (argc != 2) usage(EXIT_FAILURE); - else if (strcmp(argv[0], "help") == 0) + else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0) usage(EXIT_SUCCESS); - else if (strcmp(argv[0], "client-header") == 0) + else if (strcmp(argv[1], "client-header") == 0) mode = CLIENT_HEADER; - else if (strcmp(argv[0], "server-header") == 0) + else if (strcmp(argv[1], "server-header") == 0) mode = SERVER_HEADER; - else if (strcmp(argv[0], "enum-header") == 0) - mode = ENUM_HEADER; - else if (strcmp(argv[0], "private-code") == 0) - mode = PRIVATE_CODE; - else if (strcmp(argv[0], "public-code") == 0) - mode = PUBLIC_CODE; - else if (strcmp(argv[0], "code") == 0) + else if (strcmp(argv[1], "code") == 0) mode = CODE; else usage(EXIT_FAILURE); - if (argc == 3) { - input_filename = argv[1]; - input = fopen(input_filename, "r"); - if (input == NULL) { - fprintf(stderr, "Could not open input file: %s\n", - strerror(errno)); - exit(EXIT_FAILURE); - } - if (freopen(argv[2], "w", stdout) == NULL) { - fprintf(stderr, "Could not open output file: %s\n", - strerror(errno)); - fclose(input); - exit(EXIT_FAILURE); - } - } - - /* initialize protocol structure */ - memset(&protocol, 0, sizeof protocol); wl_list_init(&protocol.interface_list); - protocol.core_headers = core_headers; - - /* initialize context */ + protocol.type_index = 0; + protocol.null_run_length = 0; + protocol.copyright = NULL; memset(&ctx, 0, sizeof ctx); ctx.protocol = &protocol; - if (input == stdin) - ctx.loc.filename = ""; - else - ctx.loc.filename = input_filename; - if (!is_dtd_valid(input, ctx.loc.filename)) { - fprintf(stderr, - "*******************************************************\n" - "* *\n" - "* WARNING: XML failed validation against built-in DTD *\n" - "* *\n" - "*******************************************************\n"); - if (strict) { - fclose(input); - exit(EXIT_FAILURE); - } - } - - /* create XML parser */ + ctx.loc.filename = ""; ctx.parser = XML_ParserCreate(NULL); XML_SetUserData(ctx.parser, &ctx); if (ctx.parser == NULL) { fprintf(stderr, "failed to create parser\n"); - fclose(input); exit(EXIT_FAILURE); } @@ -2186,21 +1291,13 @@ int main(int argc, char *argv[]) do { buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE); - len = fread(buf, 1, XML_BUFFER_SIZE, input); + len = fread(buf, 1, XML_BUFFER_SIZE, stdin); if (len < 0) { - fprintf(stderr, "fread: %s\n", strerror(errno)); - fclose(input); - exit(EXIT_FAILURE); - } - if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) { - fprintf(stderr, - "Error parsing XML at line %ld col %ld: %s\n", - XML_GetCurrentLineNumber(ctx.parser), - XML_GetCurrentColumnNumber(ctx.parser), - XML_ErrorString(XML_GetErrorCode(ctx.parser))); - fclose(input); + fprintf(stderr, "fread: %m\n"); exit(EXIT_FAILURE); } + XML_ParseBuffer(ctx.parser, len, len == 0); + } while (len > 0); XML_ParserFree(ctx.parser); @@ -2212,25 +1309,10 @@ int main(int argc, char *argv[]) case SERVER_HEADER: emit_header(&protocol, SERVER); break; - case ENUM_HEADER: - emit_enum_header(&protocol); - break; - case PRIVATE_CODE: - emit_code(&protocol, PRIVATE); - break; case CODE: - fprintf(stderr, - "Using \"code\" is deprecated - use " - "private-code or public-code.\n" - "See the help page for details.\n"); - /* fallthrough */ - case PUBLIC_CODE: - emit_code(&protocol, PUBLIC); + emit_code(&protocol); break; } - free_protocol(&protocol); - fclose(input); - return 0; } diff --git a/src/scanner.mk b/src/scanner.mk new file mode 100644 index 00000000..1b6963ce --- /dev/null +++ b/src/scanner.mk @@ -0,0 +1,8 @@ +%-protocol.c : $(protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) code < $< > $@ + +%-server-protocol.h : $(protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) server-header < $< > $@ + +%-client-protocol.h : $(protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) client-header < $< > $@ diff --git a/src/timespec-util.h b/src/timespec-util.h deleted file mode 100644 index d3c53bd7..00000000 --- a/src/timespec-util.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright © 2014 - 2015 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. - */ - -#ifndef TIMESPEC_UTIL_H -#define TIMESPEC_UTIL_H - -#include -#include -#include -#include - -#define NSEC_PER_SEC 1000000000 - -/* Subtract timespecs - * - * \param r[out] result: a - b - * \param a[in] operand - * \param b[in] operand - */ -static inline void -timespec_sub(struct timespec *r, - const struct timespec *a, const struct timespec *b) -{ - r->tv_sec = a->tv_sec - b->tv_sec; - r->tv_nsec = a->tv_nsec - b->tv_nsec; - if (r->tv_nsec < 0) { - r->tv_sec--; - r->tv_nsec += NSEC_PER_SEC; - } -} - -/* Add a nanosecond value to a timespec - * - * \param r[out] result: a + b - * \param a[in] base operand as timespec - * \param b[in] operand in nanoseconds - */ -static inline void -timespec_add_nsec(struct timespec *r, const struct timespec *a, int64_t b) -{ - r->tv_sec = a->tv_sec + (b / NSEC_PER_SEC); - r->tv_nsec = a->tv_nsec + (b % NSEC_PER_SEC); - - if (r->tv_nsec >= NSEC_PER_SEC) { - r->tv_sec++; - r->tv_nsec -= NSEC_PER_SEC; - } else if (r->tv_nsec < 0) { - r->tv_sec--; - r->tv_nsec += NSEC_PER_SEC; - } -} - -/* Add a millisecond value to a timespec - * - * \param r[out] result: a + b - * \param a[in] base operand as timespec - * \param b[in] operand in milliseconds - */ -static inline void -timespec_add_msec(struct timespec *r, const struct timespec *a, int64_t b) -{ - timespec_add_nsec(r, a, b * 1000000); -} - -/* Convert timespec to nanoseconds - * - * \param a timespec - * \return nanoseconds - */ -static inline int64_t -timespec_to_nsec(const struct timespec *a) -{ - return (int64_t)a->tv_sec * NSEC_PER_SEC + a->tv_nsec; -} - -/* Subtract timespecs and return result in nanoseconds - * - * \param a[in] operand - * \param b[in] operand - * \return to_nanoseconds(a - b) - */ -static inline int64_t -timespec_sub_to_nsec(const struct timespec *a, const struct timespec *b) -{ - struct timespec r; - timespec_sub(&r, a, b); - return timespec_to_nsec(&r); -} - -/* Convert timespec to milliseconds - * - * \param a timespec - * \return milliseconds - * - * Rounding to integer milliseconds happens always down (floor()). - */ -static inline int64_t -timespec_to_msec(const struct timespec *a) -{ - return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; -} - -/* Subtract timespecs and return result in milliseconds - * - * \param a[in] operand - * \param b[in] operand - * \return to_milliseconds(a - b) - */ -static inline int64_t -timespec_sub_to_msec(const struct timespec *a, const struct timespec *b) -{ - return timespec_sub_to_nsec(a, b) / 1000000; -} - -/* Convert timespec to microseconds - * - * \param a timespec - * \return microseconds - * - * Rounding to integer microseconds happens always down (floor()). - */ -static inline int64_t -timespec_to_usec(const struct timespec *a) -{ - return (int64_t)a->tv_sec * 1000000 + a->tv_nsec / 1000; -} - -/* Convert timespec to protocol data - * - * \param a timespec - * \param tv_sec_hi[out] the high bytes of the seconds part - * \param tv_sec_lo[out] the low bytes of the seconds part - * \param tv_nsec[out] the nanoseconds part - * - * The input timespec must be normalized (the nanoseconds part should - * be less than 1 second) and non-negative. - */ -static inline void -timespec_to_proto(const struct timespec *a, uint32_t *tv_sec_hi, - uint32_t *tv_sec_lo, uint32_t *tv_nsec) -{ - assert(a->tv_sec >= 0); - assert(a->tv_nsec >= 0 && a->tv_nsec < NSEC_PER_SEC); - - uint64_t sec64 = a->tv_sec; - - *tv_sec_hi = sec64 >> 32; - *tv_sec_lo = sec64 & 0xffffffff; - *tv_nsec = a->tv_nsec; -} - -/* Convert nanoseconds to timespec - * - * \param a timespec - * \param b nanoseconds - */ -static inline void -timespec_from_nsec(struct timespec *a, int64_t b) -{ - a->tv_sec = b / NSEC_PER_SEC; - a->tv_nsec = b % NSEC_PER_SEC; -} - -/* Convert microseconds to timespec - * - * \param a timespec - * \param b microseconds - */ -static inline void -timespec_from_usec(struct timespec *a, int64_t b) -{ - timespec_from_nsec(a, b * 1000); -} - -/* Convert milliseconds to timespec - * - * \param a timespec - * \param b milliseconds - */ -static inline void -timespec_from_msec(struct timespec *a, int64_t b) -{ - timespec_from_nsec(a, b * 1000000); -} - -/* Convert protocol data to timespec - * - * \param a[out] timespec - * \param tv_sec_hi the high bytes of seconds part - * \param tv_sec_lo the low bytes of seconds part - * \param tv_nsec the nanoseconds part - */ -static inline void -timespec_from_proto(struct timespec *a, uint32_t tv_sec_hi, - uint32_t tv_sec_lo, uint32_t tv_nsec) -{ - a->tv_sec = ((uint64_t)tv_sec_hi << 32) + tv_sec_lo; - a->tv_nsec = tv_nsec; -} - -/* Check if a timespec is zero - * - * \param a timespec - * \return whether the timespec is zero - */ -static inline bool -timespec_is_zero(const struct timespec *a) -{ - return a->tv_sec == 0 && a->tv_nsec == 0; -} - -/* Check if two timespecs are equal - * - * \param a[in] timespec to check - * \param b[in] timespec to check - * \return whether timespecs a and b are equal - */ -static inline bool -timespec_eq(const struct timespec *a, const struct timespec *b) -{ - return a->tv_sec == b->tv_sec && - a->tv_nsec == b->tv_nsec; -} - -/* Convert milli-Hertz to nanoseconds - * - * \param mhz frequency in mHz, not zero - * \return period in nanoseconds - */ -static inline int64_t -millihz_to_nsec(uint32_t mhz) -{ - assert(mhz > 0); - return 1000000000000LL / mhz; -} - -/** - * Checks whether a timespec value is after another - * - * \param a[in] timespec to compare - * \param b[in] timespec to compare - * \return whether a is after b - */ -static inline bool -timespec_after(const struct timespec *a, const struct timespec *b) -{ - return (a->tv_sec == b->tv_sec) ? - (a->tv_nsec > b->tv_nsec) : - (a->tv_sec > b->tv_sec); -} - -/** - * Add timespecs - * - * \param r[out] result: a + b - * \param a[in] operand - * \param b[in] operand - */ -static inline void -timespec_add(struct timespec *r, - const struct timespec *a, const struct timespec *b) -{ - r->tv_sec = a->tv_sec + b->tv_sec; - r->tv_nsec = a->tv_nsec + b->tv_nsec; - if (r->tv_nsec > NSEC_PER_SEC) { - r->tv_sec++; - r->tv_nsec -= NSEC_PER_SEC; - } -} - -/** - * Saturating timespec subtraction - * - * \param r[out] result: max(a - b, 0) - * \param a[in] operand - * \param b[in] operand - */ -static inline void -timespec_sub_saturate(struct timespec *r, - const struct timespec *a, const struct timespec *b) -{ - timespec_sub(r, a, b); - if (r->tv_sec < 0) { - r->tv_sec = 0; - r->tv_nsec = 0; - } -} - -#endif /* TIMESPEC_UTIL_H */ diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h deleted file mode 100644 index e0523e49..00000000 --- a/src/wayland-client-core.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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. - */ - -#ifndef WAYLAND_CLIENT_CORE_H -#define WAYLAND_CLIENT_CORE_H - -#include -#include "wayland-util.h" -#include "wayland-version.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct timespec; - -/** \class wl_proxy - * - * \brief Represents a protocol object on the client side. - * - * A wl_proxy acts as a client side proxy to an object existing in the - * compositor. The proxy is responsible for converting requests made by the - * clients with \ref wl_proxy_marshal() into Wayland's wire format. Events - * coming from the compositor are also handled by the proxy, which will in - * turn call the handler set with \ref wl_proxy_add_listener(). - * - * \note With the exception of function \ref wl_proxy_set_queue(), functions - * accessing a wl_proxy are not normally used by client code. Clients - * should normally use the higher level interface generated by the scanner to - * interact with compositor objects. - * - */ -struct wl_proxy; - -/** \class wl_display - * - * \brief Represents a connection to the compositor and acts as a proxy to - * the wl_display singleton object. - * - * A wl_display object represents a client connection to a Wayland - * compositor. It is created with either \ref wl_display_connect() or - * \ref wl_display_connect_to_fd(). A connection is terminated using - * \ref wl_display_disconnect(). - * - * A wl_display is also used as the \ref wl_proxy for the wl_display - * singleton object on the compositor side. - * - * A wl_display object handles all the data sent from and to the - * compositor. When a \ref wl_proxy marshals a request, it will write its wire - * representation to the display's write buffer. The data is sent to the - * compositor when the client calls \ref wl_display_flush(). - * - * Incoming data is handled in two steps: queueing and dispatching. In the - * queue step, the data coming from the display fd is interpreted and - * added to a queue. On the dispatch step, the handler for the incoming - * event set by the client on the corresponding \ref wl_proxy is called. - * - * A wl_display has at least one event queue, called the default - * queue. Clients can create additional event queues with \ref - * wl_display_create_queue() and assign \ref wl_proxy's to it. Events - * occurring in a particular proxy are always queued in its assigned queue. - * A client can ensure that a certain assumption, such as holding a lock - * or running from a given thread, is true when a proxy event handler is - * called by assigning that proxy to an event queue and making sure that - * this queue is only dispatched when the assumption holds. - * - * The default queue is dispatched by calling \ref wl_display_dispatch(). - * This will dispatch any events queued on the default queue and attempt - * to read from the display fd if it's empty. Events read are then queued - * on the appropriate queues according to the proxy assignment. - * - * A user created queue is dispatched with \ref wl_display_dispatch_queue(). - * This function behaves exactly the same as wl_display_dispatch() - * but it dispatches given queue instead of the default queue. - * - * A real world example of event queue usage is Mesa's implementation of - * eglSwapBuffers() for the Wayland platform. This function might need - * to block until a frame callback is received, but dispatching the default - * queue could cause an event handler on the client to start drawing - * again. This problem is solved using another event queue, so that only - * the events handled by the EGL code are dispatched during the block. - * - * This creates a problem where a thread dispatches a non-default - * queue, reading all the data from the display fd. If the application - * would call \em poll(2) after that it would block, even though there - * might be events queued on the default queue. Those events should be - * dispatched with \ref wl_display_dispatch_pending() or \ref - * wl_display_dispatch_queue_pending() before flushing and blocking. - */ -struct wl_display; - -/** \class wl_event_queue - * - * \brief A queue for \ref wl_proxy object events. - * - * Event queues allows the events on a display to be handled in a thread-safe - * manner. See \ref wl_display for details. - * - */ -struct wl_event_queue; - -/** Destroy proxy after marshalling - * \relates wl_proxy - */ -#define WL_MARSHAL_FLAG_DESTROY (1 << 0) - -void -wl_event_queue_destroy(struct wl_event_queue *queue); - -struct wl_proxy * -wl_proxy_marshal_flags(struct wl_proxy *proxy, uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - uint32_t flags, ...); - -struct wl_proxy * -wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - uint32_t flags, - union wl_argument *args); - -void -wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...); - -void -wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode, - union wl_argument *args); - -struct wl_proxy * -wl_proxy_create(struct wl_proxy *factory, - const struct wl_interface *interface); - -void * -wl_proxy_create_wrapper(void *proxy); - -void -wl_proxy_wrapper_destroy(void *proxy_wrapper); - -struct wl_proxy * -wl_proxy_marshal_constructor(struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - ...); - -struct wl_proxy * -wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - ...); - -struct wl_proxy * -wl_proxy_marshal_array_constructor(struct wl_proxy *proxy, - uint32_t opcode, union wl_argument *args, - const struct wl_interface *interface); - -struct wl_proxy * -wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy, - uint32_t opcode, - union wl_argument *args, - const struct wl_interface *interface, - uint32_t version); - -void -wl_proxy_destroy(struct wl_proxy *proxy); - -int -wl_proxy_add_listener(struct wl_proxy *proxy, - void (**implementation)(void), void *data); - -const void * -wl_proxy_get_listener(struct wl_proxy *proxy); - -int -wl_proxy_add_dispatcher(struct wl_proxy *proxy, - wl_dispatcher_func_t dispatcher_func, - const void * dispatcher_data, void *data); - -void -wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); - -void * -wl_proxy_get_user_data(struct wl_proxy *proxy); - -uint32_t -wl_proxy_get_version(struct wl_proxy *proxy); - -uint32_t -wl_proxy_get_id(struct wl_proxy *proxy); - -void -wl_proxy_set_tag(struct wl_proxy *proxy, - const char * const *tag); - -const char * const * -wl_proxy_get_tag(struct wl_proxy *proxy); - -const char * -wl_proxy_get_class(struct wl_proxy *proxy); - -const struct wl_interface * -wl_proxy_get_interface(struct wl_proxy *proxy); - -struct wl_display * -wl_proxy_get_display(struct wl_proxy *proxy); - -void -wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue); - -struct wl_event_queue * -wl_proxy_get_queue(const struct wl_proxy *proxy); - -const char * -wl_event_queue_get_name(const struct wl_event_queue *queue); - -struct wl_display * -wl_display_connect(const char *name); - -struct wl_display * -wl_display_connect_to_fd(int fd); - -void -wl_display_disconnect(struct wl_display *display); - -int -wl_display_get_fd(struct wl_display *display); - -int -wl_display_dispatch(struct wl_display *display); - -int -wl_display_dispatch_queue(struct wl_display *display, - struct wl_event_queue *queue); - -int -wl_display_dispatch_timeout(struct wl_display *display, - const struct timespec *timeout); - -int -wl_display_dispatch_queue_timeout(struct wl_display *display, - struct wl_event_queue *queue, - const struct timespec *timeout); - -int -wl_display_dispatch_queue_pending(struct wl_display *display, - struct wl_event_queue *queue); - -int -wl_display_dispatch_queue_pending_single(struct wl_display *display, - struct wl_event_queue *queue); - -int -wl_display_dispatch_pending(struct wl_display *display); - -int -wl_display_dispatch_pending_single(struct wl_display *display); - -int -wl_display_get_error(struct wl_display *display); - -uint32_t -wl_display_get_protocol_error(struct wl_display *display, - const struct wl_interface **interface, - uint32_t *id); - -int -wl_display_flush(struct wl_display *display); - -int -wl_display_roundtrip_queue(struct wl_display *display, - struct wl_event_queue *queue); - -int -wl_display_roundtrip(struct wl_display *display); - -struct wl_event_queue * -wl_display_create_queue(struct wl_display *display); - -struct wl_event_queue * -wl_display_create_queue_with_name(struct wl_display *display, - const char *name); - -int -wl_display_prepare_read_queue(struct wl_display *display, - struct wl_event_queue *queue); - -int -wl_display_prepare_read(struct wl_display *display); - -void -wl_display_cancel_read(struct wl_display *display); - -int -wl_display_read_events(struct wl_display *display); - -void -wl_log_set_handler_client(wl_log_func_t handler); - -void -wl_display_set_max_buffer_size(struct wl_display *display, - size_t max_buffer_size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/wayland-client-uninstalled.pc.in b/src/wayland-client-uninstalled.pc.in new file mode 100644 index 00000000..3086621d --- /dev/null +++ b/src/wayland-client-uninstalled.pc.in @@ -0,0 +1,8 @@ +libdir=@abs_builddir@/.libs +includedir=@abs_srcdir@ + +Name: Wayland Client +Description: Wayland client side library (not installed) +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lwayland-client diff --git a/src/wayland-client.c b/src/wayland-client.c index 50b3b4b2..9f817f69 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -2,26 +2,23 @@ * Copyright © 2008-2012 Kristian Høgsberg * Copyright © 2010-2012 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: + * 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 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. + * 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. */ #define _GNU_SOURCE @@ -37,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -45,19 +43,12 @@ #include "wayland-os.h" #include "wayland-client.h" #include "wayland-private.h" -#include "timespec-util.h" /** \cond */ enum wl_proxy_flag { WL_PROXY_FLAG_ID_DELETED = (1 << 0), - WL_PROXY_FLAG_DESTROYED = (1 << 1), - WL_PROXY_FLAG_WRAPPER = (1 << 2), -}; - -struct wl_zombie { - int event_count; - int *fd_count; + WL_PROXY_FLAG_DESTROYED = (1 << 1) }; struct wl_proxy { @@ -68,16 +59,18 @@ struct wl_proxy { int refcount; void *user_data; wl_dispatcher_func_t dispatcher; +}; + +struct wl_global { + uint32_t id; + char *interface; uint32_t version; - const char * const *tag; - struct wl_list queue_link; /**< in struct wl_event_queue::proxy_list */ + struct wl_list link; }; struct wl_event_queue { struct wl_list event_list; - struct wl_list proxy_list; /**< struct wl_proxy::queue_link */ struct wl_display *display; - char *name; }; struct wl_display { @@ -115,12 +108,11 @@ struct wl_display { /** \endcond */ static int debug_client = 0; -static int debug_color = 0; /** * This helper function wakes up all threads that are * waiting for display->reader_cond (i. e. when reading is done, - * canceled, or an error occurred) + * canceled, or an error occured) * * NOTE: must be called with display->mutex locked */ @@ -161,8 +153,8 @@ display_fatal_error(struct wl_display *display, int error) /** * This function is called for error events - * and indicates that in some object an error occurred. - * The difference between this function and display_fatal_error() + * and indicates that in some object an error occured. + * Difference between this function and display_fatal_error() * is that this one handles errors that will come by wire, * whereas display_fatal_error() is called for local errors. * @@ -181,7 +173,7 @@ display_protocol_error(struct wl_display *display, uint32_t code, return; /* set correct errno */ - if (intf && wl_interface_equal(intf, &wl_display_interface)) { + if (wl_interface_equal(intf, &wl_display_interface)) { switch (code) { case WL_DISPLAY_ERROR_INVALID_OBJECT: case WL_DISPLAY_ERROR_INVALID_METHOD: @@ -190,9 +182,6 @@ display_protocol_error(struct wl_display *display, uint32_t code, case WL_DISPLAY_ERROR_NO_MEMORY: err = ENOMEM; break; - case WL_DISPLAY_ERROR_IMPLEMENTATION: - err = EPROTO; - break; default: err = EFAULT; } @@ -222,87 +211,10 @@ display_protocol_error(struct wl_display *display, uint32_t code, } static void -wl_event_queue_init(struct wl_event_queue *queue, - struct wl_display *display, - const char *name) +wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display) { wl_list_init(&queue->event_list); - wl_list_init(&queue->proxy_list); queue->display = display; - if (name) - queue->name = strdup(name); -} - -static void -wl_proxy_unref(struct wl_proxy *proxy) -{ - if (!(proxy->refcount > 0)) - wl_abort("Proxy requested for unref has no references\n"); - if (--proxy->refcount > 0) - return; - - /* If we get here, the client must have explicitly requested - * deletion. */ - if (!(proxy->flags & WL_PROXY_FLAG_DESTROYED)) - wl_abort("Proxy with no references not yet explicitly" - "destroyed\n"); - free(proxy); -} - -static void -validate_closure_objects(struct wl_closure *closure) -{ - const char *signature; - struct argument_details arg; - int i, count; - struct wl_proxy *proxy; - - signature = closure->message->signature; - count = arg_count_for_signature(signature); - for (i = 0; i < count; i++) { - signature = get_next_argument(signature, &arg); - switch (arg.type) { - case WL_ARG_NEW_ID: - case WL_ARG_OBJECT: - proxy = (struct wl_proxy *) closure->args[i].o; - if (proxy && proxy->flags & WL_PROXY_FLAG_DESTROYED) - closure->args[i].o = NULL; - break; - default: - break; - } - } -} - -/* Destroys a closure which was demarshaled for dispatch; unrefs all the - * proxies in its arguments, as well as its own proxy, and destroys the - * closure itself. */ -static void -destroy_queued_closure(struct wl_closure *closure) -{ - const char *signature; - struct argument_details arg; - struct wl_proxy *proxy; - int i, count; - - signature = closure->message->signature; - count = arg_count_for_signature(signature); - for (i = 0; i < count; i++) { - signature = get_next_argument(signature, &arg); - switch (arg.type) { - case WL_ARG_NEW_ID: - case WL_ARG_OBJECT: - proxy = (struct wl_proxy *) closure->args[i].o; - if (proxy) - wl_proxy_unref(proxy); - break; - default: - break; - } - } - - wl_proxy_unref(closure->proxy); - wl_closure_destroy(closure); } static void @@ -310,39 +222,11 @@ wl_event_queue_release(struct wl_event_queue *queue) { struct wl_closure *closure; - if (!wl_list_empty(&queue->proxy_list)) { - struct wl_proxy *proxy, *tmp; - - if (queue != &queue->display->default_queue) { - if (queue->name) { - wl_log("warning: queue \"%s\" " - "%p destroyed while proxies " - "still attached:\n", queue->name, queue); - } else { - wl_log("warning: queue " - "%p destroyed while proxies " - "still attached:\n", queue); - } - } - - wl_list_for_each_safe(proxy, tmp, &queue->proxy_list, - queue_link) { - if (queue != &queue->display->default_queue) { - wl_log(" %s#%u still attached\n", - proxy->object.interface->name, - proxy->object.id); - } - proxy->queue = NULL; - wl_list_remove(&proxy->queue_link); - wl_list_init(&proxy->queue_link); - } - } - while (!wl_list_empty(&queue->event_list)) { - closure = wl_container_of(queue->event_list.next, - closure, link); + closure = container_of(queue->event_list.next, + struct wl_closure, link); wl_list_remove(&closure->link); - destroy_queued_closure(closure); + wl_closure_destroy(closure); } } @@ -366,7 +250,6 @@ wl_event_queue_destroy(struct wl_event_queue *queue) pthread_mutex_lock(&display->mutex); wl_event_queue_release(queue); - free(queue->name); free(queue); pthread_mutex_unlock(&display->mutex); } @@ -384,125 +267,33 @@ wl_display_create_queue(struct wl_display *display) { struct wl_event_queue *queue; - queue = zalloc(sizeof *queue); + queue = malloc(sizeof *queue); if (queue == NULL) return NULL; - wl_event_queue_init(queue, display, NULL); + wl_event_queue_init(queue, display); return queue; } -/** Create a new event queue for this display and give it a name - * - * \param display The display context object - * \param name A human readable queue name - * \return A new event queue associated with this display or NULL on - * failure. - * - * \memberof wl_display - */ -WL_EXPORT struct wl_event_queue * -wl_display_create_queue_with_name(struct wl_display *display, const char *name) -{ - struct wl_event_queue *queue; - - queue = zalloc(sizeof *queue); - if (queue == NULL) - return NULL; - - wl_event_queue_init(queue, display, name); - - return queue; -} - -static int -message_count_fds(const char *signature) -{ - unsigned int count, i, fds = 0; - struct argument_details arg; - - count = arg_count_for_signature(signature); - for (i = 0; i < count; i++) { - signature = get_next_argument(signature, &arg); - if (arg.type == WL_ARG_FD) - fds++; - } - - return fds; -} - -static struct wl_zombie * -prepare_zombie(struct wl_proxy *proxy) -{ - const struct wl_interface *interface = proxy->object.interface; - const struct wl_message *message; - int i, count; - struct wl_zombie *zombie = NULL; - - /* If we hit an event with an FD, ensure we have a zombie object and - * fill the fd_count slot for that event with the number of FDs for - * that event. Interfaces with no events containing FDs will not have - * zombie objects created. */ - for (i = 0; i < interface->event_count; i++) { - message = &interface->events[i]; - count = message_count_fds(message->signature); - - if (!count) - continue; - - if (!zombie) { - zombie = zalloc(sizeof(*zombie) + - (interface->event_count * sizeof(int))); - if (!zombie) - return NULL; - - zombie->event_count = interface->event_count; - zombie->fd_count = (int *) &zombie[1]; - } - - zombie->fd_count[i] = count; - } - - return zombie; -} - -static enum wl_iterator_result -free_zombies(void *element, void *data, uint32_t flags) -{ - if (flags & WL_MAP_ENTRY_ZOMBIE) - free(element); - - return WL_ITERATOR_CONTINUE; -} - static struct wl_proxy * -proxy_create(struct wl_proxy *factory, const struct wl_interface *interface, - uint32_t version) +proxy_create(struct wl_proxy *factory, const struct wl_interface *interface) { struct wl_proxy *proxy; struct wl_display *display = factory->display; - proxy = zalloc(sizeof *proxy); + proxy = malloc(sizeof *proxy); if (proxy == NULL) return NULL; + memset(proxy, 0, sizeof *proxy); + proxy->object.interface = interface; proxy->display = display; proxy->queue = factory->queue; proxy->refcount = 1; - proxy->version = version; proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy); - if (proxy->object.id == 0) { - free(proxy); - return NULL; - } - - if (proxy->queue != NULL) - wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link); - else - wl_list_init(&proxy->queue_link); return proxy; } @@ -533,7 +324,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface) struct wl_proxy *proxy; pthread_mutex_lock(&display->mutex); - proxy = proxy_create(factory, interface, factory->version); + proxy = proxy_create(factory, interface); pthread_mutex_unlock(&display->mutex); return proxy; @@ -547,78 +338,27 @@ wl_proxy_create_for_id(struct wl_proxy *factory, struct wl_proxy *proxy; struct wl_display *display = factory->display; - proxy = zalloc(sizeof *proxy); + proxy = malloc(sizeof *proxy); if (proxy == NULL) return NULL; + memset(proxy, 0, sizeof *proxy); + proxy->object.interface = interface; proxy->object.id = id; proxy->display = display; proxy->queue = factory->queue; proxy->refcount = 1; - proxy->version = factory->version; - if (wl_map_insert_at(&display->objects, 0, id, proxy) == -1) { - free(proxy); - return NULL; - } - - if (proxy->queue != NULL) - wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link); - else - wl_list_init(&proxy->queue_link); + wl_map_insert_at(&display->objects, 0, id, proxy); return proxy; } -static void -proxy_destroy(struct wl_proxy *proxy) -{ - if (proxy->flags & WL_PROXY_FLAG_ID_DELETED) { - wl_map_remove(&proxy->display->objects, proxy->object.id); - } else if (proxy->object.id < WL_SERVER_ID_START) { - struct wl_zombie *zombie = prepare_zombie(proxy); - - /* The map now contains the zombie entry, until the delete_id - * event arrives. */ - wl_map_insert_at(&proxy->display->objects, - WL_MAP_ENTRY_ZOMBIE, - proxy->object.id, - zombie); - } else { - wl_map_insert_at(&proxy->display->objects, 0, - proxy->object.id, NULL); - } - - proxy->flags |= WL_PROXY_FLAG_DESTROYED; - - proxy->queue = NULL; - wl_list_remove(&proxy->queue_link); - wl_list_init(&proxy->queue_link); - - wl_proxy_unref(proxy); -} - -static void -wl_proxy_destroy_caller_locks(struct wl_proxy *proxy) -{ - if (proxy->flags & WL_PROXY_FLAG_WRAPPER) - wl_abort("Tried to destroy wrapper with wl_proxy_destroy()\n"); - - proxy_destroy(proxy); -} - /** Destroy a proxy object * * \param proxy The proxy to be destroyed * - * \c proxy must not be a proxy wrapper. - * - * \note This function will abort in response to egregious - * errors, and will do so with the display lock held. This means - * SIGABRT handlers must not perform any actions that would - * attempt to take that lock, or a deadlock would occur. - * * \memberof wl_proxy */ WL_EXPORT void @@ -628,7 +368,21 @@ wl_proxy_destroy(struct wl_proxy *proxy) pthread_mutex_lock(&display->mutex); - wl_proxy_destroy_caller_locks(proxy); + if (proxy->flags & WL_PROXY_FLAG_ID_DELETED) + wl_map_remove(&proxy->display->objects, proxy->object.id); + else if (proxy->object.id < WL_SERVER_ID_START) + wl_map_insert_at(&proxy->display->objects, 0, + proxy->object.id, WL_ZOMBIE_OBJECT); + else + wl_map_insert_at(&proxy->display->objects, 0, + proxy->object.id, NULL); + + + proxy->flags |= WL_PROXY_FLAG_DESTROYED; + + proxy->refcount--; + if (!proxy->refcount) + free(proxy); pthread_mutex_unlock(&display->mutex); } @@ -648,17 +402,12 @@ wl_proxy_destroy(struct wl_proxy *proxy) * \c n, \c implementation[n] should point to the handler of \c n for * the given object. * - * \c proxy must not be a proxy wrapper. - * * \memberof wl_proxy */ WL_EXPORT int wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), void *data) { - if (proxy->flags & WL_PROXY_FLAG_WRAPPER) - wl_abort("Proxy %p is a wrapper\n", proxy); - if (proxy->object.implementation || proxy->dispatcher) { wl_log("proxy %p already has listener\n", proxy); return -1; @@ -678,11 +427,8 @@ wl_proxy_add_listener(struct wl_proxy *proxy, * Gets the address to the proxy's listener; which is the listener set with * \ref wl_proxy_add_listener. * - * This function is useful in clients with multiple listeners on the same - * interface to allow the identification of which code to execute. - * - * If \ref wl_proxy_add_dispatcher was used, this function returns the - * dispatcher_data pointer instead. + * This function is useful in client with multiple listeners on the same + * interface to allow the identification of which code to eexecute. * * \memberof wl_proxy */ @@ -708,8 +454,6 @@ wl_proxy_get_listener(struct wl_proxy *proxy) * The exact details of dispatcher_data depend on the dispatcher used. This * function is intended to be used by language bindings, not user code. * - * \c proxy must not be a proxy wrapper. - * * \memberof wl_proxy */ WL_EXPORT int @@ -717,11 +461,8 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy, wl_dispatcher_func_t dispatcher, const void *implementation, void *data) { - if (proxy->flags & WL_PROXY_FLAG_WRAPPER) - wl_abort("Proxy %p is a wrapper\n", proxy); - if (proxy->object.implementation || proxy->dispatcher) { - wl_log("proxy %p already has listener\n", proxy); + wl_log("proxy %p already has listener\n"); return -1; } @@ -735,7 +476,7 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy, static struct wl_proxy * create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message, union wl_argument *args, - const struct wl_interface *interface, uint32_t version) + const struct wl_interface *interface) { int i, count; const char *signature; @@ -746,14 +487,16 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message, count = arg_count_for_signature(signature); for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); - if (arg.type != WL_ARG_NEW_ID) - continue; - new_proxy = proxy_create(proxy, interface, version); - if (new_proxy == NULL) - return NULL; + switch (arg.type) { + case 'n': + new_proxy = proxy_create(proxy, interface); + if (new_proxy == NULL) + return NULL; - args[i].o = &new_proxy->object; + args[i].o = &new_proxy->object; + break; + } } return new_proxy; @@ -766,14 +509,13 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message, * \param args Extra arguments for the given request * \param interface The interface to use for the new proxy * - * This function translates a request given an opcode, an interface and a - * wl_argument array to the wire format and writes it to the connection - * buffer. + * Translates the request given by opcode and the extra arguments into the + * wire format and write it to the connection buffer. This version takes an + * array of the union type wl_argument. * * For new-id arguments, this function will allocate a new wl_proxy * and send the ID to the server. The new wl_proxy will be returned - * on success or NULL on error with errno set accordingly. The newly - * created proxy will inherit their version from their parent. + * on success or NULL on errror with errno set accordingly. * * \note This is intended to be used by language bindings and not in * non-generated code. @@ -786,180 +528,39 @@ WL_EXPORT struct wl_proxy * wl_proxy_marshal_array_constructor(struct wl_proxy *proxy, uint32_t opcode, union wl_argument *args, const struct wl_interface *interface) -{ - return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, - args, interface, - proxy->version); -} - - -/** Prepare a request to be sent to the compositor - * - * \param proxy The proxy object - * \param opcode Opcode of the request to be sent - * \param args Extra arguments for the given request - * \param interface The interface to use for the new proxy - * \param version The protocol object version for the new proxy - * - * Translates the request given by opcode and the extra arguments into the - * wire format and write it to the connection buffer. This version takes an - * array of the union type wl_argument. - * - * For new-id arguments, this function will allocate a new wl_proxy - * and send the ID to the server. The new wl_proxy will be returned - * on success or NULL on error with errno set accordingly. The newly - * created proxy will have the version specified. - * - * \note This is intended to be used by language bindings and not in - * non-generated code. - * - * \sa wl_proxy_marshal() - * - * \memberof wl_proxy - */ -WL_EXPORT struct wl_proxy * -wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy, - uint32_t opcode, - union wl_argument *args, - const struct wl_interface *interface, - uint32_t version) -{ - return wl_proxy_marshal_array_flags(proxy, opcode, interface, version, 0, args); -} - -/** Prepare a request to be sent to the compositor - * - * \param proxy The proxy object - * \param opcode Opcode of the request to be sent - * \param interface The interface to use for the new proxy - * \param version The protocol object version of the new proxy - * \param flags Flags that modify marshalling behaviour - * \param ... Extra arguments for the given request - * \return A new wl_proxy for the new_id argument or NULL on error - * - * Translates the request given by opcode and the extra arguments into the - * wire format and write it to the connection buffer. - * - * For new-id arguments, this function will allocate a new wl_proxy - * and send the ID to the server. The new wl_proxy will be returned - * on success or NULL on error with errno set accordingly. The newly - * created proxy will have the version specified. - * - * The flag WL_MARSHAL_FLAG_DESTROY may be passed to ensure the proxy - * is destroyed atomically with the marshalling in order to prevent - * races that can occur if the display lock is dropped between the - * marshal and destroy operations. - * - * \note This should not normally be used by non-generated code. - * - * \memberof wl_proxy - */ -WL_EXPORT struct wl_proxy * -wl_proxy_marshal_flags(struct wl_proxy *proxy, uint32_t opcode, - const struct wl_interface *interface, uint32_t version, - uint32_t flags, ...) -{ - union wl_argument args[WL_CLOSURE_MAX_ARGS]; - va_list ap; - - va_start(ap, flags); - wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, - args, WL_CLOSURE_MAX_ARGS, ap); - va_end(ap); - - return wl_proxy_marshal_array_flags(proxy, opcode, interface, version, flags, args); -} - -/** Prepare a request to be sent to the compositor - * - * \param proxy The proxy object - * \param opcode Opcode of the request to be sent - * \param interface The interface to use for the new proxy - * \param version The protocol object version for the new proxy - * \param flags Flags that modify marshalling behaviour - * \param args Extra arguments for the given request - * - * Translates the request given by opcode and the extra arguments into the - * wire format and write it to the connection buffer. This version takes an - * array of the union type wl_argument. - * - * For new-id arguments, this function will allocate a new wl_proxy - * and send the ID to the server. The new wl_proxy will be returned - * on success or NULL on error with errno set accordingly. The newly - * created proxy will have the version specified. - * - * The flag WL_MARSHAL_FLAG_DESTROY may be passed to ensure the proxy - * is destroyed atomically with the marshalling in order to prevent - * races that can occur if the display lock is dropped between the - * marshal and destroy operations. - * - * \note This is intended to be used by language bindings and not in - * non-generated code. - * - * \sa wl_proxy_marshal_flags() - * - * \memberof wl_proxy - */ -WL_EXPORT struct wl_proxy * -wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode, - const struct wl_interface *interface, uint32_t version, - uint32_t flags, union wl_argument *args) { struct wl_closure *closure; struct wl_proxy *new_proxy = NULL; const struct wl_message *message; - struct wl_display *disp = proxy->display; - pthread_mutex_lock(&disp->mutex); + pthread_mutex_lock(&proxy->display->mutex); message = &proxy->object.interface->methods[opcode]; if (interface) { new_proxy = create_outgoing_proxy(proxy, message, - args, interface, - version); + args, interface); if (new_proxy == NULL) goto err_unlock; } - if (proxy->display->last_error) { - goto err_unlock; - } - closure = wl_closure_marshal(&proxy->object, opcode, args, message); if (closure == NULL) { - wl_log("Error marshalling request for %s.%s: %s\n", - proxy->object.interface->name, message->name, - strerror(errno)); - display_fatal_error(proxy->display, errno); - goto err_unlock; + wl_log("Error marshalling request: %m\n"); + abort(); } - if (debug_client) { - struct wl_event_queue *queue; - const char *queue_name = NULL; - - queue = wl_proxy_get_queue(proxy); - if (queue) - queue_name = wl_event_queue_get_name(queue); - - wl_closure_print(closure, &proxy->object, true, false, NULL, - queue_name, debug_color); - } + if (debug_client) + wl_closure_print(closure, &proxy->object, true); if (wl_closure_send(closure, proxy->display->connection)) { - wl_log("Error sending request for %s.%s: %s\n", - proxy->object.interface->name, message->name, - strerror(errno)); - display_fatal_error(proxy->display, errno); + wl_log("Error sending request: %m\n"); + abort(); } wl_closure_destroy(closure); err_unlock: - if (flags & WL_MARSHAL_FLAG_DESTROY) - wl_proxy_destroy_caller_locks(proxy); - - pthread_mutex_unlock(&disp->mutex); + pthread_mutex_unlock(&proxy->display->mutex); return new_proxy; } @@ -1002,15 +603,12 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) * \param ... Extra arguments for the given request * \return A new wl_proxy for the new_id argument or NULL on error * - * This function translates a request given an opcode, an interface and extra - * arguments to the wire format and writes it to the connection buffer. The - * types of the extra arguments must correspond to the argument types of the - * method associated with the opcode in the interface. + * Translates the request given by opcode and the extra arguments into the + * wire format and write it to the connection buffer. * * For new-id arguments, this function will allocate a new wl_proxy * and send the ID to the server. The new wl_proxy will be returned - * on success or NULL on error with errno set accordingly. The newly - * created proxy will inherit their version from their parent. + * on success or NULL on errror with errno set accordingly. * * \note This should not normally be used by non-generated code. * @@ -1032,46 +630,6 @@ wl_proxy_marshal_constructor(struct wl_proxy *proxy, uint32_t opcode, args, interface); } - -/** Prepare a request to be sent to the compositor - * - * \param proxy The proxy object - * \param opcode Opcode of the request to be sent - * \param interface The interface to use for the new proxy - * \param version The protocol object version of the new proxy - * \param ... Extra arguments for the given request - * \return A new wl_proxy for the new_id argument or NULL on error - * - * Translates the request given by opcode and the extra arguments into the - * wire format and write it to the connection buffer. - * - * For new-id arguments, this function will allocate a new wl_proxy - * and send the ID to the server. The new wl_proxy will be returned - * on success or NULL on error with errno set accordingly. The newly - * created proxy will have the version specified. - * - * \note This should not normally be used by non-generated code. - * - * \memberof wl_proxy - */ -WL_EXPORT struct wl_proxy * -wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, ...) -{ - union wl_argument args[WL_CLOSURE_MAX_ARGS]; - va_list ap; - - va_start(ap, version); - wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, - args, WL_CLOSURE_MAX_ARGS, ap); - va_end(ap); - - return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, - args, interface, - version); -} - /** Prepare a request to be sent to the compositor * * \param proxy The proxy object @@ -1101,26 +659,12 @@ display_handle_error(void *data, uint32_t code, const char *message) { struct wl_proxy *proxy = object; - uint32_t object_id; - const struct wl_interface *interface; - if (proxy) { - wl_log("%s#%u: error %d: %s\n", - proxy->object.interface->name, - proxy->object.id, - code, message); + wl_log("%s@%u: error %d: %s\n", + proxy->object.interface->name, proxy->object.id, code, message); - object_id = proxy->object.id; - interface = proxy->object.interface; - } else { - wl_log("[destroyed object]: error %d: %s\n", - code, message); - - object_id = 0; - interface = NULL; - } - - display_protocol_error(display, code, object_id, interface); + display_protocol_error(display, code, proxy->object.id, + proxy->object.interface); } static void @@ -1132,16 +676,13 @@ display_handle_delete_id(void *data, struct wl_display *display, uint32_t id) proxy = wl_map_lookup(&display->objects, id); - if (wl_object_is_zombie(&display->objects, id)) { - /* For zombie objects, the 'proxy' is actually the zombie - * event-information structure, which we can free. */ - free(proxy); - wl_map_remove(&display->objects, id); - } else if (proxy) { - proxy->flags |= WL_PROXY_FLAG_ID_DELETED; - } else { + if (!proxy) wl_log("error: received delete_id for unknown id (%u)\n", id); - } + + if (proxy && proxy != WL_ZOMBIE_OBJECT) + proxy->flags |= WL_PROXY_FLAG_ID_DELETED; + else + wl_map_remove(&display->objects, id); pthread_mutex_unlock(&display->mutex); } @@ -1158,51 +699,35 @@ connect_to_socket(const char *name) socklen_t size; const char *runtime_dir; int name_size, fd; - bool path_is_absolute; - - if (name == NULL) - name = getenv("WAYLAND_DISPLAY"); - if (name == NULL) - name = "wayland-0"; - - path_is_absolute = name[0] == '/'; runtime_dir = getenv("XDG_RUNTIME_DIR"); - if (((!runtime_dir || runtime_dir[0] != '/') && !path_is_absolute)) { - wl_log("error: XDG_RUNTIME_DIR is invalid or not set in the environment.\n"); + if (!runtime_dir) { + wl_log("error: XDG_RUNTIME_DIR not set in the environment.\n"); /* to prevent programs reporting * "failed to create display: Success" */ errno = ENOENT; return -1; } + if (name == NULL) + name = getenv("WAYLAND_DISPLAY"); + if (name == NULL) + name = "wayland-0"; + fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0); if (fd < 0) return -1; memset(&addr, 0, sizeof addr); addr.sun_family = AF_LOCAL; - if (!path_is_absolute) { - name_size = - snprintf(addr.sun_path, sizeof addr.sun_path, - "%s/%s", runtime_dir, name) + 1; - } else { - /* absolute path */ - name_size = - snprintf(addr.sun_path, sizeof addr.sun_path, - "%s", name) + 1; - } + name_size = + snprintf(addr.sun_path, sizeof addr.sun_path, + "%s/%s", runtime_dir, name) + 1; - if (!(name_size > 0)) - wl_abort("Error assigning path name for socket connection\n"); + assert(name_size > 0); if (name_size > (int)sizeof addr.sun_path) { - if (!path_is_absolute) { - wl_log("error: socket path \"%s/%s\" plus null terminator" - " exceeds %i bytes\n", runtime_dir, name, (int) sizeof(addr.sun_path)); - } else { - wl_log("error: socket path \"%s\" plus null terminator" - " exceeds %i bytes\n", name, (int) sizeof(addr.sun_path)); - } + wl_log("error: socket path \"%s/%s\" plus null terminator" + " exceeds 108 bytes\n", runtime_dir, name); close(fd); /* to prevent programs reporting * "failed to add socket: Success" */ @@ -1236,48 +761,32 @@ wl_display_connect_to_fd(int fd) { struct wl_display *display; const char *debug; - const char *no_color; - const char *force_color; - no_color = getenv("NO_COLOR"); - force_color = getenv("FORCE_COLOR"); debug = getenv("WAYLAND_DEBUG"); - if (debug && (wl_check_env_token(debug, "client") || wl_check_env_token(debug, "1"))) { + if (debug && (strstr(debug, "client") || strstr(debug, "1"))) debug_client = 1; - if (isatty(fileno(stderr))) - debug_color = 1; - } - if (force_color && force_color[0] != '\0') - debug_color = 1; - - if (no_color && no_color[0] != '\0') - debug_color = 0; - - display = zalloc(sizeof *display); + display = malloc(sizeof *display); if (display == NULL) { close(fd); return NULL; } + memset(display, 0, sizeof *display); + display->fd = fd; wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE); - wl_event_queue_init(&display->default_queue, display, "Default Queue"); - wl_event_queue_init(&display->display_queue, display, "Display Queue"); + wl_event_queue_init(&display->default_queue, display); + wl_event_queue_init(&display->display_queue, display); pthread_mutex_init(&display->mutex, NULL); pthread_cond_init(&display->reader_cond, NULL); display->reader_count = 0; - if (wl_map_insert_at(&display->objects, 0, 0, NULL) == -1) - goto err_connection; - - display->proxy.object.id = - wl_map_insert_new(&display->objects, 0, display); - - if (display->proxy.object.id == 0) - goto err_connection; + wl_map_insert_new(&display->objects, 0, NULL); display->proxy.object.interface = &wl_display_interface; + display->proxy.object.id = + wl_map_insert_new(&display->objects, 0, display); display->proxy.display = display; display->proxy.object.implementation = (void(**)(void)) &display_listener; display->proxy.user_data = display; @@ -1285,26 +794,7 @@ wl_display_connect_to_fd(int fd) display->proxy.flags = 0; display->proxy.refcount = 1; - /* We set this version to 0 for backwards compatibility. - * - * If a client is using old versions of protocol headers, - * it will use unversioned API to create proxies. Those - * proxies will inherit this 0. - * - * A client could be passing these proxies into library - * code newer than the headers that checks proxy - * versions. When the proxy version is reported as 0 - * the library will know that it can't reliably determine - * the proxy version, and should do whatever fallback is - * required. - * - * This trick forces wl_display to always report 0, but - * since it's a special object that we can't bind - * specific versions of anyway, this should be fine. - */ - display->proxy.version = 0; - - display->connection = wl_connection_create(display->fd, 0); + display->connection = wl_connection_create(display->fd); if (display->connection == NULL) goto err_connection; @@ -1329,23 +819,6 @@ wl_display_connect_to_fd(int fd) * its value will be replaced with the WAYLAND_DISPLAY environment * variable if it is set, otherwise display "wayland-0" will be used. * - * If WAYLAND_SOCKET is set, it's interpreted as a file descriptor number - * referring to an already opened socket. In this case, the socket is used - * as-is and \c name is ignored. - * - * If \c name is a relative path, then the socket is opened relative to - * the XDG_RUNTIME_DIR directory. - * - * If \c name is an absolute path, then that path is used as-is for - * the location of the socket at which the Wayland server is listening; - * no qualification inside XDG_RUNTIME_DIR is attempted. - * - * If \c name is \c NULL and the WAYLAND_DISPLAY environment variable - * is set to an absolute pathname, then that pathname is used as-is - * for the socket in the same manner as if \c name held an absolute - * path. Support for absolute paths in \c name and WAYLAND_DISPLAY - * is present since Wayland version 1.15. - * * \memberof wl_display */ WL_EXPORT struct wl_display * @@ -1356,17 +829,12 @@ wl_display_connect(const char *name) connection = getenv("WAYLAND_SOCKET"); if (connection) { - int prev_errno = errno; - errno = 0; - fd = strtol(connection, &end, 10); - if (errno != 0 || connection == end || *end != '\0') + fd = strtol(connection, &end, 0); + if (*end != '\0') return NULL; - errno = prev_errno; flags = fcntl(fd, F_GETFD); - if (flags == -1 && errno == EBADF) - return NULL; - else if (flags != -1) + if (flags != -1) fcntl(fd, F_SETFD, flags | FD_CLOEXEC); unsetenv("WAYLAND_SOCKET"); } else { @@ -1382,9 +850,8 @@ wl_display_connect(const char *name) * * \param display The display context object * - * Close the connection to \c display. The \ref wl_proxy and - * \ref wl_event_queue objects need to be manually destroyed by the caller - * before disconnecting. + * Close the connection to \c display and free all resources associated + * with it. * * \memberof wl_display */ @@ -1392,12 +859,8 @@ WL_EXPORT void wl_display_disconnect(struct wl_display *display) { wl_connection_destroy(display->connection); - wl_map_for_each(&display->objects, free_zombies, NULL); wl_map_release(&display->objects); wl_event_queue_release(&display->default_queue); - free(display->default_queue.name); - wl_event_queue_release(&display->display_queue); - free(display->display_queue.name); pthread_mutex_destroy(&display->mutex); pthread_cond_destroy(&display->reader_cond); close(display->fd); @@ -1440,40 +903,22 @@ static const struct wl_callback_listener sync_listener = { * \param queue The queue on which to run the roundtrip * \return The number of dispatched events on success or -1 on failure * - * This function blocks until the server has processed all currently issued - * requests by sending a request to the display server and waiting for a - * reply before returning. + * Blocks until the server process all currently issued requests and + * sends out pending events on the event queue. * - * This function uses wl_display_dispatch_queue() internally. It is not allowed - * to call this function while the thread is being prepared for reading events, - * and doing so will cause a dead lock. - * - * \note This function may dispatch other events being received on the given - * queue. - * - * \sa wl_display_roundtrip() * \memberof wl_display */ WL_EXPORT int wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *queue) { - struct wl_display *display_wrapper; struct wl_callback *callback; int done, ret = 0; done = 0; - - display_wrapper = wl_proxy_create_wrapper(display); - if (!display_wrapper) - return -1; - - wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); - callback = wl_display_sync(display_wrapper); - wl_proxy_wrapper_destroy(display_wrapper); - + callback = wl_display_sync(display); if (callback == NULL) return -1; - + wl_proxy_set_queue((struct wl_proxy *) callback, queue); wl_callback_add_listener(callback, &sync_listener, &done); while (!done && ret >= 0) ret = wl_display_dispatch_queue(display, queue); @@ -1489,16 +934,8 @@ wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *qu * \param display The display context object * \return The number of dispatched events on success or -1 on failure * - * This function blocks until the server has processed all currently issued - * requests by sending a request to the display server and waiting for a reply - * before returning. - * - * This function uses wl_display_dispatch_queue() internally. It is not allowed - * to call this function while the thread is being prepared for reading events, - * and doing so will cause a dead lock. - * - * \note This function may dispatch other events being received on the default - * queue. + * Blocks until the server process all currently issued requests and + * sends out pending events on the default event queue. * * \memberof wl_display */ @@ -1522,19 +959,22 @@ create_proxies(struct wl_proxy *sender, struct wl_closure *closure) count = arg_count_for_signature(signature); for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); - if (arg.type != WL_ARG_NEW_ID) - continue; - - id = closure->args[i].n; - if (id == 0) { - closure->args[i].o = NULL; - continue; + switch (arg.type) { + case 'n': + id = closure->args[i].n; + if (id == 0) { + closure->args[i].o = NULL; + break; + } + proxy = wl_proxy_create_for_id(sender, id, + closure->message->types[i]); + if (proxy == NULL) + return -1; + closure->args[i].o = (struct wl_object *)proxy; + break; + default: + break; } - proxy = wl_proxy_create_for_id(sender, id, - closure->message->types[i]); - if (proxy == NULL) - return -1; - closure->args[i].o = (struct wl_object *)proxy; } return 0; @@ -1553,8 +993,8 @@ increase_closure_args_refcount(struct wl_closure *closure) for (i = 0; i < count; i++) { signature = get_next_argument(signature, &arg); switch (arg.type) { - case WL_ARG_NEW_ID: - case WL_ARG_OBJECT: + case 'n': + case 'o': proxy = (struct wl_proxy *) closure->args[i].o; if (proxy) proxy->refcount++; @@ -1563,8 +1003,6 @@ increase_closure_args_refcount(struct wl_closure *closure) break; } } - - closure->proxy->refcount++; } static int @@ -1576,74 +1014,21 @@ queue_event(struct wl_display *display, int len) struct wl_closure *closure; const struct wl_message *message; struct wl_event_queue *queue; - struct timespec tp; - unsigned int time; - int num_zombie_fds; wl_connection_copy(display->connection, p, sizeof p); id = p[0]; opcode = p[1] & 0xffff; size = p[1] >> 16; - - /* - * If the message is larger than the maximum size of the - * connection buffer, the connection buffer will fill to - * its max size and stay there, with no message ever - * successfully being processed. If the user of - * libwayland-client uses a level-triggered event loop, - * this will cause the client to enter a loop that - * consumes CPU. To avoid this, immediately drop the - * connection. Since the maximum size of a message should - * not depend on the max buffer size chosen by the client, - * always compare the message size against the - * limit enforced by libwayland 1.22 and below (4096), - * rather than the actual value the client chose. - */ - if (size > WL_MAX_MESSAGE_SIZE) { - wl_log("Message length %u exceeds limit %d\n", - size, WL_MAX_MESSAGE_SIZE); - errno = E2BIG; - return -1; - } - if (len < size) return 0; - /* If our proxy is gone or a zombie, just eat the event (and any FDs, - * if applicable). */ proxy = wl_map_lookup(&display->objects, id); - if (!proxy || wl_object_is_zombie(&display->objects, id)) { - struct wl_zombie *zombie = wl_map_lookup(&display->objects, id); - num_zombie_fds = (zombie && opcode < zombie->event_count) ? - zombie->fd_count[opcode] : 0; - - if (debug_client) { - clock_gettime(CLOCK_REALTIME, &tp); - time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); - fprintf(stderr, "%s[%7u.%03u] %sdiscarded %s[%s]%s#%u%s.[event %d]%s" - "(%d fd, %d byte)\n", - debug_color ? WL_DEBUG_COLOR_GREEN : "", - time / 1000, time % 1000, - debug_color ? WL_DEBUG_COLOR_RED : "", - debug_color ? WL_DEBUG_COLOR_BLUE : "", - zombie ? "zombie" : "unknown", - debug_color ? WL_DEBUG_COLOR_MAGENTA : "", id, - debug_color ? WL_DEBUG_COLOR_BLUE : "", opcode, - debug_color ? WL_DEBUG_COLOR_RESET : "", - num_zombie_fds, size); - } - if (num_zombie_fds > 0) - wl_connection_close_fds_in(display->connection, - num_zombie_fds); - + if (proxy == WL_ZOMBIE_OBJECT) { + wl_connection_consume(display->connection, size); + return size; + } else if (proxy == NULL) { wl_connection_consume(display->connection, size); return size; - } - - if (opcode >= proxy->object.interface->event_count) { - wl_log("interface '%s' has no event %u\n", - proxy->object.interface->name, opcode); - return -1; } message = &proxy->object.interface->events[opcode]; @@ -1662,33 +1047,49 @@ queue_event(struct wl_display *display, int len) return -1; } - closure->proxy = proxy; increase_closure_args_refcount(closure); + proxy->refcount++; + closure->proxy = proxy; if (proxy == &display->proxy) queue = &display->display_queue; else queue = proxy->queue; - if (!queue) - wl_abort("Tried to add event to destroyed queue\n"); - wl_list_insert(queue->event_list.prev, &closure->link); return size; } -static uint32_t -id_from_object(union wl_argument *arg) +static void +decrease_closure_args_refcount(struct wl_closure *closure) { + const char *signature; + struct argument_details arg; + int i, count; struct wl_proxy *proxy; - if (arg->o) { - proxy = (struct wl_proxy *)arg->o; - return proxy->object.id; - } + signature = closure->message->signature; + count = arg_count_for_signature(signature); + for (i = 0; i < count; i++) { + signature = get_next_argument(signature, &arg); + switch (arg.type) { + case 'n': + case 'o': + proxy = (struct wl_proxy *) closure->args[i].o; + if (proxy) { + if (proxy->flags & WL_PROXY_FLAG_DESTROYED) + closure->args[i].o = NULL; - return 0; + proxy->refcount--; + if (!proxy->refcount) + free(proxy); + } + break; + default: + break; + } + } } static void @@ -1699,42 +1100,46 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue) int opcode; bool proxy_destroyed; - closure = wl_container_of(queue->event_list.next, closure, link); + closure = container_of(queue->event_list.next, + struct wl_closure, link); wl_list_remove(&closure->link); opcode = closure->opcode; /* Verify that the receiving object is still valid by checking if has * been destroyed by the application. */ - validate_closure_objects(closure); + + decrease_closure_args_refcount(closure); proxy = closure->proxy; proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED); - if (debug_client) { - bool discarded = proxy_destroyed || - !(proxy->dispatcher || proxy->object.implementation); - - wl_closure_print(closure, &proxy->object, false, discarded, - id_from_object, queue->name, debug_color); - } - + proxy->refcount--; if (proxy_destroyed) { - destroy_queued_closure(closure); + if (!proxy->refcount) + free(proxy); + + wl_closure_destroy(closure); return; } pthread_mutex_unlock(&display->mutex); if (proxy->dispatcher) { + if (debug_client) + wl_closure_print(closure, &proxy->object, false); + wl_closure_dispatch(closure, proxy->dispatcher, &proxy->object, opcode); } else if (proxy->object.implementation) { + if (debug_client) + wl_closure_print(closure, &proxy->object, false); + wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT, &proxy->object, opcode, proxy->user_data); } - pthread_mutex_lock(&display->mutex); + wl_closure_destroy(closure); - destroy_queued_closure(closure); + pthread_mutex_lock(&display->mutex); } static int @@ -1747,13 +1152,8 @@ read_events(struct wl_display *display) if (display->reader_count == 0) { total = wl_connection_read(display->connection); if (total == -1) { - if (errno == EAGAIN) { - /* we must wake up threads whenever - * the reader_count dropped to 0 */ - display_wakeup_threads(display); - + if (errno == EAGAIN) return 0; - } display_fatal_error(display, errno); return -1; @@ -1782,56 +1182,27 @@ read_events(struct wl_display *display) while (display->read_serial == serial) pthread_cond_wait(&display->reader_cond, &display->mutex); - - if (display->last_error) { - errno = display->last_error; - return -1; - } } return 0; } -static void -cancel_read(struct wl_display *display) -{ - display->reader_count--; - if (display->reader_count == 0) - display_wakeup_threads(display); -} - /** Read events from display file descriptor * * \param display The display context object * \return 0 on success or -1 on error. In case of error errno will * be set accordingly * - * Calling this function will result in data available on the display file - * descriptor being read and read events will be queued on their corresponding - * event queues. + * This will read events from the file descriptor for the display. + * This function does not dispatch events, it only reads and queues + * events into their corresponding event queues. If no data is + * avilable on the file descriptor, wl_display_read_events() returns + * immediately. To dispatch events that may have been queued, call + * wl_display_dispatch_pending() or + * wl_display_dispatch_queue_pending(). * - * Before calling this function, depending on what thread it is to be called - * from, wl_display_prepare_read_queue() or wl_display_prepare_read() needs to - * be called. See wl_display_prepare_read_queue() for more details. - * - * When being called at a point where other threads have been prepared to read - * (using wl_display_prepare_read_queue() or wl_display_prepare_read()) this - * function will sleep until all other prepared threads have either been - * cancelled (using wl_display_cancel_read()) or them self entered this - * function. The last thread that calls this function will then read and queue - * events on their corresponding event queues, and finally wake up all other - * wl_display_read_events() calls causing them to return. - * - * If a thread cancels a read preparation when all other threads that have - * prepared to read has either called wl_display_cancel_read() or - * wl_display_read_events(), all reader threads will return without having read - * any data. - * - * To dispatch events that may have been queued, call - * wl_display_dispatch_pending() or wl_display_dispatch_queue_pending(). - * - * \sa wl_display_prepare_read(), wl_display_cancel_read(), - * wl_display_dispatch_pending(), wl_display_dispatch() + * Before calling this function, wl_display_prepare_read() must be + * called first. * * \memberof wl_display */ @@ -1843,7 +1214,6 @@ wl_display_read_events(struct wl_display *display) pthread_mutex_lock(&display->mutex); if (display->last_error) { - cancel_read(display); pthread_mutex_unlock(&display->mutex); errno = display->last_error; @@ -1888,88 +1258,6 @@ err: return -1; } - -static int -dispatch_queue_single(struct wl_display *display, struct wl_event_queue *queue) -{ - if (display->last_error) - goto err; - - while (!wl_list_empty(&display->display_queue.event_list)) { - dispatch_event(display, &display->display_queue); - if (display->last_error) - goto err; - } - - if (!wl_list_empty(&queue->event_list)) { - dispatch_event(display, queue); - if (display->last_error) - goto err; - return 1; - } else { - return 0; - } - -err: - errno = display->last_error; - - return -1; -} - -/** Prepare to read events from the display's file descriptor to a queue - * - * \param display The display context object - * \param queue The event queue to use - * \return 0 on success or -1 if event queue was not empty - * - * This function (or wl_display_prepare_read()) must be called before reading - * from the file descriptor using wl_display_read_events(). Calling - * wl_display_prepare_read_queue() announces the calling thread's intention to - * read and ensures that until the thread is ready to read and calls - * wl_display_read_events(), no other thread will read from the file descriptor. - * This only succeeds if the event queue is empty, and if not -1 is returned and - * errno set to EAGAIN. - * - * If a thread successfully calls wl_display_prepare_read_queue(), it must - * either call wl_display_read_events() when it's ready or cancel the read - * intention by calling wl_display_cancel_read(). - * - * Use this function before polling on the display fd or integrate the fd into a - * toolkit event loop in a race-free way. A correct usage would be (with most - * error checking left out): - * - * \code - * while (wl_display_prepare_read_queue(display, queue) != 0) - * wl_display_dispatch_queue_pending(display, queue); - * wl_display_flush(display); - * - * ret = poll(fds, nfds, -1); - * if (has_error(ret)) - * wl_display_cancel_read(display); - * else - * wl_display_read_events(display); - * - * wl_display_dispatch_queue_pending(display, queue); - * \endcode - * - * Here we call wl_display_prepare_read_queue(), which ensures that between - * returning from that call and eventually calling wl_display_read_events(), no - * other thread will read from the fd and queue events in our queue. If the call - * to wl_display_prepare_read_queue() fails, we dispatch the pending events and - * try again until we're successful. - * - * The wl_display_prepare_read_queue() function doesn't acquire exclusive access - * to the display's fd. It only registers that the thread calling this function - * has intention to read from fd. When all registered readers call - * wl_display_read_events(), only one (at random) eventually reads and queues - * the events and the others are sleeping meanwhile. This way we avoid races and - * still can read from more threads. - * - * \sa wl_display_cancel_read(), wl_display_read_events(), - * wl_display_prepare_read() - * - * \memberof wl_display - */ WL_EXPORT int wl_display_prepare_read_queue(struct wl_display *display, struct wl_event_queue *queue) @@ -1991,15 +1279,64 @@ wl_display_prepare_read_queue(struct wl_display *display, return ret; } -/** Prepare to read events from the display's file descriptor +/** Prepare to read events after polling file descriptor * * \param display The display context object * \return 0 on success or -1 if event queue was not empty * - * This function does the same thing as wl_display_prepare_read_queue() - * with the default queue passed as the queue. + * This function must be called before reading from the file + * descriptor using wl_display_read_events(). Calling + * wl_display_prepare_read() announces the calling threads intention + * to read and ensures that until the thread is ready to read and + * calls wl_display_read_events(), no other thread will read from the + * file descriptor. This only succeeds if the event queue is empty + * though, and if there are undispatched events in the queue, -1 is + * returned and errno set to EAGAIN. + * + * If a thread successfully calls wl_display_prepare_read(), it must + * either call wl_display_read_events() when it's ready or cancel the + * read intention by calling wl_display_cancel_read(). + * + * Use this function before polling on the display fd or to integrate + * the fd into a toolkit event loop in a race-free way. Typically, a + * toolkit will call wl_display_dispatch_pending() before sleeping, to + * make sure it doesn't block with unhandled events. Upon waking up, + * it will assume the file descriptor is readable and read events from + * the fd by calling wl_display_dispatch(). Simplified, we have: + * + * wl_display_dispatch_pending(display); + * wl_display_flush(display); + * poll(fds, nfds, -1); + * wl_display_dispatch(display); + * + * There are two races here: first, before blocking in poll(), the fd + * could become readable and another thread reads the events. Some of + * these events may be for the main queue and the other thread will + * queue them there and then the main thread will go to sleep in + * poll(). This will stall the application, which could be waiting + * for a event to kick of the next animation frame, for example. + * + * The other race is immediately after poll(), where another thread + * could preempt and read events before the main thread calls + * wl_display_dispatch(). This call now blocks and starves the other + * fds in the event loop. + * + * A correct sequence would be: + * + * while (wl_display_prepare_read(display) != 0) + * wl_display_dispatch_pending(display); + * wl_display_flush(display); + * poll(fds, nfds, -1); + * wl_display_read_events(display); + * wl_display_dispatch_pending(display); + * + * Here we call wl_display_prepare_read(), which ensures that between + * returning from that call and eventually calling + * wl_display_read_events(), no other thread will read from the fd and + * queue events in our queue. If the call to + * wl_display_prepare_read() fails, we dispatch the pending events and + * try again until we're successful. * - * \sa wl_display_prepare_read_queue * \memberof wl_display */ WL_EXPORT int @@ -2008,15 +1345,13 @@ wl_display_prepare_read(struct wl_display *display) return wl_display_prepare_read_queue(display, &display->default_queue); } -/** Cancel read intention on display's fd +/** Release exclusive access to display file descriptor * * \param display The display context object * - * After a thread successfully called wl_display_prepare_read() it must - * either call wl_display_read_events() or wl_display_cancel_read(). - * If the threads do not follow this rule it will lead to deadlock. - * - * \sa wl_display_prepare_read(), wl_display_read_events() + * This releases the exclusive access. Useful for canceling the lock + * when a timed out poll returns fd not readable and we're not going + * to read from the fd anytime soon. * * \memberof wl_display */ @@ -2025,184 +1360,26 @@ wl_display_cancel_read(struct wl_display *display) { pthread_mutex_lock(&display->mutex); - cancel_read(display); + display->reader_count--; + if (display->reader_count == 0) + display_wakeup_threads(display); pthread_mutex_unlock(&display->mutex); } -static int -wl_display_poll(struct wl_display *display, - short int events, - const struct timespec *timeout) -{ - int ret; - struct pollfd pfd[1]; - struct timespec now; - struct timespec deadline = {0}; - struct timespec result; - struct timespec *remaining_timeout = NULL; - - if (timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_add(&deadline, &now, timeout); - } - - pfd[0].fd = display->fd; - pfd[0].events = events; - do { - if (timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_sub_saturate(&result, &deadline, &now); - remaining_timeout = &result; - } - ret = ppoll(pfd, 1, remaining_timeout, NULL); - } while (ret == -1 && errno == EINTR); - - return ret; -} - -/** Dispatch events in an event queue with a timeout - * - * \param display The display context object - * \param queue The event queue to dispatch - * \param timeout A timeout describing how long the call should block trying to - * dispatch events - * \return The number of dispatched events on success, -1 on failure - * - * This function behaves identical to wl_display_dispatch_queue() except - * that it also takes a timeout and returns 0 if the timeout elapsed. - * - * Passing NULL as a timeout means an infinite timeout. An empty timespec - * causes wl_display_dispatch_queue_timeout() to return immediately even if no - * events have been dispatched. - * - * If a timeout is passed to wl_display_dispatch_queue_timeout() it is updated - * to the remaining time. - * - * \sa wl_display_dispatch_queue() - * - * \memberof wl_display - */ -WL_EXPORT int -wl_display_dispatch_queue_timeout(struct wl_display *display, - struct wl_event_queue *queue, - const struct timespec *timeout) -{ - int ret; - struct timespec now; - struct timespec deadline = {0}; - struct timespec result; - struct timespec *remaining_timeout = NULL; - - if (timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_add(&deadline, &now, timeout); - } - - if (wl_display_prepare_read_queue(display, queue) == -1) - return wl_display_dispatch_queue_pending(display, queue); - - while (true) { - ret = wl_display_flush(display); - - if (ret != -1 || errno != EAGAIN) - break; - - if (timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_sub_saturate(&result, &deadline, &now); - remaining_timeout = &result; - } - ret = wl_display_poll(display, POLLOUT, remaining_timeout); - - if (ret <= 0) { - wl_display_cancel_read(display); - return ret; - } - } - - /* Don't stop if flushing hits an EPIPE; continue so we can read any - * protocol error that may have triggered it. */ - if (ret < 0 && errno != EPIPE) { - wl_display_cancel_read(display); - return -1; - } - - while (true) { - if (timeout) { - clock_gettime(CLOCK_MONOTONIC, &now); - timespec_sub_saturate(&result, &deadline, &now); - remaining_timeout = &result; - } - - ret = wl_display_poll(display, POLLIN, remaining_timeout); - if (ret <= 0) { - wl_display_cancel_read(display); - break; - } - - ret = wl_display_read_events(display); - if (ret == -1) - break; - - ret = wl_display_dispatch_queue_pending(display, queue); - if (ret != 0) - break; - - /* We managed to read data from the display but there is no - * complete event to dispatch yet. Try reading again. */ - if (wl_display_prepare_read_queue(display, queue) == -1) - return wl_display_dispatch_queue_pending(display, queue); - } - - return ret; -} - -WL_EXPORT int -wl_display_dispatch_timeout(struct wl_display *display, - const struct timespec *timeout) -{ - return wl_display_dispatch_queue_timeout(display, - &display->default_queue, - timeout); -} - /** Dispatch events in an event queue * * \param display The display context object * \param queue The event queue to dispatch * \return The number of dispatched events on success or -1 on failure * - * Dispatch events on the given event queue. + * Dispatch all incoming events for objects assigned to the given + * event queue. On failure -1 is returned and errno set appropriately. * - * If the given event queue is empty, this function blocks until there are - * events to be read from the display fd. Events are read and queued on - * the appropriate event queues. Finally, events on given event queue are - * dispatched. On failure -1 is returned and errno set appropriately. - * - * In a multi threaded environment, do not manually wait using poll() (or - * equivalent) before calling this function, as doing so might cause a dead - * lock. If external reliance on poll() (or equivalent) is required, see - * wl_display_prepare_read_queue() of how to do so. - * - * This function is thread safe as long as it dispatches the right queue on the - * right thread. It is also compatible with the multi thread event reading - * preparation API (see wl_display_prepare_read_queue()), and uses the - * equivalent functionality internally. It is not allowed to call this function - * while the thread is being prepared for reading events, and doing so will - * cause a dead lock. - * - * It can be used as a helper function to ease the procedure of reading and - * dispatching events. - * - * \note Since Wayland 1.5 the display has an extra queue - * for its own events (i. e. delete_id). This queue is dispatched always, - * no matter what queue we passed as an argument to this function. - * That means that this function can return even when it has not dispatched any - * event for the given queue. - * - * \sa wl_display_dispatch(), wl_display_dispatch_pending(), - * wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue() + * This function blocks if there are no events to dispatch. If calling from + * the main thread, it will block reading data from the display fd. For other + * threads this will block until the main thread queues events on the queue + * passed as argument. * * \memberof wl_display */ @@ -2210,12 +1387,60 @@ WL_EXPORT int wl_display_dispatch_queue(struct wl_display *display, struct wl_event_queue *queue) { + struct pollfd pfd[2]; int ret; - ret = wl_display_dispatch_queue_timeout(display, queue, NULL); - assert(ret == -1 || ret > 0); + pthread_mutex_lock(&display->mutex); + + ret = dispatch_queue(display, queue); + if (ret == -1) + goto err_unlock; + if (ret > 0) { + pthread_mutex_unlock(&display->mutex); + return ret; + } + + /* We ignore EPIPE here, so that we try to read events before + * returning an error. When the compositor sends an error it + * will close the socket, and if we bail out here we don't get + * a chance to process the error. */ + ret = wl_connection_flush(display->connection); + if (ret < 0 && errno != EAGAIN && errno != EPIPE) { + display_fatal_error(display, errno); + goto err_unlock; + } + + display->reader_count++; + + pthread_mutex_unlock(&display->mutex); + + pfd[0].fd = display->fd; + pfd[0].events = POLLIN; + do { + ret = poll(pfd, 1, -1); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + wl_display_cancel_read(display); + return -1; + } + + pthread_mutex_lock(&display->mutex); + + if (read_events(display) == -1) + goto err_unlock; + + ret = dispatch_queue(display, queue); + if (ret == -1) + goto err_unlock; + + pthread_mutex_unlock(&display->mutex); return ret; + + err_unlock: + pthread_mutex_unlock(&display->mutex); + return -1; } /** Dispatch pending events in an event queue @@ -2246,64 +1471,26 @@ wl_display_dispatch_queue_pending(struct wl_display *display, return ret; } -/** Dispatch at most one pending event in an event queue - * - * \param display The display context object - * \param queue The event queue to dispatch - * \return The number of dispatched events (0 or 1) on success or -1 on failure - * - * Dispatch at most one pending event for objects assigned to the given - * event queue. On failure -1 is returned and errno set appropriately. - * If there are no events queued, this function returns immediately. - * - * \memberof wl_display - * \since 1.25.0 - */ -WL_EXPORT int -wl_display_dispatch_queue_pending_single(struct wl_display *display, - struct wl_event_queue *queue) -{ - int ret; - - pthread_mutex_lock(&display->mutex); - - ret = dispatch_queue_single(display, queue); - - pthread_mutex_unlock(&display->mutex); - - return ret; -} - /** Process incoming events * * \param display The display context object * \return The number of dispatched events on success or -1 on failure * - * Dispatch events on the default event queue. + * Dispatch the display's main event queue. * - * If the default event queue is empty, this function blocks until there are + * If the main event queue is empty, this function blocks until there are * events to be read from the display fd. Events are read and queued on - * the appropriate event queues. Finally, events on the default event queue - * are dispatched. On failure -1 is returned and errno set appropriately. + * the appropriate event queues. Finally, events on the main event queue + * are dispatched. * - * In a multi threaded environment, do not manually wait using poll() (or - * equivalent) before calling this function, as doing so might cause a dead - * lock. If external reliance on poll() (or equivalent) is required, see - * wl_display_prepare_read_queue() of how to do so. - * - * This function is thread safe as long as it dispatches the right queue on the - * right thread. It is also compatible with the multi thread event reading - * preparation API (see wl_display_prepare_read_queue()), and uses the - * equivalent functionality internally. It is not allowed to call this function - * while the thread is being prepared for reading events, and doing so will - * cause a dead lock. - * - * \note It is not possible to check if there are events on the queue - * or not. For dispatching default queue events without blocking, see \ref + * \note It is not possible to check if there are events on the main queue + * or not. For dispatching main queue events without blocking, see \ref * wl_display_dispatch_pending(). * - * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue(), - * wl_display_read_events() + * \note Calling this will release the display file descriptor if this + * thread acquired it using wl_display_acquire_fd(). + * + * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue() * * \memberof wl_display */ @@ -2313,7 +1500,7 @@ wl_display_dispatch(struct wl_display *display) return wl_display_dispatch_queue(display, &display->default_queue); } -/** Dispatch default queue events without reading from the display fd +/** Dispatch main queue events without reading from the display fd * * \param display The display context object * \return The number of dispatched events or -1 on failure @@ -2322,6 +1509,30 @@ wl_display_dispatch(struct wl_display *display) * attempt to read the display fd and simply returns zero if the main * queue is empty, i.e., it doesn't block. * + * This is necessary when a client's main loop wakes up on some fd other + * than the display fd (network socket, timer fd, etc) and calls \ref + * wl_display_dispatch_queue() from that callback. This may queue up + * events in the main queue while reading all data from the display fd. + * When the main thread returns to the main loop to block, the display fd + * no longer has data, causing a call to \em poll(2) (or similar + * functions) to block indefinitely, even though there are events ready + * to dispatch. + * + * To proper integrate the wayland display fd into a main loop, the + * client should always call \ref wl_display_dispatch_pending() and then + * \ref wl_display_flush() prior to going back to sleep. At that point, + * the fd typically doesn't have data so attempting I/O could block, but + * events queued up on the main queue should be dispatched. + * + * A real-world example is a main loop that wakes up on a timerfd (or a + * sound card fd becoming writable, for example in a video player), which + * then triggers GL rendering and eventually eglSwapBuffers(). + * eglSwapBuffers() may call wl_display_dispatch_queue() if it didn't + * receive the frame event for the previous frame, and as such queue + * events in the main queue. + * + * \note Calling this makes the current thread the main one. + * * \sa wl_display_dispatch(), wl_display_dispatch_queue(), * wl_display_flush() * @@ -2334,25 +1545,6 @@ wl_display_dispatch_pending(struct wl_display *display) &display->default_queue); } -/** Dispatch at most one pending event in the default event queue. - * - * \param display The display context object - * \return The number of dispatched events (0 or 1) on success or -1 on failure - * - * Dispatch at most one pending event for objects assigned to the default - * event queue. On failure -1 is returned and errno set appropriately. - * If there are no events queued, this function returns immediately. - * - * \memberof wl_display - * \since 1.25.0 - */ -WL_EXPORT int -wl_display_dispatch_pending_single(struct wl_display *display) -{ - return wl_display_dispatch_queue_pending_single(display, - &display->default_queue); -} - /** Retrieve the last error that occurred on a display * * \param display The display context object @@ -2380,15 +1572,14 @@ wl_display_get_error(struct wl_display *display) return ret; } -/** Retrieves the information about a protocol error: +/** + * Retrieves the information about a protocol error: * * \param display The Wayland display - * \param interface if not NULL, stores the interface where the error occurred, - * or NULL, if unknown. + * \param interface if not NULL, stores the interface where the error occurred * \param id if not NULL, stores the object id that generated - * the error, or 0, if the object id is unknown. There's no - * guarantee the object is still valid; the client must know - * if it deleted the object. + * the error. There's no guarantee the object is + * still valid; the client must know if it deleted the object. * \return The error code as defined in the interface specification. * * \code @@ -2400,8 +1591,8 @@ wl_display_get_error(struct wl_display *display) * } * * ... - * \endcode - * \memberof wl_display + * + * \endcode */ WL_EXPORT uint32_t wl_display_get_protocol_error(struct wl_display *display, @@ -2430,10 +1621,10 @@ wl_display_get_protocol_error(struct wl_display *display, * \param display The display context object * \return The number of bytes sent on success or -1 on failure * - * Send all buffered data on the client side to the server. Clients should - * always call this function before blocking on input from the display fd. - * On success, the number of bytes sent to the server is returned. On - * failure, this function returns -1 and errno is set appropriately. + * Send all buffered data on the client side to the server. Clients + * should call this function before blocking. On success, the number + * of bytes sent to the server is returned. On failure, this + * function returns -1 and errno is set appropriately. * * wl_display_flush() never blocks. It will write as much data as * possible, but if all data could not be written, errno will be set @@ -2453,12 +1644,8 @@ wl_display_flush(struct wl_display *display) errno = display->last_error; ret = -1; } else { - /* We don't make EPIPE a fatal error here, so that we may try to - * read events after the failed flush. When the compositor sends - * an error it will close the socket, and if we make EPIPE fatal - * here we don't get a chance to process the error. */ ret = wl_connection_flush(display->connection); - if (ret < 0 && errno != EAGAIN && errno != EPIPE) + if (ret < 0 && errno != EAGAIN) display_fatal_error(display, errno); } @@ -2467,32 +1654,6 @@ wl_display_flush(struct wl_display *display) return ret; } -/** Adjust the maximum size of the client connection buffers - * - * \param display The display context object - * \param max_buffer_size The maximum size of the connection buffers - * - * Client buffers are unbounded by default. This function sets a limit to the - * size of the connection buffers. - * - * A value of 0 for \a max_buffer_size requests the buffers to be unbounded. - * - * The actual size of the connection buffers is a power of two, the requested - * \a max_buffer_size is therefore rounded up to the nearest power of two value. - * - * Lowering the maximum size may not take effect immediately if the current - * content of the buffer does not fit within the new size limit. - * - * \memberof wl_display - * \since 1.22.90 - */ -WL_EXPORT void -wl_display_set_max_buffer_size(struct wl_display *display, - size_t max_buffer_size) -{ - wl_connection_set_max_buffer_size(display->connection, max_buffer_size); -} - /** Set the user data associated with a proxy * * \param proxy The proxy object @@ -2522,28 +1683,6 @@ wl_proxy_get_user_data(struct wl_proxy *proxy) return proxy->user_data; } -/** Get the protocol object version of a proxy object - * - * \param proxy The proxy object - * \return The protocol object version of the proxy or 0 - * - * Gets the protocol object version of a proxy object, or 0 - * if the proxy was created with unversioned API. - * - * A returned value of 0 means that no version information is - * available, so the caller must make safe assumptions about - * the object's real version. - * - * wl_display's version will always return 0. - * - * \memberof wl_proxy - */ -WL_EXPORT uint32_t -wl_proxy_get_version(struct wl_proxy *proxy) -{ - return proxy->version; -} - /** Get the id of a proxy object * * \param proxy The proxy object @@ -2557,70 +1696,6 @@ wl_proxy_get_id(struct wl_proxy *proxy) return proxy->object.id; } -/** Set the tag of a proxy object - * - * A toolkit or application can set a unique tag on a proxy in order to - * identify whether an object is managed by itself or some external part. - * - * To create a tag, the recommended way is to define a statically allocated - * constant char array containing some descriptive string. The tag will be the - * pointer to the non-const pointer to the beginning of the array. - * - * For example, to define and set a tag on a surface managed by a certain - * subsystem: - * - * static const char *my_tag = "my tag"; - * - * wl_proxy_set_tag((struct wl_proxy *) surface, &my_tag); - * - * Then, in a callback with wl_surface as an argument, in order to check - * whether it's a surface managed by the same subsystem. - * - * const char * const *tag; - * - * tag = wl_proxy_get_tag((struct wl_proxy *) surface); - * if (tag != &my_tag) - * return; - * - * ... - * - * For debugging purposes, a tag should be suitable to be included in a debug - * log entry, e.g. - * - * const char * const *tag; - * - * tag = wl_proxy_get_tag((struct wl_proxy *) surface); - * printf("Got a surface with the tag %p (%s)\n", - * tag, (tag && *tag) ? *tag : ""); - * - * \param proxy The proxy object - * \param tag The tag - * - * \memberof wl_proxy - * \since 1.17.90 - */ -WL_EXPORT void -wl_proxy_set_tag(struct wl_proxy *proxy, - const char * const *tag) -{ - proxy->tag = tag; -} - -/** Get the tag of a proxy object - * - * See wl_proxy_set_tag for details. - * - * \param proxy The proxy object - * - * \memberof wl_proxy - * \since 1.17.90 - */ -WL_EXPORT const char * const * -wl_proxy_get_tag(struct wl_proxy *proxy) -{ - return proxy->tag; -} - /** Get the interface name (class) of a proxy object * * \param proxy The proxy object @@ -2634,57 +1709,13 @@ wl_proxy_get_class(struct wl_proxy *proxy) return proxy->object.interface->name; } -/** Get the interface of a proxy object - * - * \param proxy The proxy object - * \return The interface of the object associated with the proxy - * - * \memberof wl_proxy - * \since 1.24 - */ -WL_EXPORT const struct wl_interface * -wl_proxy_get_interface(struct wl_proxy *proxy) -{ - return proxy->object.interface; -} - -/** Get the display of a proxy object - * - * \param proxy The proxy object - * \return The wl_display the proxy is associated with - * - * \memberof wl_proxy - * \since 1.23 - */ -WL_EXPORT struct wl_display * -wl_proxy_get_display(struct wl_proxy *proxy) -{ - return proxy->display; -} - /** Assign a proxy to an event queue * * \param proxy The proxy object - * \param queue The event queue that will handle this proxy or NULL + * \param queue The event queue that will handle this proxy * * Assign proxy to event queue. Events coming from \c proxy will be - * queued in \c queue from now. If queue is NULL, then the display's - * default queue is set to the proxy. - * - * In order to guarantee proper handing of all events which were queued - * before the queue change takes effect, it is required to dispatch the - * proxy's old event queue after setting a new event queue. - * - * This is particularly important for multi-threaded setups, where it is - * possible for events to be queued to the proxy's old queue from a - * different thread during the invocation of this function. - * - * To ensure that all events for a newly created proxy are dispatched - * on a particular queue, it is necessary to use a proxy wrapper if - * events are read and dispatched on more than one thread. See - * wl_proxy_create_wrapper() for more details. - * - * \note By default, the queue set in proxy is the one inherited from parent. + * queued in \c queue instead of the display's main queue. * * \sa wl_display_dispatch_queue() * @@ -2693,154 +1724,10 @@ wl_proxy_get_display(struct wl_proxy *proxy) WL_EXPORT void wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue) { - pthread_mutex_lock(&proxy->display->mutex); - - wl_list_remove(&proxy->queue_link); - - if (queue) { - if (!(proxy->display == queue->display)) - wl_abort("Proxy and queue point to different " - "wl_displays"); + if (queue) proxy->queue = queue; - } else { - proxy->queue = &proxy->display->default_queue; - } - - wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link); - - pthread_mutex_unlock(&proxy->display->mutex); -} - -/** Get a proxy's event queue - * - * \param proxy The proxy to query - * - * Return the event queue - */ -WL_EXPORT struct wl_event_queue * -wl_proxy_get_queue(const struct wl_proxy *proxy) -{ - return proxy->queue; - -} -/** Get the name of an event queue - * - * \param queue The queue to query - * - * Return the human readable name for the event queue - * - * This may be NULL if no name has been set. - * - * \memberof wl_proxy - */ -WL_EXPORT const char * -wl_event_queue_get_name(const struct wl_event_queue *queue) -{ - return queue->name; -} - -/** Create a proxy wrapper for making queue assignments thread-safe - * - * \param proxy The proxy object to be wrapped - * \return A proxy wrapper for the given proxy or NULL on failure - * - * A proxy wrapper is type of 'struct wl_proxy' instance that can be used when - * sending requests instead of using the original proxy. A proxy wrapper does - * not have an implementation or dispatcher, and events received on the - * object is still emitted on the original proxy. Trying to set an - * implementation or dispatcher will have no effect but result in a warning - * being logged. - * - * Setting the proxy queue of the proxy wrapper will make new objects created - * using the proxy wrapper use the set proxy queue. - * Even though there is no implementation nor dispatcher, the proxy queue can - * be changed. This will affect the default queue of new objects created by - * requests sent via the proxy wrapper. - * - * A proxy wrapper can only be destroyed using wl_proxy_wrapper_destroy(). - * - * A proxy wrapper must be destroyed before the proxy it was created from. - * - * If a user reads and dispatches events on more than one thread, it is - * necessary to use a proxy wrapper when sending requests on objects when the - * intention is that a newly created proxy is to use a proxy queue different - * from the proxy the request was sent on, as creating the new proxy and then - * setting the queue is not thread safe. - * - * For example, a module that runs using its own proxy queue that needs to - * do display roundtrip must wrap the wl_display proxy object before sending - * the wl_display.sync request. For example: - * - * \code - * - * struct wl_event_queue *queue = ...; - * struct wl_display *wrapped_display; - * struct wl_callback *callback; - * - * wrapped_display = wl_proxy_create_wrapper(display); - * wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue); - * callback = wl_display_sync(wrapped_display); - * wl_proxy_wrapper_destroy(wrapped_display); - * wl_callback_add_listener(callback, ...); - * - * \endcode - * - * \memberof wl_proxy - */ -WL_EXPORT void * -wl_proxy_create_wrapper(void *proxy) -{ - struct wl_proxy *wrapped_proxy = proxy; - struct wl_proxy *wrapper; - - wrapper = zalloc(sizeof *wrapper); - if (!wrapper) - return NULL; - - pthread_mutex_lock(&wrapped_proxy->display->mutex); - - wrapper->object.interface = wrapped_proxy->object.interface; - wrapper->object.id = wrapped_proxy->object.id; - wrapper->version = wrapped_proxy->version; - wrapper->display = wrapped_proxy->display; - wrapper->queue = wrapped_proxy->queue; - wrapper->flags = WL_PROXY_FLAG_WRAPPER; - wrapper->refcount = 1; - - if (wrapper->queue != NULL) - wl_list_insert(&wrapper->queue->proxy_list, &wrapper->queue_link); else - wl_list_init(&wrapper->queue_link); - - pthread_mutex_unlock(&wrapped_proxy->display->mutex); - - return wrapper; -} - -/** Destroy a proxy wrapper - * \param proxy_wrapper The proxy wrapper to be destroyed - * - * \memberof wl_proxy - */ -WL_EXPORT void -wl_proxy_wrapper_destroy(void *proxy_wrapper) -{ - struct wl_proxy *wrapper = proxy_wrapper; - - if (!(wrapper->flags & WL_PROXY_FLAG_WRAPPER)) - wl_abort("Tried to destroy non-wrapper proxy with " - "wl_proxy_wrapper_destroy\n"); - - if (!(wrapper->refcount == 1)) - wl_abort("Expected proxy wrapper's refcount to be 1\n"); - - pthread_mutex_lock(&wrapper->display->mutex); - - wl_list_remove(&wrapper->queue_link); - - pthread_mutex_unlock(&wrapper->display->mutex); - - free(wrapper); + proxy->queue = &proxy->display->default_queue; } WL_EXPORT void diff --git a/src/wayland-client.h b/src/wayland-client.h index 9f70fa3f..0801a818 100644 --- a/src/wayland-client.h +++ b/src/wayland-client.h @@ -1,42 +1,186 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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: + * 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 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. - */ - -/** \file - * - * \brief Include the client API and protocol C API. - * - * \warning Use of this header file is discouraged. Prefer including - * wayland-client-core.h instead, which does not include the - * client protocol header and as such only defines the library - * API. + * 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 WAYLAND_CLIENT_H #define WAYLAND_CLIENT_H -#include "wayland-client-core.h" +#include "wayland-util.h" +#include "wayland-version.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \class wl_proxy + * + * \brief Represents a protocol object on the client side. + * + * A wl_proxy acts as a client side proxy to an object existing in the + * compositor. The proxy is responsible for converting requests made by the + * clients with \ref wl_proxy_marshal() into Wayland's wire format. Events + * coming from the compositor are also handled by the proxy, which will in + * turn call the handler set with \ref wl_proxy_add_listener(). + * + * \note With the exception of function \ref wl_proxy_set_queue(), functions + * accessing a \ref wl_proxy are not normally used by client code. Clients + * should normally use the higher level interface generated by the scanner to + * interact with compositor objects. + * + */ +struct wl_proxy; + +/** \class wl_display + * + * \brief Represents a connection to the compositor and acts as a proxy to + * the wl_display singleton object. + * + * A \ref wl_display object represents a client connection to a Wayland + * compositor. It is created with either \ref wl_display_connect() or + * \ref wl_display_connect_to_fd(). A connection is terminated using + * \ref wl_display_disconnect(). + * + * A \ref wl_display is also used as the \ref wl_proxy for the \ref wl_display + * singleton object on the compositor side. + * + * A \ref wl_display object handles all the data sent from and to the + * compositor. When a \ref wl_proxy marshals a request, it will write its wire + * representation to the display's write buffer. The data is sent to the + * compositor when the client calls \ref wl_display_flush(). + * + * Incoming data is handled in two steps: queueing and dispatching. In the + * queue step, the data coming from the display fd is interpreted and + * added to a queue. On the dispatch step, the handler for the incoming + * event set by the client on the corresponding \ref wl_proxy is called. + * + * A \ref wl_display has at least one event queue, called the main + * queue. Clients can create additional event queues with \ref + * wl_display_create_queue() and assign \ref wl_proxy's to it. Events + * occurring in a particular proxy are always queued in its assigned queue. + * A client can ensure that a certain assumption, such as holding a lock + * or running from a given thread, is true when a proxy event handler is + * called by assigning that proxy to an event queue and making sure that + * this queue is only dispatched when the assumption holds. + * + * The main queue is dispatched by calling \ref wl_display_dispatch(). + * This will dispatch any events queued on the main queue and attempt + * to read from the display fd if its empty. Events read are then queued + * on the appropriate queues according to the proxy assignment. Calling + * that function makes the calling thread the main thread. + * + * A user created queue is dispatched with \ref wl_display_dispatch_queue(). + * If there are no events to dispatch this function will block. If this + * is called by the main thread, this will attempt to read data from the + * display fd and queue any events on the appropriate queues. If calling + * from any other thread, the function will block until the main thread + * queues an event on the queue being dispatched. + * + * A real world example of event queue usage is Mesa's implementation of + * eglSwapBuffers() for the Wayland platform. This function might need + * to block until a frame callback is received, but dispatching the main + * queue could cause an event handler on the client to start drawing + * again. This problem is solved using another event queue, so that only + * the events handled by the EGL code are dispatched during the block. + * + * This creates a problem where the main thread dispatches a non-main + * queue, reading all the data from the display fd. If the application + * would call \em poll(2) after that it would block, even though there + * might be events queued on the main queue. Those events should be + * dispatched with \ref wl_display_dispatch_pending() before + * flushing and blocking. + */ +struct wl_display; + +/** \class wl_event_queue + * + * \brief A queue for \ref wl_proxy object events. + * + * Event queues allows the events on a display to be handled in a thread-safe + * manner. See \ref wl_display for details. + * + */ +struct wl_event_queue; + +void wl_event_queue_destroy(struct wl_event_queue *queue); + +void wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...); +void wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode, + union wl_argument *args); +struct wl_proxy *wl_proxy_create(struct wl_proxy *factory, + const struct wl_interface *interface); +struct wl_proxy *wl_proxy_marshal_constructor(struct wl_proxy *proxy, + uint32_t opcode, + const struct wl_interface *interface, + ...); +struct wl_proxy * +wl_proxy_marshal_array_constructor(struct wl_proxy *proxy, + uint32_t opcode, union wl_argument *args, + const struct wl_interface *interface); + +void wl_proxy_destroy(struct wl_proxy *proxy); +int wl_proxy_add_listener(struct wl_proxy *proxy, + void (**implementation)(void), void *data); +const void *wl_proxy_get_listener(struct wl_proxy *proxy); +int wl_proxy_add_dispatcher(struct wl_proxy *proxy, + wl_dispatcher_func_t dispatcher_func, + const void * dispatcher_data, void *data); +void wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); +void *wl_proxy_get_user_data(struct wl_proxy *proxy); +uint32_t wl_proxy_get_id(struct wl_proxy *proxy); +const char *wl_proxy_get_class(struct wl_proxy *proxy); +void wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue); + #include "wayland-client-protocol.h" +struct wl_display *wl_display_connect(const char *name); +struct wl_display *wl_display_connect_to_fd(int fd); +void wl_display_disconnect(struct wl_display *display); +int wl_display_get_fd(struct wl_display *display); +int wl_display_dispatch(struct wl_display *display); +int wl_display_dispatch_queue(struct wl_display *display, + struct wl_event_queue *queue); +int wl_display_dispatch_queue_pending(struct wl_display *display, + struct wl_event_queue *queue); +int wl_display_dispatch_pending(struct wl_display *display); +int wl_display_get_error(struct wl_display *display); +uint32_t wl_display_get_protocol_error(struct wl_display *display, + const struct wl_interface **interface, + uint32_t *id); + +int wl_display_flush(struct wl_display *display); +int wl_display_roundtrip_queue(struct wl_display *display, + struct wl_event_queue *queue); +int wl_display_roundtrip(struct wl_display *display); +struct wl_event_queue *wl_display_create_queue(struct wl_display *display); + +int wl_display_prepare_read_queue(struct wl_display *display, + struct wl_event_queue *queue); +int wl_display_prepare_read(struct wl_display *display); +void wl_display_cancel_read(struct wl_display *display); +int wl_display_read_events(struct wl_display *display); + +void wl_log_set_handler_client(wl_log_func_t handler); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/wayland-client.pc.in b/src/wayland-client.pc.in new file mode 100644 index 00000000..eef61da5 --- /dev/null +++ b/src/wayland-client.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +datarootdir=@datarootdir@ +pkgdatadir=@datadir@/@PACKAGE@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Wayland Client +Description: Wayland client side library +Version: @WAYLAND_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lwayland-client diff --git a/src/wayland-egl.h b/src/wayland-egl.h new file mode 100644 index 00000000..c40280b1 --- /dev/null +++ b/src/wayland-egl.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * Copyright © 2011 Benjamin Franzke + * + * 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 WAYLAND_EGL_H +#define WAYLAND_EGL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define WL_EGL_PLATFORM 1 + +struct wl_egl_window; + +struct wl_egl_window * +wl_egl_window_create(struct wl_surface *surface, + int width, int height); + +void +wl_egl_window_destroy(struct wl_egl_window *egl_window); + +void +wl_egl_window_resize(struct wl_egl_window *egl_window, + int width, int height, + int dx, int dy); + +void +wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, + int *width, int *height); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/wayland-os.c b/src/wayland-os.c index f00ead4b..1185e1db 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -1,53 +1,37 @@ /* * Copyright © 2012 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: + * 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 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. + * 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. */ #define _GNU_SOURCE -#include "../config.h" - #include #include #include #include #include -#include #include -#include -#include -#ifdef HAVE_SYS_UCRED_H -#include -#endif +#include "../config.h" #include "wayland-os.h" -/* used by tests */ -int (*wl_fcntl)(int fildes, int cmd, ...) = fcntl; -int (*wl_socket)(int domain, int type, int protocol) = socket; -ssize_t (*wl_recvmsg)(int socket, struct msghdr *message, int flags) = recvmsg; -int (*wl_epoll_create1)(int flags) = epoll_create1; - static int set_cloexec_or_close(int fd) { @@ -56,11 +40,11 @@ set_cloexec_or_close(int fd) if (fd == -1) return -1; - flags = wl_fcntl(fd, F_GETFD); + flags = fcntl(fd, F_GETFD); if (flags == -1) goto err; - if (wl_fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) goto err; return fd; @@ -75,72 +59,28 @@ wl_os_socket_cloexec(int domain, int type, int protocol) { int fd; - fd = wl_socket(domain, type | SOCK_CLOEXEC, protocol); + fd = socket(domain, type | SOCK_CLOEXEC, protocol); if (fd >= 0) return fd; if (errno != EINVAL) return -1; - fd = wl_socket(domain, type, protocol); + fd = socket(domain, type, protocol); return set_cloexec_or_close(fd); } -#if defined(__FreeBSD__) int -wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) -{ - socklen_t len; - struct xucred ucred; - - len = sizeof(ucred); - if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &ucred, &len) < 0 || - ucred.cr_version != XUCRED_VERSION) - return -1; - *uid = ucred.cr_uid; - *gid = ucred.cr_gid; -#if HAVE_XUCRED_CR_PID - /* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */ - *pid = ucred.cr_pid; -#else - *pid = 0; -#endif - return 0; -} -#elif defined(SO_PEERCRED) -int -wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) -{ - socklen_t len; -#if defined(__OpenBSD__) - struct sockpeercred ucred; -#else - struct ucred ucred; -#endif - - len = sizeof(ucred); - if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) - return -1; - *uid = ucred.uid; - *gid = ucred.gid; - *pid = ucred.pid; - return 0; -} -#else -#error "Don't know how to read ucred on this platform" -#endif - -int -wl_os_dupfd_cloexec(int fd, int minfd) +wl_os_dupfd_cloexec(int fd, long minfd) { int newfd; - newfd = wl_fcntl(fd, F_DUPFD_CLOEXEC, minfd); + newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd); if (newfd >= 0) return newfd; if (errno != EINVAL) return -1; - newfd = wl_fcntl(fd, F_DUPFD, minfd); + newfd = fcntl(fd, F_DUPFD, minfd); return set_cloexec_or_close(newfd); } @@ -153,7 +93,7 @@ recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags) int *fd; int *end; - len = wl_recvmsg(sockfd, msg, flags); + len = recvmsg(sockfd, msg, flags); if (len == -1) return -1; @@ -178,23 +118,14 @@ recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags) ssize_t wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) { -#if HAVE_BROKEN_MSG_CMSG_CLOEXEC - /* - * FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015 - * and 2021, so we have to use the non-MSG_CMSG_CLOEXEC fallback - * directly when compiling against a version that does not include the - * fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211). - */ -#pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.") -#else ssize_t len; - len = wl_recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); + len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); if (len >= 0) return len; if (errno != EINVAL) return -1; -#endif + return recvmsg_cloexec_fallback(sockfd, msg, flags); } @@ -204,7 +135,7 @@ wl_os_epoll_create_cloexec(void) int fd; #ifdef EPOLL_CLOEXEC - fd = wl_epoll_create1(EPOLL_CLOEXEC); + fd = epoll_create1(EPOLL_CLOEXEC); if (fd >= 0) return fd; if (errno != EINVAL) @@ -231,32 +162,3 @@ wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) fd = accept(sockfd, addr, addrlen); return set_cloexec_or_close(fd); } - -/* - * Fallback function for operating systems that don't implement - * mremap(MREMAP_MAYMOVE). - */ -void * -wl_os_mremap_maymove(int fd, void *old_data, ssize_t *old_size, - ssize_t new_size, int prot, int flags) -{ - void *result; - - /* Make sure any pending write is flushed. */ - if (msync(old_data, *old_size, MS_SYNC) != 0) - return MAP_FAILED; - - /* We could try mapping a new block immediately after the current one - * with MAP_FIXED, however that is not guaranteed to work and breaks - * on CHERI-enabled architectures since the data pointer will still - * have the bounds of the previous allocation. - */ - result = mmap(NULL, new_size, prot, flags, fd, 0); - if (result == MAP_FAILED) - return MAP_FAILED; - - if (munmap(old_data, *old_size) == 0) - *old_size = 0; - - return result; -} diff --git a/src/wayland-os.h b/src/wayland-os.h index 068fd2fe..c612975d 100644 --- a/src/wayland-os.h +++ b/src/wayland-os.h @@ -1,42 +1,33 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 WAYLAND_OS_H #define WAYLAND_OS_H -#include -#include - int wl_os_socket_cloexec(int domain, int type, int protocol); int -wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid); - -int -wl_os_dupfd_cloexec(int fd, int minfd); +wl_os_dupfd_cloexec(int fd, long minfd); ssize_t wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); @@ -47,10 +38,6 @@ wl_os_epoll_create_cloexec(void); int wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen); -void * -wl_os_mremap_maymove(int fd, void *old_data, ssize_t *old_size, - ssize_t new_size, int prot, int flags); - /* * The following are for wayland-os.c and the unit tests. diff --git a/src/wayland-private.h b/src/wayland-private.h index d0e4cfc6..67e87830 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -3,77 +3,44 @@ * Copyright © 2011 Intel Corporation * Copyright © 2013 Jason Ekstrand * - * 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: + * 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 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. + * 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 WAYLAND_PRIVATE_H #define WAYLAND_PRIVATE_H #include -#include -#include -#include #define WL_HIDE_DEPRECATED 1 #include "wayland-util.h" -/* Invalid memory address */ -#define WL_ARRAY_POISON_PTR (void *) 4 - #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) );}) + #define WL_MAP_SERVER_SIDE 0 #define WL_MAP_CLIENT_SIDE 1 #define WL_SERVER_ID_START 0xff000000 -#define WL_MAP_MAX_OBJECTS 0x00f00000 #define WL_CLOSURE_MAX_ARGS 20 -#define WL_BUFFER_DEFAULT_SIZE_POT 12 -#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT) -#if WL_BUFFER_DEFAULT_MAX_SIZE < WL_MAX_MESSAGE_SIZE -# error default buffer cannot hold maximum-sized message -#endif - -#define WL_DEBUG_COLOR_RESET "\e[0m" -#define WL_DEBUG_COLOR_RED "\e[31m" -#define WL_DEBUG_COLOR_GREEN "\e[32m" -#define WL_DEBUG_COLOR_YELLOW "\e[33m" -#define WL_DEBUG_COLOR_BLUE "\e[34m" -#define WL_DEBUG_COLOR_MAGENTA "\e[35m" -#define WL_DEBUG_COLOR_CYAN "\e[36m" - -/** - * Argument types used in signatures. - */ -enum wl_arg_type { - WL_ARG_INT = 'i', - WL_ARG_UINT = 'u', - WL_ARG_FIXED = 'f', - WL_ARG_STRING = 's', - WL_ARG_OBJECT = 'o', - WL_ARG_NEW_ID = 'n', - WL_ARG_ARRAY = 'a', - WL_ARG_FD = 'h', -}; struct wl_object { const struct wl_interface *interface; @@ -81,17 +48,15 @@ struct wl_object { uint32_t id; }; -int -wl_interface_equal(const struct wl_interface *iface1, - const struct wl_interface *iface2); +extern struct wl_object global_zombie_object; +#define WL_ZOMBIE_OBJECT ((void*)&global_zombie_object) /* Flags for wl_map_insert_new and wl_map_insert_at. Flags can be queried with * wl_map_lookup_flags. The current implementation has room for 1 bit worth of * flags. If more flags are ever added, the implementation of wl_map will have * to change to allow for new flags */ enum wl_map_entry_flags { - WL_MAP_ENTRY_LEGACY = (1 << 0), /* Server side only */ - WL_MAP_ENTRY_ZOMBIE = (1 << 0) /* Client side only */ + WL_MAP_ENTRY_LEGACY = (1 << 0) }; struct wl_map { @@ -101,68 +66,36 @@ struct wl_map { uint32_t free_list; }; -typedef enum wl_iterator_result (*wl_iterator_func_t)(void *element, - void *data, - uint32_t flags); +typedef void (*wl_iterator_func_t)(void *element, void *data); -void -wl_map_init(struct wl_map *map, uint32_t side); +void wl_map_init(struct wl_map *map, uint32_t side); +void wl_map_release(struct wl_map *map); +uint32_t wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data); +int wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data); +int wl_map_reserve_new(struct wl_map *map, uint32_t i); +void wl_map_remove(struct wl_map *map, uint32_t i); +void *wl_map_lookup(struct wl_map *map, uint32_t i); +uint32_t wl_map_lookup_flags(struct wl_map *map, uint32_t i); +void wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data); -void -wl_map_release(struct wl_map *map); +struct wl_connection; +struct wl_closure; +struct wl_proxy; -uint32_t -wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data); +int wl_interface_equal(const struct wl_interface *iface1, + const struct wl_interface *iface2); -int -wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data); +struct wl_connection *wl_connection_create(int fd); +void wl_connection_destroy(struct wl_connection *connection); +void wl_connection_copy(struct wl_connection *connection, void *data, size_t size); +void wl_connection_consume(struct wl_connection *connection, size_t size); -int -wl_map_reserve_new(struct wl_map *map, uint32_t i); +int wl_connection_flush(struct wl_connection *connection); +int wl_connection_read(struct wl_connection *connection); -void -wl_map_remove(struct wl_map *map, uint32_t i); - -void * -wl_map_lookup(struct wl_map *map, uint32_t i); - -uint32_t -wl_map_lookup_flags(struct wl_map *map, uint32_t i); - -void -wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data); - -struct wl_connection * -wl_connection_create(int fd, size_t max_buffer_size); - -int -wl_connection_destroy(struct wl_connection *connection); - -void -wl_connection_copy(struct wl_connection *connection, void *data, size_t size); - -void -wl_connection_consume(struct wl_connection *connection, size_t size); - -int -wl_connection_flush(struct wl_connection *connection); - -uint32_t -wl_connection_pending_input(struct wl_connection *connection); - -int -wl_connection_read(struct wl_connection *connection); - -int -wl_connection_write(struct wl_connection *connection, - const void *data, size_t count); - -int -wl_connection_queue(struct wl_connection *connection, - const void *data, size_t count); - -int -wl_connection_get_fd(struct wl_connection *connection); +int wl_connection_write(struct wl_connection *connection, const void *data, size_t count); +int wl_connection_queue(struct wl_connection *connection, + const void *data, size_t count); struct wl_closure { int count; @@ -176,7 +109,7 @@ struct wl_closure { }; struct argument_details { - enum wl_arg_type type; + char type; int nullable; }; @@ -186,9 +119,6 @@ get_next_argument(const char *signature, struct argument_details *details); int arg_count_for_signature(const char *signature); -int -wl_message_count_arrays(const struct wl_message *message); - int wl_message_get_since(const struct wl_message *message); @@ -200,7 +130,6 @@ struct wl_closure * wl_closure_marshal(struct wl_object *sender, uint32_t opcode, union wl_argument *args, const struct wl_message *message); - struct wl_closure * wl_closure_vmarshal(struct wl_object *sender, uint32_t opcode, va_list ap, @@ -212,9 +141,6 @@ wl_connection_demarshal(struct wl_connection *connection, struct wl_map *objects, const struct wl_message *message); -bool -wl_object_is_zombie(struct wl_map *map, uint32_t id); - int wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects); @@ -226,50 +152,25 @@ enum wl_closure_invoke_flag { void wl_closure_invoke(struct wl_closure *closure, uint32_t flags, struct wl_object *target, uint32_t opcode, void *data); - void wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher, struct wl_object *target, uint32_t opcode); - int wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); - int wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection); - -bool -wl_check_env_token(const char *env, const char *token); - void -wl_closure_print(struct wl_closure *closure, - struct wl_object *target, int send, int discarded, - uint32_t (*n_parse)(union wl_argument *arg), - const char *queue_name, int color); - +wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send); void wl_closure_destroy(struct wl_closure *closure); extern wl_log_func_t wl_log_handler; void wl_log(const char *fmt, ...); -void wl_abort(const char *fmt, ...); struct wl_display; struct wl_array * wl_display_get_additional_shm_formats(struct wl_display *display); -static inline void * -zalloc(size_t s) -{ - return calloc(1, s); -} - -void -wl_connection_close_fds_in(struct wl_connection *connection, int max); - -void -wl_connection_set_max_buffer_size(struct wl_connection *connection, - size_t max_buffer_size); - #endif diff --git a/src/wayland-scanner-uninstalled.pc.in b/src/wayland-scanner-uninstalled.pc.in new file mode 100644 index 00000000..8dcfef31 --- /dev/null +++ b/src/wayland-scanner-uninstalled.pc.in @@ -0,0 +1,6 @@ +pkgdatadir=@abs_top_srcdir@ +wayland_scanner=@abs_builddir@/wayland-scanner + +Name: Wayland Scanner +Description: Wayland scanner (not installed) +Version: @PACKAGE_VERSION@ diff --git a/src/wayland-scanner.pc.in b/src/wayland-scanner.pc.in new file mode 100644 index 00000000..7b2a4c92 --- /dev/null +++ b/src/wayland-scanner.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +datarootdir=@datarootdir@ +pkgdatadir=@datadir@/@PACKAGE@ +wayland_scanner=@bindir@/wayland-scanner + +Name: Wayland Scanner +Description: Wayland scanner +Version: @WAYLAND_VERSION@ diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h deleted file mode 100644 index cc08de58..00000000 --- a/src/wayland-server-core.h +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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. - */ - -#ifndef WAYLAND_SERVER_CORE_H -#define WAYLAND_SERVER_CORE_H - -#include -#include -#include -#include "wayland-util.h" -#include "wayland-version.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - WL_EVENT_READABLE = 0x01, - WL_EVENT_WRITABLE = 0x02, - WL_EVENT_HANGUP = 0x04, - WL_EVENT_ERROR = 0x08 -}; - -/** File descriptor dispatch function type - * - * Functions of this type are used as callbacks for file descriptor events. - * - * \param fd The file descriptor delivering the event. - * \param mask Describes the kind of the event as a bitwise-or of: - * \c WL_EVENT_READABLE, \c WL_EVENT_WRITABLE, \c WL_EVENT_HANGUP, - * \c WL_EVENT_ERROR. - * \param data The user data argument of the related wl_event_loop_add_fd() - * call. - * \return If the event source is registered for re-check with - * wl_event_source_check(): 0 for all done, 1 for needing a re-check. - * If not registered, the return value is ignored and should be zero. - * - * \sa wl_event_loop_add_fd() - * \memberof wl_event_source - */ -typedef int (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data); - -/** Timer dispatch function type - * - * Functions of this type are used as callbacks for timer expiry. - * - * \param data The user data argument of the related wl_event_loop_add_timer() - * call. - * \return If the event source is registered for re-check with - * wl_event_source_check(): 0 for all done, 1 for needing a re-check. - * If not registered, the return value is ignored and should be zero. - * - * \sa wl_event_loop_add_timer() - * \memberof wl_event_source - */ -typedef int (*wl_event_loop_timer_func_t)(void *data); - -/** Signal dispatch function type - * - * Functions of this type are used as callbacks for (POSIX) signals. - * - * \param signal_number - * \param data The user data argument of the related wl_event_loop_add_signal() - * call. - * \return If the event source is registered for re-check with - * wl_event_source_check(): 0 for all done, 1 for needing a re-check. - * If not registered, the return value is ignored and should be zero. - * - * \sa wl_event_loop_add_signal() - * \memberof wl_event_source - */ -typedef int (*wl_event_loop_signal_func_t)(int signal_number, void *data); - -/** Idle task function type - * - * Functions of this type are used as callbacks before blocking in - * wl_event_loop_dispatch(). - * - * \param data The user data argument of the related wl_event_loop_add_idle() - * call. - * - * \sa wl_event_loop_add_idle() wl_event_loop_dispatch() - * \memberof wl_event_source - */ -typedef void (*wl_event_loop_idle_func_t)(void *data); - -/** \struct wl_event_loop - * - * \brief An event loop context - * - * Usually you create an event loop context, add sources to it, and call - * wl_event_loop_dispatch() in a loop to process events. - * - * \sa wl_event_source - */ - -/** \struct wl_event_source - * - * \brief An abstract event source - * - * This is the generic type for fd, timer, signal, and idle sources. - * Functions that operate on specific source types must not be used with - * a different type, even if the function signature allows it. - */ - -struct wl_event_loop * -wl_event_loop_create(void); - -void -wl_event_loop_destroy(struct wl_event_loop *loop); - -struct wl_event_source * -wl_event_loop_add_fd(struct wl_event_loop *loop, - int fd, uint32_t mask, - wl_event_loop_fd_func_t func, - void *data); - -int -wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask); - -struct wl_event_source * -wl_event_loop_add_timer(struct wl_event_loop *loop, - wl_event_loop_timer_func_t func, - void *data); - -struct wl_event_source * -wl_event_loop_add_signal(struct wl_event_loop *loop, - int signal_number, - wl_event_loop_signal_func_t func, - void *data); - -int -wl_event_source_timer_update(struct wl_event_source *source, - int ms_delay); - -int -wl_event_source_remove(struct wl_event_source *source); - -void -wl_event_source_check(struct wl_event_source *source); - -int -wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout); - -void -wl_event_loop_dispatch_idle(struct wl_event_loop *loop); - -struct wl_event_source * -wl_event_loop_add_idle(struct wl_event_loop *loop, - wl_event_loop_idle_func_t func, - void *data); - -int -wl_event_loop_get_fd(struct wl_event_loop *loop); - -struct wl_listener; - -typedef void (*wl_notify_func_t)(struct wl_listener *listener, void *data); - -void -wl_event_loop_add_destroy_listener(struct wl_event_loop *loop, - struct wl_listener *listener); - -struct wl_listener * -wl_event_loop_get_destroy_listener(struct wl_event_loop *loop, - wl_notify_func_t notify); - -struct wl_display * -wl_display_create(void); - -void -wl_display_destroy(struct wl_display *display); - -struct wl_event_loop * -wl_display_get_event_loop(struct wl_display *display); - -int -wl_display_add_socket(struct wl_display *display, const char *name); - -const char * -wl_display_add_socket_auto(struct wl_display *display); - -int -wl_display_add_socket_fd(struct wl_display *display, int sock_fd); - -void -wl_display_terminate(struct wl_display *display); - -void -wl_display_run(struct wl_display *display); - -void -wl_display_flush_clients(struct wl_display *display); - -void -wl_display_destroy_clients(struct wl_display *display); - -void -wl_display_set_default_max_buffer_size(struct wl_display *display, - size_t max_buffer_size); - -struct wl_client; -struct wl_global; - -typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data, - uint32_t version, uint32_t id); - -typedef void (*wl_global_withdrawn_func_t)(struct wl_global *global); - -uint32_t -wl_display_get_serial(const struct wl_display *display); - -uint32_t -wl_display_next_serial(struct wl_display *display); - -void -wl_display_add_destroy_listener(struct wl_display *display, - struct wl_listener *listener); - -void -wl_display_add_client_created_listener(struct wl_display *display, - struct wl_listener *listener); - -struct wl_listener * -wl_display_get_destroy_listener(struct wl_display *display, - wl_notify_func_t notify); - -struct wl_global * -wl_global_create(struct wl_display *display, - const struct wl_interface *interface, - int version, - void *data, wl_global_bind_func_t bind); - -void -wl_global_remove(struct wl_global *global); - -void -wl_global_set_withdrawn_listener(struct wl_global *global, - wl_global_withdrawn_func_t func); - -void -wl_global_destroy(struct wl_global *global); - -/** A filter function for wl_global objects - * - * \param client The client object - * \param global The global object to show or hide - * \param data The user data pointer - * - * A filter function enables the server to decide which globals to - * advertise to each client. - * - * When a wl_global filter is set, the given callback function will be - * called during wl_global advertisement and binding. - * - * This function should return true if the global object should be made - * visible to the client or false otherwise. - */ -typedef bool (*wl_display_global_filter_func_t)(const struct wl_client *client, - const struct wl_global *global, - void *data); - -void -wl_display_set_global_filter(struct wl_display *display, - wl_display_global_filter_func_t filter, - void *data); - -const struct wl_interface * -wl_global_get_interface(const struct wl_global *global); - -uint32_t -wl_global_get_name(const struct wl_global *global, - const struct wl_client *client); - -uint32_t -wl_global_get_version(const struct wl_global *global); - -struct wl_display * -wl_global_get_display(const struct wl_global *global); - -void * -wl_global_get_user_data(const struct wl_global *global); - -void -wl_global_set_user_data(struct wl_global *global, void *data); - -struct wl_client * -wl_client_create(struct wl_display *display, int fd); - -struct wl_list * -wl_display_get_client_list(struct wl_display *display); - -struct wl_list * -wl_client_get_link(struct wl_client *client); - -struct wl_client * -wl_client_from_link(struct wl_list *link); - -/** Iterate over a list of clients. */ -#define wl_client_for_each(client, list) \ - for (client = wl_client_from_link((list)->next); \ - wl_client_get_link(client) != (list); \ - client = wl_client_from_link(wl_client_get_link(client)->next)) - -void -wl_client_destroy(struct wl_client *client); - -void -wl_client_flush(struct wl_client *client); - -void -wl_client_get_credentials(const struct wl_client *client, - pid_t *pid, uid_t *uid, gid_t *gid); - -int -wl_client_get_fd(struct wl_client *client); - -void -wl_client_add_destroy_listener(struct wl_client *client, - struct wl_listener *listener); - -struct wl_listener * -wl_client_get_destroy_listener(struct wl_client *client, - wl_notify_func_t notify); - -void -wl_client_add_destroy_late_listener(struct wl_client *client, - struct wl_listener *listener); - -struct wl_listener * -wl_client_get_destroy_late_listener(struct wl_client *client, - wl_notify_func_t notify); - -struct wl_resource * -wl_client_get_object(struct wl_client *client, uint32_t id); - -void -wl_client_post_no_memory(struct wl_client *client); - -void -wl_client_post_implementation_error(struct wl_client *client, - const char* msg, ...) WL_PRINTF(2,3); - -void -wl_client_add_resource_created_listener(struct wl_client *client, - struct wl_listener *listener); - -/** Callback function type for wl_client_for_each_resource() */ -typedef enum wl_iterator_result (*wl_client_for_each_resource_iterator_func_t)( - struct wl_resource *resource, - void *user_data); - -void -wl_client_for_each_resource(struct wl_client *client, - wl_client_for_each_resource_iterator_func_t iterator, - void *user_data); - -typedef void (*wl_user_data_destroy_func_t)(void *data); - -void -wl_client_set_user_data(struct wl_client *client, - void *data, - wl_user_data_destroy_func_t dtor); - -void * -wl_client_get_user_data(struct wl_client *client); - -void -wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size); - -/** \class wl_listener - * - * \brief A single listener for Wayland signals - * - * wl_listener provides the means to listen for wl_signal notifications. Many - * Wayland objects use wl_listener for notification of significant events like - * object destruction. - * - * Clients should create wl_listener objects manually and can register them as - * listeners to signals using wl_signal_add(), assuming the signal is - * directly accessible. For opaque structs like wl_event_loop, adding a - * listener should be done through provided accessor methods. A listener can - * only listen to one signal at a time. - * - * \code - * struct wl_listener your_listener; - * - * your_listener.notify = your_callback_method; - * - * // Direct access - * wl_signal_add(&some_object->destroy_signal, &your_listener); - * - * // Accessor access - * wl_event_loop *loop = ...; - * wl_event_loop_add_destroy_listener(loop, &your_listener); - * \endcode - * - * If the listener is part of a larger struct, #wl_container_of can be used - * to retrieve a pointer to it: - * - * \code - * void your_listener(struct wl_listener *listener, void *data) - * { - * struct your_data *data; - * - * your_data = wl_container_of(listener, data, your_member_name); - * } - * \endcode - * - * If you need to remove a listener from a signal, use wl_list_remove(). - * - * \code - * wl_list_remove(&your_listener.link); - * \endcode - * - * \sa wl_signal - */ -struct wl_listener { - /** Part of wl_signal::listener_list */ - struct wl_list link; - - /** Callback function pointer */ - wl_notify_func_t notify; -}; - -/** \class wl_signal - * - * \brief A source of a type of observable event - * - * Signals are recognized points where significant events can be observed. - * Compositors as well as the server can provide signals. Observers are - * wl_listener's that are added through #wl_signal_add. Signals are emitted - * using #wl_signal_emit, which will invoke all listeners until that - * listener is removed by wl_list_remove() (or whenever the signal is - * destroyed). - * - * \sa wl_listener for more information on using wl_signal - */ -struct wl_signal { - struct wl_list listener_list; -}; - -/** Initialize a new \ref wl_signal for use. - * - * \param signal The signal that will be initialized - * - * \memberof wl_signal - */ -static inline void -wl_signal_init(struct wl_signal *signal) -{ - wl_list_init(&signal->listener_list); -} - -/** Add the specified listener to this signal. - * - * \param signal The signal that will emit events to the listener - * \param listener The listener to add - * - * \memberof wl_signal - */ -static inline void -wl_signal_add(struct wl_signal *signal, struct wl_listener *listener) -{ - wl_list_insert(signal->listener_list.prev, &listener->link); -} - -/** Gets the listener struct for the specified callback. - * - * \param signal The signal that contains the specified listener - * \param notify The listener that is the target of this search - * \return the list item that corresponds to the specified listener, or NULL - * if none was found - * - * \memberof wl_signal - */ -static inline struct wl_listener * -wl_signal_get(struct wl_signal *signal, wl_notify_func_t notify) -{ - struct wl_listener *l; - - wl_list_for_each(l, &signal->listener_list, link) - if (l->notify == notify) - return l; - - return NULL; -} - -/** Emits this signal, notifying all registered listeners. - * - * \param signal The signal object that will emit the signal - * \param data The data that will be emitted with the signal - * - * \memberof wl_signal - */ -static inline void -wl_signal_emit(struct wl_signal *signal, void *data) -{ - struct wl_listener *l, *next; - - wl_list_for_each_safe(l, next, &signal->listener_list, link) - l->notify(l, data); -} - -void -wl_signal_emit_mutable(struct wl_signal *signal, void *data); - -typedef void (*wl_resource_destroy_func_t)(struct wl_resource *resource); - -/* - * Post an event to the client's object referred to by 'resource'. - * 'opcode' is the event number generated from the protocol XML - * description (the event name). The variable arguments are the event - * parameters, in the order they appear in the protocol XML specification. - * - * The variable arguments' types are: - * - type=uint: uint32_t - * - type=int: int32_t - * - type=fixed: wl_fixed_t - * - type=string: (const char *) to a nil-terminated string - * - type=array: (struct wl_array *) - * - type=fd: int, that is an open file descriptor - * - type=new_id: (struct wl_object *) or (struct wl_resource *) - * - type=object: (struct wl_object *) or (struct wl_resource *) - */ -void -wl_resource_post_event(struct wl_resource *resource, - uint32_t opcode, ...); - -void -wl_resource_post_event_array(struct wl_resource *resource, - uint32_t opcode, union wl_argument *args); - -void -wl_resource_queue_event(struct wl_resource *resource, - uint32_t opcode, ...); - -void -wl_resource_queue_event_array(struct wl_resource *resource, - uint32_t opcode, union wl_argument *args); - -void -wl_resource_post_error_vargs(struct wl_resource *resource, - uint32_t code, const char *msg, va_list argp); - -void -wl_resource_post_error(struct wl_resource *resource, - uint32_t code, const char *msg, ...) WL_PRINTF(3, 4); - -void -wl_resource_post_no_memory(struct wl_resource *resource); - -struct wl_display * -wl_client_get_display(struct wl_client *client); - -struct wl_resource * -wl_resource_create(struct wl_client *client, - const struct wl_interface *interface, - int version, uint32_t id); - -void -wl_resource_set_implementation(struct wl_resource *resource, - const void *implementation, - void *data, - wl_resource_destroy_func_t destroy); - -void -wl_resource_set_dispatcher(struct wl_resource *resource, - wl_dispatcher_func_t dispatcher, - const void *implementation, - void *data, - wl_resource_destroy_func_t destroy); - -void -wl_resource_destroy(struct wl_resource *resource); - -uint32_t -wl_resource_get_id(const struct wl_resource *resource); - -struct wl_list * -wl_resource_get_link(struct wl_resource *resource); - -struct wl_resource * -wl_resource_from_link(struct wl_list *resource); - -struct wl_resource * -wl_resource_find_for_client(struct wl_list *list, struct wl_client *client); - -struct wl_client * -wl_resource_get_client(struct wl_resource *resource); - -void -wl_resource_set_user_data(struct wl_resource *resource, void *data); - -void * -wl_resource_get_user_data(struct wl_resource *resource); - -int -wl_resource_get_version(const struct wl_resource *resource); - -void -wl_resource_set_destructor(struct wl_resource *resource, - wl_resource_destroy_func_t destroy); - -int -wl_resource_instance_of(struct wl_resource *resource, - const struct wl_interface *interface, - const void *implementation); - -const char * -wl_resource_get_class(const struct wl_resource *resource); - -const struct wl_interface * -wl_resource_get_interface(struct wl_resource *resource); - -void -wl_resource_add_destroy_listener(struct wl_resource *resource, - struct wl_listener *listener); - -struct wl_listener * -wl_resource_get_destroy_listener(struct wl_resource *resource, - wl_notify_func_t notify); - -#define wl_resource_for_each(resource, list) \ - for (resource = 0, resource = wl_resource_from_link((list)->next); \ - wl_resource_get_link(resource) != (list); \ - resource = wl_resource_from_link(wl_resource_get_link(resource)->next)) - -#define wl_resource_for_each_safe(resource, tmp, list) \ - for (resource = 0, tmp = 0, \ - resource = wl_resource_from_link((list)->next), \ - tmp = wl_resource_from_link((list)->next->next); \ - wl_resource_get_link(resource) != (list); \ - resource = tmp, \ - tmp = wl_resource_from_link(wl_resource_get_link(resource)->next)) - -struct wl_shm_buffer * -wl_shm_buffer_get(struct wl_resource *resource); - -void -wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer); - -void -wl_shm_buffer_end_access(struct wl_shm_buffer *buffer); - -void * -wl_shm_buffer_get_data(struct wl_shm_buffer *buffer); - -int32_t -wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer); - -uint32_t -wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer); - -int32_t -wl_shm_buffer_get_width(const struct wl_shm_buffer *buffer); - -int32_t -wl_shm_buffer_get_height(const struct wl_shm_buffer *buffer); - -struct wl_shm_buffer * -wl_shm_buffer_ref(struct wl_shm_buffer *buffer); - -void -wl_shm_buffer_unref(struct wl_shm_buffer *buffer); - -struct wl_shm_pool * -wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer); - -void -wl_shm_pool_unref(struct wl_shm_pool *pool); - -int -wl_display_init_shm(struct wl_display *display); - -uint32_t * -wl_display_add_shm_format(struct wl_display *display, uint32_t format); - -WL_DEPRECATED -struct wl_shm_buffer * -wl_shm_buffer_create(struct wl_client *client, - uint32_t id, int32_t width, int32_t height, - int32_t stride, uint32_t format); - -void -wl_log_set_handler_server(wl_log_func_t handler); - -enum wl_protocol_logger_type { - WL_PROTOCOL_LOGGER_REQUEST, - WL_PROTOCOL_LOGGER_EVENT, -}; - -struct wl_protocol_logger_message { - struct wl_resource *resource; - int message_opcode; - const struct wl_message *message; - int arguments_count; - const union wl_argument *arguments; -}; - -/** Callback function type for wl_display_add_protocol_logger() */ -typedef void (*wl_protocol_logger_func_t)(void *user_data, - enum wl_protocol_logger_type direction, - const struct wl_protocol_logger_message *message); - -struct wl_protocol_logger * -wl_display_add_protocol_logger(struct wl_display *display, - wl_protocol_logger_func_t, void *user_data); - -void -wl_protocol_logger_destroy(struct wl_protocol_logger *logger); - -void -wl_fixes_handle_ack_global_remove(struct wl_resource *fixes_resource, - struct wl_resource *registry_resource, - uint32_t global_name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/wayland-server-private.h b/src/wayland-server-private.h deleted file mode 100644 index 23fa4587..00000000 --- a/src/wayland-server-private.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2011 Intel Corporation - * Copyright © 2013 Jason Ekstrand - * - * 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. - */ - -#ifndef WAYLAND_SERVER_PRIVATE_H -#define WAYLAND_SERVER_PRIVATE_H - -#include "wayland-server-core.h" - -struct wl_priv_signal { - struct wl_list listener_list; - struct wl_list emit_list; -}; - -void -wl_priv_signal_init(struct wl_priv_signal *signal); - -void -wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener); - -struct wl_listener * -wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify); - -void -wl_priv_signal_emit(struct wl_priv_signal *signal, void *data); - -void -wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data); - -#endif diff --git a/src/wayland-server-uninstalled.pc.in b/src/wayland-server-uninstalled.pc.in new file mode 100644 index 00000000..90577828 --- /dev/null +++ b/src/wayland-server-uninstalled.pc.in @@ -0,0 +1,8 @@ +libdir=@abs_builddir@/.libs +includedir=@abs_srcdir@ + +Name: Wayland Server +Description: Server side implementation of the Wayland protocol (not installed) +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lwayland-server diff --git a/src/wayland-server.c b/src/wayland-server.c index 31b597e4..674aecaf 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -1,58 +1,54 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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: + * 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 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. + * 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. */ #define _GNU_SOURCE -#include #include #include #include #include #include +#include #include #include #include #include #include #include +#include #include #include -#include #include #include +#include -#include "wayland-util.h" #include "wayland-private.h" -#include "wayland-server-private.h" #include "wayland-server.h" +#include "wayland-server-protocol.h" #include "wayland-os.h" /* This is the size of the char array in struct sock_addr_un. - * No Wayland socket can be created with a path longer than this, - * including the null terminator. - */ + No Wayland socket can be created with a path longer than this, + including the null terminator. */ #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 108 #endif @@ -75,193 +71,77 @@ struct wl_client { struct wl_event_source *source; struct wl_display *display; struct wl_resource *display_resource; + uint32_t id_count; + uint32_t mask; struct wl_list link; struct wl_map objects; - struct wl_priv_signal destroy_signal; - struct wl_priv_signal destroy_late_signal; - pid_t pid; - uid_t uid; - gid_t gid; - bool error; - struct wl_priv_signal resource_created_signal; - void *data; - wl_user_data_destroy_func_t data_dtor; + struct wl_signal destroy_signal; + struct ucred ucred; + int error; }; struct wl_display { struct wl_event_loop *loop; - bool run; + int run; - uint32_t next_global_name; + uint32_t id; uint32_t serial; struct wl_list registry_resource_list; struct wl_list global_list; struct wl_list socket_list; struct wl_list client_list; - struct wl_list protocol_loggers; - struct wl_priv_signal destroy_signal; - struct wl_priv_signal create_client_signal; + struct wl_signal destroy_signal; struct wl_array additional_shm_formats; - - wl_display_global_filter_func_t global_filter; - void *global_filter_data; - - int terminate_efd; - struct wl_event_source *term_source; - - size_t max_buffer_size; -}; - -struct wl_registry { - struct wl_display *display; - struct wl_list offer_list; }; struct wl_global { struct wl_display *display; const struct wl_interface *interface; - struct wl_list offer_list; uint32_t name; uint32_t version; void *data; wl_global_bind_func_t bind; - wl_global_withdrawn_func_t withdrawn; struct wl_list link; - bool unpublished; -}; - -struct wl_global_offer { - struct wl_list global_link; /**< in struct wl_global::offer_list */ - struct wl_list registry_link; /**< in struct wl_registry::offer_list */ - struct wl_resource *registry_resource; - struct wl_global *global; }; struct wl_resource { struct wl_object object; wl_resource_destroy_func_t destroy; struct wl_list link; - /* Unfortunately some users of libwayland (e.g. mesa) still use the - * deprecated wl_resource struct, even if creating it with the new - * wl_resource_create(). So we cannot change the layout of the struct - * unless after the data field. */ - struct wl_signal deprecated_destroy_signal; + struct wl_signal destroy_signal; struct wl_client *client; void *data; int version; wl_dispatcher_func_t dispatcher; - struct wl_priv_signal destroy_signal; -}; - -struct wl_protocol_logger { - struct wl_list link; - wl_protocol_logger_func_t func; - void *user_data; }; static int debug_server = 0; -static int debug_color = 0; - -static void -log_closure(struct wl_resource *resource, - struct wl_closure *closure, int send) -{ - struct wl_object *object = &resource->object; - struct wl_display *display = resource->client->display; - struct wl_protocol_logger *protocol_logger; - struct wl_protocol_logger_message message; - - if (debug_server) - wl_closure_print(closure, object, send, false, NULL, NULL, debug_color); - - if (!wl_list_empty(&display->protocol_loggers)) { - message.resource = resource; - message.message_opcode = closure->opcode; - message.message = closure->message; - message.arguments_count = closure->count; - message.arguments = closure->args; - wl_list_for_each(protocol_logger, - &display->protocol_loggers, link) { - protocol_logger->func(protocol_logger->user_data, - send ? WL_PROTOCOL_LOGGER_EVENT : - WL_PROTOCOL_LOGGER_REQUEST, - &message); - } - } -} - -static bool -verify_objects(struct wl_resource *resource, uint32_t opcode, - union wl_argument *args) -{ - struct wl_object *object = &resource->object; - const char *signature = object->interface->events[opcode].signature; - struct argument_details arg; - struct wl_resource *res; - int count, i; - - count = arg_count_for_signature(signature); - for (i = 0; i < count; i++) { - signature = get_next_argument(signature, &arg); - switch (arg.type) { - case WL_ARG_NEW_ID: - case WL_ARG_OBJECT: - res = (struct wl_resource *) (args[i].o); - if (res && res->client != resource->client) { - wl_log("compositor bug: The compositor " - "tried to use an object from one " - "client in a '%s.%s' for a different " - "client.\n", object->interface->name, - object->interface->events[opcode].name); - return false; - } - default: - break; - } - } - return true; -} - -static void -handle_array(struct wl_resource *resource, uint32_t opcode, - union wl_argument *args, - int (*send_func)(struct wl_closure *, struct wl_connection *)) -{ - struct wl_closure *closure; - struct wl_object *object = &resource->object; - - if (resource->client->error) - return; - - if (!verify_objects(resource, opcode, args)) { - resource->client->error = true; - return; - } - - closure = wl_closure_marshal(object, opcode, args, - &object->interface->events[opcode]); - - if (closure == NULL) { - resource->client->error = true; - return; - } - - log_closure(resource, closure, true); - - if (send_func(closure, resource->client->connection)) - resource->client->error = true; - - wl_closure_destroy(closure); -} WL_EXPORT void wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, union wl_argument *args) { - handle_array(resource, opcode, args, wl_closure_send); + struct wl_closure *closure; + struct wl_object *object = &resource->object; + + closure = wl_closure_marshal(object, opcode, args, + &object->interface->events[opcode]); + + if (closure == NULL) { + resource->client->error = 1; + return; + } + + if (wl_closure_send(closure, resource->client->connection)) + resource->client->error = 1; + + if (debug_server) + wl_closure_print(closure, object, true); + + wl_closure_destroy(closure); } WL_EXPORT void @@ -284,7 +164,24 @@ WL_EXPORT void wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode, union wl_argument *args) { - handle_array(resource, opcode, args, wl_closure_queue); + struct wl_closure *closure; + struct wl_object *object = &resource->object; + + closure = wl_closure_marshal(object, opcode, args, + &object->interface->events[opcode]); + + if (closure == NULL) { + resource->client->error = 1; + return; + } + + if (wl_closure_queue(closure, resource->client->connection)) + resource->client->error = 1; + + if (debug_server) + wl_closure_print(closure, object, true); + + wl_closure_destroy(closure); } WL_EXPORT void @@ -302,23 +199,19 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...) wl_resource_queue_event_array(resource, opcode, args); } -/** Post a protocol error - * - * \param resource The resource object - * \param code The error code - * \param msg The error message format string - * \param argp The format string argument list - * - * \memberof wl_resource - */ WL_EXPORT void -wl_resource_post_error_vargs(struct wl_resource *resource, - uint32_t code, const char *msg, va_list argp) +wl_resource_post_error(struct wl_resource *resource, + uint32_t code, const char *msg, ...) { struct wl_client *client = resource->client; char buffer[128]; + va_list ap; - vsnprintf(buffer, sizeof buffer, msg, argp); + va_start(ap, msg); + vsnprintf(buffer, sizeof buffer, msg, ap); + va_end(ap); + + client->error = 1; /* * When a client aborts, its resources are destroyed in id order, @@ -327,39 +220,11 @@ wl_resource_post_error_vargs(struct wl_resource *resource, * with a NULL display_resource. Do not try to send errors to an * already dead client. */ - if (client->error || !client->display_resource) + if (!client->display_resource) return; wl_resource_post_event(client->display_resource, WL_DISPLAY_ERROR, resource, code, buffer); - client->error = true; -} - -/** Post a protocol error - * - * \param resource The resource object - * \param code The error code - * \param msg The error message format string - * \param ... The format string arguments - * - * \memberof wl_resource - */ -WL_EXPORT void -wl_resource_post_error(struct wl_resource *resource, - uint32_t code, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - wl_resource_post_error_vargs(resource, code, msg, ap); - va_end(ap); -} - -static void -destroy_client_with_error(struct wl_client *client, const char *reason) -{ - wl_log("%s (pid %u)\n", reason, client->pid); - wl_client_destroy(client); } static int @@ -373,24 +238,18 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) const struct wl_message *message; uint32_t p[2]; uint32_t resource_flags; - int opcode, size, since; + int opcode, size; int len; - if (mask & WL_EVENT_HANGUP) { + if (mask & (WL_EVENT_ERROR | WL_EVENT_HANGUP)) { wl_client_destroy(client); return 1; } - if (mask & WL_EVENT_ERROR) { - destroy_client_with_error(client, "socket error"); - return 1; - } - if (mask & WL_EVENT_WRITABLE) { len = wl_connection_flush(connection); if (len < 0 && errno != EAGAIN) { - destroy_client_with_error( - client, "failed to flush client connection"); + wl_client_destroy(client); return 1; } else if (len >= 0) { wl_event_source_fd_update(client->source, @@ -401,40 +260,16 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) len = 0; if (mask & WL_EVENT_READABLE) { len = wl_connection_read(connection); - if (len == 0 || (len < 0 && errno != EAGAIN)) { - destroy_client_with_error( - client, "failed to read client connection"); + if (len < 0 && errno != EAGAIN) { + wl_client_destroy(client); return 1; } } - while (len >= 0 && (size_t) len >= sizeof p) { + while ((size_t) len >= sizeof p) { wl_connection_copy(connection, p, sizeof p); opcode = p[1] & 0xffff; size = p[1] >> 16; - - /* - * If the message is larger than the maximum size of the - * connection buffer, the connection buffer will fill to - * its max size and stay there, with no message ever - * successfully being processed. Since libwayland-server - * uses level-triggered epoll, it will cause the server to - * enter a loop that consumes CPU. To avoid this, - * immediately disconnect the client with a protocol - * error. Since the maximum size of a message should not - * depend on the buffer size chosen by the compositor, - * always compare the message size against the - * limit enforced by libwayland 1.22 and below (4096), - * rather than the actual value the compositor chose. - */ - if (size > WL_MAX_MESSAGE_SIZE) { - wl_resource_post_error(client->display_resource, - WL_DISPLAY_ERROR_INVALID_METHOD, - "message length %u exceeds %d", - size, WL_MAX_MESSAGE_SIZE); - break; - } - if (len < size) break; @@ -451,7 +286,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) if (opcode >= object->interface->method_count) { wl_resource_post_error(client->display_resource, WL_DISPLAY_ERROR_INVALID_METHOD, - "invalid method %d, object %s#%u", + "invalid method %d, object %s@%u", opcode, object->interface->name, object->id); @@ -459,22 +294,22 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) } message = &object->interface->methods[opcode]; - since = wl_message_get_since(message); if (!(resource_flags & WL_MAP_ENTRY_LEGACY) && - resource->version > 0 && resource->version < since) { + resource->version > 0 && + resource->version < wl_message_get_since(message)) { wl_resource_post_error(client->display_resource, WL_DISPLAY_ERROR_INVALID_METHOD, - "invalid version for %s#%u.%s (%d, need at least %d)", + "invalid method %d, object %s@%u", + opcode, object->interface->name, - object->id, - message->name, - resource->version, since); + object->id); break; } closure = wl_connection_demarshal(client->connection, size, &client->objects, message); + len -= size; if (closure == NULL && errno == ENOMEM) { wl_resource_post_no_memory(resource); @@ -483,7 +318,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) wl_closure_lookup_objects(closure, &client->objects) < 0) { wl_resource_post_error(client->display_resource, WL_DISPLAY_ERROR_INVALID_METHOD, - "invalid arguments for %s#%u.%s", + "invalid arguments for %s@%u.%s", object->interface->name, object->id, message->name); @@ -491,7 +326,8 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) break; } - log_closure(resource, closure, false); + if (debug_server) + wl_closure_print(closure, object, false); if ((resource_flags & WL_MAP_ENTRY_LEGACY) || resource->dispatcher == NULL) { @@ -506,14 +342,10 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) if (client->error) break; - - len = wl_connection_pending_input(connection); } - if (client->error) { - destroy_client_with_error(client, - "error in client communication"); - } + if (client->error) + wl_client_destroy(client); return 1; } @@ -526,7 +358,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) * socket later - typically when the compositor has handled all * requests and goes back to block in the event loop. This function * flushes all queued up events for a client immediately. - * + * * \memberof wl_client */ WL_EXPORT void @@ -539,7 +371,7 @@ wl_client_flush(struct wl_client *client) * * \param client The client object * \return The display object the client is associated with. - * + * * \memberof wl_client */ WL_EXPORT struct wl_display * @@ -569,28 +401,21 @@ bind_display(struct wl_client *client, struct wl_display *display); * wl_display_connect_to_fd() on the client side or used with the * WAYLAND_SOCKET environment variable on the client side. * - * Listeners added with wl_display_add_client_created_listener() will - * be notified by this function after the client is fully constructed. - * * On failure this function sets errno accordingly and returns NULL. - * - * On success, the new client object takes the ownership of the file - * descriptor. On failure, the ownership of the socket endpoint file - * descriptor is unchanged, it is the responsibility of the caller to - * perform cleanup, e.g. call close(). - * + * * \memberof wl_display */ WL_EXPORT struct wl_client * wl_client_create(struct wl_display *display, int fd) { struct wl_client *client; + socklen_t len; - client = zalloc(sizeof *client); + client = malloc(sizeof *client); if (client == NULL) return NULL; - wl_priv_signal_init(&client->resource_created_signal); + memset(client, 0, sizeof *client); client->display = display; client->source = wl_event_loop_add_fd(display->loop, fd, WL_EVENT_READABLE, @@ -599,12 +424,12 @@ wl_client_create(struct wl_display *display, int fd) if (!client->source) goto err_client; - if (wl_os_socket_peercred(fd, &client->uid, &client->gid, - &client->pid) != 0) + len = sizeof client->ucred; + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, + &client->ucred, &len) < 0) goto err_source; - client->connection = wl_connection_create(fd, display->max_buffer_size); - + client->connection = wl_connection_create(fd); if (client->connection == NULL) goto err_source; @@ -613,15 +438,12 @@ wl_client_create(struct wl_display *display, int fd) if (wl_map_insert_at(&client->objects, 0, 0, NULL) < 0) goto err_map; - wl_priv_signal_init(&client->destroy_signal); - wl_priv_signal_init(&client->destroy_late_signal); + wl_signal_init(&client->destroy_signal); if (bind_display(client, display) < 0) goto err_map; wl_list_insert(display->client_list.prev, &client->link); - wl_priv_signal_emit(&display->create_client_signal, client); - return client; err_map: @@ -646,61 +468,23 @@ err_client: * SO_PEERCRED, on the client socket fd. All the pointers can be * NULL, if the caller is not interested in a particular ID. * - * Note, process IDs are subject to race conditions and are not a reliable way - * to identify a client. - * * Be aware that for clients that a compositor forks and execs and * then connects using socketpair(), this function will return the * credentials for the compositor. The credentials for the socketpair * are set at creation time in the compositor. - * + * * \memberof wl_client */ WL_EXPORT void -wl_client_get_credentials(const struct wl_client *client, +wl_client_get_credentials(struct wl_client *client, pid_t *pid, uid_t *uid, gid_t *gid) { if (pid) - *pid = client->pid; + *pid = client->ucred.pid; if (uid) - *uid = client->uid; + *uid = client->ucred.uid; if (gid) - *gid = client->gid; -} - -/** Get the file descriptor for the client - * - * \param client The display object - * \return The file descriptor to use for the connection - * - * This function returns the file descriptor for the given client. - * - * Be sure to use the file descriptor from the client for inspection only. - * If the caller does anything to the file descriptor that changes its state, - * it will likely cause problems. - * - * See also wl_client_get_credentials(). - * It is recommended that you evaluate whether wl_client_get_credentials() - * can be applied to your use case instead of this function. - * - * If you would like to distinguish just between the client and the compositor - * itself from the client's request, it can be done by getting the client - * credentials and by checking the PID of the client and the compositor's PID. - * Regarding the case in which the socketpair() is being used, you need to be - * careful. Please note the documentation for wl_client_get_credentials(). - * - * This function can be used for a compositor to validate a request from - * a client if there are additional information provided from the client's - * file descriptor. For instance, suppose you can get the security contexts - * from the client's file descriptor. The compositor can validate the client's - * request with the contexts and make a decision whether it permits or deny it. - * - * \memberof wl_client - */ -WL_EXPORT int -wl_client_get_fd(struct wl_client *client) -{ - return wl_connection_get_fd(client->connection); + *gid = client->ucred.gid; } /** Look up an object in the client name space @@ -710,8 +494,8 @@ wl_client_get_fd(struct wl_client *client) * \return The object or NULL if there is not object for the given ID * * This looks up an object in the client object name space by its - * object ID. - * + * object ID. + * * \memberof wl_client */ WL_EXPORT struct wl_resource * @@ -727,30 +511,6 @@ wl_client_post_no_memory(struct wl_client *client) WL_DISPLAY_ERROR_NO_MEMORY, "no memory"); } -/** Report an internal server error - * - * \param client The client object - * \param msg A printf-style format string - * \param ... Format string arguments - * - * Report an unspecified internal implementation error and disconnect - * the client. - * - * \memberof wl_client - */ -WL_EXPORT void -wl_client_post_implementation_error(struct wl_client *client, - char const *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - wl_resource_post_error_vargs(client->display_resource, - WL_DISPLAY_ERROR_IMPLEMENTATION, - msg, ap); - va_end(ap); -} - WL_EXPORT void wl_resource_post_no_memory(struct wl_resource *resource) { @@ -758,59 +518,32 @@ wl_resource_post_no_memory(struct wl_resource *resource) WL_DISPLAY_ERROR_NO_MEMORY, "no memory"); } -/** Detect if a wl_resource uses the deprecated public definition. - * - * Before Wayland 1.2.0, the definition of struct wl_resource was public. - * It was made opaque just before 1.2.0, and later new fields were added. - * The new fields cannot be accessed if a program is using the deprecated - * definition, as there would not be memory allocated for them. - * - * The creation pattern for the deprecated definition was wl_resource_init() - * followed by wl_client_add_resource(). wl_resource_init() was an inline - * function and no longer exists, but binaries might still carry it. - * wl_client_add_resource() still exists for ABI compatibility. - */ -static bool -resource_is_deprecated(struct wl_resource *resource) -{ - struct wl_map *map = &resource->client->objects; - int id = resource->object.id; - - /* wl_client_add_resource() marks deprecated resources with the flag. */ - if (wl_map_lookup_flags(map, id) & WL_MAP_ENTRY_LEGACY) - return true; - - return false; -} - -/** Removes the wl_resource from the client's object map and deletes it. - * - * Triggers the destroy signal and destructor for the resource before - * removing it from the client's object map and releasing the resource's - * memory. - * - * This order is important to ensure listeners and destruction code can - * find the resource before it has been destroyed whilst ensuring the - * resource is not accessible via the object map after memory has been - * freed. - */ -static enum wl_iterator_result -remove_and_destroy_resource(void *element, void *data, uint32_t flags) +static void +destroy_resource(void *element, void *data) { struct wl_resource *resource = element; struct wl_client *client = resource->client; - uint32_t id = resource->object.id;; + uint32_t flags; - wl_signal_emit(&resource->deprecated_destroy_signal, resource); - /* Don't emit the new signal for deprecated resources, as that would - * access memory outside the bounds of the deprecated struct */ - if (!resource_is_deprecated(resource)) - wl_priv_signal_final_emit(&resource->destroy_signal, resource); + wl_signal_emit(&resource->destroy_signal, resource); + flags = wl_map_lookup_flags(&client->objects, resource->object.id); if (resource->destroy) resource->destroy(resource); - /* The resource should be cleared from the map before memory is freed. */ + if (!(flags & WL_MAP_ENTRY_LEGACY)) + free(resource); +} + +WL_EXPORT void +wl_resource_destroy(struct wl_resource *resource) +{ + struct wl_client *client = resource->client; + uint32_t id; + + id = resource->object.id; + destroy_resource(resource, NULL); + if (id < WL_SERVER_ID_START) { if (client->display_resource) { wl_resource_queue_event(client->display_resource, @@ -820,24 +553,10 @@ remove_and_destroy_resource(void *element, void *data, uint32_t flags) } else { wl_map_remove(&client->objects, id); } - - if (!(flags & WL_MAP_ENTRY_LEGACY)) - free(resource); - - return WL_ITERATOR_CONTINUE; -} - -WL_EXPORT void -wl_resource_destroy(struct wl_resource *resource) -{ - struct wl_client *client = resource->client; - uint32_t flags = wl_map_lookup_flags(&client->objects, resource->object.id); - - remove_and_destroy_resource(resource, NULL, flags); } WL_EXPORT uint32_t -wl_resource_get_id(const struct wl_resource *resource) +wl_resource_get_id(struct wl_resource *resource) { return resource->object.id; } @@ -864,12 +583,12 @@ wl_resource_find_for_client(struct wl_list *list, struct wl_client *client) if (client == NULL) return NULL; - wl_list_for_each(resource, list, link) { - if (resource->client == client) - return resource; - } + wl_list_for_each(resource, list, link) { + if (resource->client == client) + return resource; + } - return NULL; + return NULL; } WL_EXPORT struct wl_client * @@ -891,7 +610,7 @@ wl_resource_get_user_data(struct wl_resource *resource) } WL_EXPORT int -wl_resource_get_version(const struct wl_resource *resource) +wl_resource_get_version(struct wl_resource *resource) { return resource->version; } @@ -916,177 +635,66 @@ WL_EXPORT void wl_resource_add_destroy_listener(struct wl_resource *resource, struct wl_listener * listener) { - if (resource_is_deprecated(resource)) - wl_signal_add(&resource->deprecated_destroy_signal, listener); - else - wl_priv_signal_add(&resource->destroy_signal, listener); + wl_signal_add(&resource->destroy_signal, listener); } WL_EXPORT struct wl_listener * wl_resource_get_destroy_listener(struct wl_resource *resource, wl_notify_func_t notify) { - if (resource_is_deprecated(resource)) - return wl_signal_get(&resource->deprecated_destroy_signal, notify); - return wl_priv_signal_get(&resource->destroy_signal, notify); + return wl_signal_get(&resource->destroy_signal, notify); } -/** Retrieve the interface name (class) of a resource object. - * - * \param resource The resource object - * - * \memberof wl_resource - */ -WL_EXPORT const char * -wl_resource_get_class(const struct wl_resource *resource) -{ - return resource->object.interface->name; -} - -/** Get the interface of a resource object - * - * \param resource The resource object - * \return The interface of the object associated with the resource - * - * \memberof wl_resource - * \since 1.24 - */ -WL_EXPORT const struct wl_interface * -wl_resource_get_interface(struct wl_resource *resource) -{ - return resource->object.interface; -} - -/** - * Add a listener to be called at the beginning of wl_client destruction - * - * The listener provided will be called when wl_client destroy has begun, - * before any of that client's resources have been destroyed. - * - * There is no requirement to remove the link of the wl_listener when the - * signal is emitted. - * - * \memberof wl_client - */ WL_EXPORT void wl_client_add_destroy_listener(struct wl_client *client, struct wl_listener *listener) { - wl_priv_signal_add(&client->destroy_signal, listener); + wl_signal_add(&client->destroy_signal, listener); } WL_EXPORT struct wl_listener * wl_client_get_destroy_listener(struct wl_client *client, wl_notify_func_t notify) { - return wl_priv_signal_get(&client->destroy_signal, notify); -} - -/** - * Add a listener to be called at the end of wl_client destruction - * - * The listener provided will be called when wl_client destroy is nearly - * complete, after all of that client's resources have been destroyed. - * - * There is no requirement to remove the link of the wl_listener when the - * signal is emitted. - * - * \memberof wl_client - * \since 1.22.0 - */ -WL_EXPORT void -wl_client_add_destroy_late_listener(struct wl_client *client, - struct wl_listener *listener) -{ - wl_priv_signal_add(&client->destroy_late_signal, listener); -} - -WL_EXPORT struct wl_listener * -wl_client_get_destroy_late_listener(struct wl_client *client, - wl_notify_func_t notify) -{ - return wl_priv_signal_get(&client->destroy_late_signal, notify); + return wl_signal_get(&client->destroy_signal, notify); } WL_EXPORT void wl_client_destroy(struct wl_client *client) { + uint32_t serial = 0; - /* wl_client_destroy() should not be called twice for the same client. */ - if (wl_list_empty(&client->link)) { - client->error = 1; - wl_log("wl_client_destroy: encountered re-entrant client destruction.\n"); - return; - } - - wl_list_remove(&client->link); - /* Keep the client link safe to inspect. */ - wl_list_init(&client->link); - - wl_priv_signal_final_emit(&client->destroy_signal, client); + wl_signal_emit(&client->destroy_signal, client); wl_client_flush(client); - wl_map_for_each(&client->objects, remove_and_destroy_resource, NULL); + wl_map_for_each(&client->objects, destroy_resource, &serial); wl_map_release(&client->objects); wl_event_source_remove(client->source); - close(wl_connection_destroy(client->connection)); - - wl_priv_signal_final_emit(&client->destroy_late_signal, client); - - wl_list_remove(&client->resource_created_signal.listener_list); - - if (client->data_dtor) - client->data_dtor(client->data); - + wl_connection_destroy(client->connection); + wl_list_remove(&client->link); free(client); } -/* Check if a global filter is registered and use it if any. - * - * If no wl_global filter has been registered, this function will - * return true, allowing the wl_global to be visible to the wl_client - */ -static bool -wl_global_is_visible(const struct wl_client *client, - const struct wl_global *global) -{ - struct wl_display *display = client->display; - - return (display->global_filter == NULL || - display->global_filter(client, global, display->global_filter_data)); -} - static void registry_bind(struct wl_client *client, struct wl_resource *resource, uint32_t name, const char *interface, uint32_t version, uint32_t id) { struct wl_global *global; - struct wl_registry *registry = resource->data; - struct wl_display *display = registry->display; + struct wl_display *display = resource->data; wl_list_for_each(global, &display->global_list, link) if (global->name == name) break; - if (&global->link == &display->global_list || !wl_global_is_visible(client, global)) + if (&global->link == &display->global_list) wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "global %s (%"PRIu32") is unavailable", interface, name); - else if (strcmp(global->interface->name, interface) != 0) - wl_resource_post_error(resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "invalid interface for global %"PRIu32": expected %s, got %s", - name, global->interface->name, interface); - else if (version == 0) - wl_resource_post_error(resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "invalid version for global %s (%"PRIu32"): 0 is not a valid version", - interface, name); + "invalid global %s (%d)", interface, name); else if (global->version < version) wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "invalid version for global %s (%"PRIu32"): expected at most %d, got %d", + "invalid version for global %s (%d): have %d, wanted %d", interface, name, global->version, version); else global->bind(client, global->data, version, id); @@ -1115,76 +723,9 @@ display_sync(struct wl_client *client, } static void -wl_global_publish(struct wl_global *global, - struct wl_resource *registry_resource) +unbind_resource(struct wl_resource *resource) { - struct wl_global_offer *offer; - struct wl_registry *registry = registry_resource->data; - - offer = zalloc(sizeof *offer); - if (offer == NULL) { - wl_resource_post_no_memory(registry_resource); - return; - } - - offer->registry_resource = registry_resource; - offer->global = global; - wl_list_insert(&global->offer_list, &offer->global_link); - wl_list_insert(®istry->offer_list, &offer->registry_link); - - wl_resource_post_event(registry_resource, - WL_REGISTRY_GLOBAL, - global->name, - global->interface->name, - global->version); -} - -static void -wl_global_offer_destroy(struct wl_global_offer *offer) -{ - wl_list_remove(&offer->global_link); - wl_list_remove(&offer->registry_link); - free(offer); -} - -static void -wl_global_offer_done(struct wl_global_offer *offer) -{ - struct wl_global *global = offer->global; - - wl_global_offer_destroy(offer); - - if (global->unpublished && global->withdrawn && wl_list_empty(&global->offer_list)) - global->withdrawn(global); -} - -static struct wl_global_offer * -wl_registry_find_offer(struct wl_registry *registry, - uint32_t global_name) -{ - struct wl_global_offer *offer; - - wl_list_for_each(offer, ®istry->offer_list, registry_link) { - if (offer->global->name == global_name) - return offer; - } - - return NULL; -} - -static void -unbind_registry_resource(struct wl_resource *resource) -{ - struct wl_registry *registry = resource->data; - struct wl_global_offer *offer; - - while (!wl_list_empty(®istry->offer_list)) { - offer = wl_container_of(registry->offer_list.next, offer, registry_link); - wl_global_offer_done(offer); - } - wl_list_remove(&resource->link); - free(registry); } static void @@ -1194,7 +735,6 @@ display_get_registry(struct wl_client *client, struct wl_display *display = resource->data; struct wl_resource *registry_resource; struct wl_global *global; - struct wl_registry *registry; registry_resource = wl_resource_create(client, &wl_registry_interface, 1, id); @@ -1203,25 +743,19 @@ display_get_registry(struct wl_client *client, return; } - registry = zalloc(sizeof *registry); - if (registry == NULL) { - wl_client_post_no_memory(client); - return; - } - - registry->display = display; - wl_list_init(®istry->offer_list); - wl_resource_set_implementation(registry_resource, ®istry_interface, - registry, unbind_registry_resource); + display, unbind_resource); wl_list_insert(&display->registry_resource_list, ®istry_resource->link); wl_list_for_each(global, &display->global_list, link) - if (wl_global_is_visible(client, global) && !global->unpublished) - wl_global_publish(global, registry_resource); + wl_resource_post_event(registry_resource, + WL_REGISTRY_GLOBAL, + global->name, + global->interface->name, + global->version); } static const struct wl_display_interface display_interface = { @@ -1241,8 +775,7 @@ bind_display(struct wl_client *client, struct wl_display *display) client->display_resource = wl_resource_create(client, &wl_display_interface, 1, 1); if (client->display_resource == NULL) { - /* DON'T send no-memory error to client - it has no - * resource to which it could post the event */ + wl_client_post_no_memory(client); return -1; } @@ -1252,18 +785,9 @@ bind_display(struct wl_client *client, struct wl_display *display) return 0; } -static int -handle_display_terminate(int fd, uint32_t mask, void *data) { - uint64_t term_event; - - if (read(fd, &term_event, sizeof(term_event)) < 0 && errno != EAGAIN) - return -1; - - return 0; -} - /** Create Wayland display object. * + * \param None * \return The Wayland display object. Null if failed to create * * This creates the wl_display object. @@ -1275,25 +799,12 @@ wl_display_create(void) { struct wl_display *display; const char *debug; - const char *no_color; - const char *force_color; - no_color = getenv("NO_COLOR"); - force_color = getenv("FORCE_COLOR"); debug = getenv("WAYLAND_DEBUG"); - if (debug && (wl_check_env_token(debug, "server") || wl_check_env_token(debug, "1"))) { + if (debug && (strstr(debug, "server") || strstr(debug, "1"))) debug_server = 1; - if (isatty(fileno(stderr))) - debug_color = 1; - } - if (force_color && force_color[0] != '\0') - debug_color = 1; - - if (no_color && no_color[0] != '\0') - debug_color = 0; - - display = zalloc(sizeof *display); + display = malloc(sizeof *display); if (display == NULL) return NULL; @@ -1303,45 +814,19 @@ wl_display_create(void) return NULL; } - display->terminate_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); - if (display->terminate_efd < 0) - goto err_eventfd; - - display->term_source = wl_event_loop_add_fd(display->loop, - display->terminate_efd, - WL_EVENT_READABLE, - handle_display_terminate, - NULL); - - if (display->term_source == NULL) - goto err_term_source; - wl_list_init(&display->global_list); wl_list_init(&display->socket_list); wl_list_init(&display->client_list); wl_list_init(&display->registry_resource_list); - wl_list_init(&display->protocol_loggers); - wl_priv_signal_init(&display->destroy_signal); - wl_priv_signal_init(&display->create_client_signal); + wl_signal_init(&display->destroy_signal); - display->next_global_name = 1; + display->id = 1; display->serial = 0; - display->global_filter = NULL; - display->global_filter_data = NULL; - display->max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE; - wl_array_init(&display->additional_shm_formats); return display; - -err_term_source: - close(display->terminate_efd); -err_eventfd: - wl_event_loop_destroy(display->loop); - free(display); - return NULL; } static void @@ -1366,44 +851,28 @@ wl_socket_alloc(void) { struct wl_socket *s; - s = zalloc(sizeof *s); + s = malloc(sizeof *s); if (!s) return NULL; + memset(s, 0, sizeof *s); s->fd = -1; s->fd_lock = -1; return s; } -/** Destroy Wayland display object. - * - * \param display The Wayland display object which should be destroyed. - * - * This function emits the wl_display destroy signal, releases - * all the sockets added to this display, free's all the globals associated - * with this display, free's memory of additional shared memory formats and - * destroy the display object. - * - * \sa wl_display_add_destroy_listener - * - * \memberof wl_display - */ WL_EXPORT void wl_display_destroy(struct wl_display *display) { struct wl_socket *s, *next; struct wl_global *global, *gnext; - wl_priv_signal_final_emit(&display->destroy_signal, display); + wl_signal_emit(&display->destroy_signal, display); wl_list_for_each_safe(s, next, &display->socket_list, link) { wl_socket_destroy(s); } - - close(display->terminate_efd); - wl_event_source_remove(display->term_source); - wl_event_loop_destroy(display->loop); wl_list_for_each_safe(global, gnext, &display->global_list, link) @@ -1411,45 +880,9 @@ wl_display_destroy(struct wl_display *display) wl_array_release(&display->additional_shm_formats); - wl_list_remove(&display->protocol_loggers); - free(display); } -/** Set a filter function for global objects - * - * \param display The Wayland display object. - * \param filter The global filter function. - * \param data User data to be associated with the global filter. - * - * Set a filter for the wl_display to advertise or hide global objects - * to clients. - * The set filter will be used during wl_global advertisement to - * determine whether a global object should be advertised to a - * given client, and during wl_global binding to determine whether - * a given client should be allowed to bind to a global. - * - * Clients that try to bind to a global that was filtered out will - * have an error raised. - * - * Setting the filter NULL will result in all globals being - * advertised to all clients. The default is no filter. - * - * The filter should be installed before any client connects and should always - * take the same decision given a client and a global. Not doing so will result - * in inconsistent filtering and broken wl_registry event sequences. - * - * \memberof wl_display - */ -WL_EXPORT void -wl_display_set_global_filter(struct wl_display *display, - wl_display_global_filter_func_t filter, - void *data) -{ - display->global_filter = filter; - display->global_filter_data = data; -} - WL_EXPORT struct wl_global * wl_global_create(struct wl_display *display, const struct wl_interface *interface, int version, @@ -1458,237 +891,58 @@ wl_global_create(struct wl_display *display, struct wl_global *global; struct wl_resource *resource; - if (version < 1) { - wl_log("wl_global_create: failing to create interface " - "'%s' with version %d because it is less than 1\n", - interface->name, version); + if (interface->version < version) { + wl_log("wl_global_create: implemented version higher " + "than interface version%m\n"); return NULL; } - if (version > interface->version) { - wl_log("wl_global_create: implemented version for '%s' " - "higher than interface version (%d > %d)\n", - interface->name, version, interface->version); - return NULL; - } - - if (display->next_global_name >= UINT32_MAX) { - wl_log("wl_global_create: ran out of global names\n"); - return NULL; - } - - global = zalloc(sizeof *global); + global = malloc(sizeof *global); if (global == NULL) return NULL; global->display = display; - global->name = display->next_global_name++; + global->name = display->id++; global->interface = interface; global->version = version; global->data = data; global->bind = bind; - global->withdrawn = NULL; - global->unpublished = false; wl_list_insert(display->global_list.prev, &global->link); - wl_list_init(&global->offer_list); wl_list_for_each(resource, &display->registry_resource_list, link) - if (wl_global_is_visible(resource->client, global)) - wl_global_publish(global, resource); + wl_resource_post_event(resource, + WL_REGISTRY_GLOBAL, + global->name, + global->interface->name, + global->version); return global; } -static void -wl_global_unpublish(struct wl_global *global) -{ - struct wl_global_offer *offer; - - wl_list_for_each(offer, &global->offer_list, global_link) - wl_resource_post_event(offer->registry_resource, - WL_REGISTRY_GLOBAL_REMOVE, global->name); - - global->unpublished = true; -} - -/** Remove the global - * - * \param global The Wayland global. - * - * Broadcast a global remove event to all clients without destroying the - * global. This function can only be called once per global. - * - * This can be used by compositors to mitigate clients being disconnected - * because a global has been added and removed too quickly. - * - * Due to the Wayland protocol being asynchronous, the wl_global objects - * cannot be destroyed immediately. For example, if a wl_global is destroyed - * and a client attempts to bind that global around same time, it can - * result in a protocol error due to an unknown global name in the bind request. - * - * In order to avoid crashing clients, the compositor should destroy the - * wl_global once it is guaranteed that no more bind requests will come. - * - * The recommended way to destroy globals is as follows: - * - * - the compositor registers a callback using the wl_global_set_withdrawn_listener() - * function, which will be called when it is safe to call wl_global_destroy(); - * - the compositor calls wl_global_remove(). This will broadcast - * wl_registry.global_remove events to all clients; - * - upon receiving a wl_registry.global_remove event, a client must - * reply to it by calling the wl_fixes.ack_global_remove() request. The - * client must call the wl_fixes.ack_global_remove() request even if it - * did not bind the global; - * - the compositor will call the wl_fixes_handle_ack_global_remove() function when - * it receives the wl_fixes.ack_global_remove() request from the client; - * - after all clients have acknowledged the global removal, the "withdrawn" - * callback will be called to notify the compositor that the - * wl_global_destroy() function can be called now. - * - * \sa wl_global_set_withdrawn_listener - * \sa wl_fixes_handle_ack_global_remove - * \since 1.17.90 - */ -WL_EXPORT void -wl_global_remove(struct wl_global *global) -{ - if (global->unpublished) - wl_abort("wl_global_remove: called twice on the same " - "global '%s#%"PRIu32"'", global->interface->name, - global->name); - - wl_global_unpublish(global); - - if (global->withdrawn && wl_list_empty(&global->offer_list)) - global->withdrawn(global); -} - -/** Set the withdrawn callback. - * - * \param global The Wayland global. - * \param func The withdrawn callback. - * - * The withdrawn callback notifies the compositor that the global can be - * safely destroyed by calling wl_global_destroy(). The callback will be called - * in the following cases: - * - * - immediately by wl_global_remove(), if there are no registeries where the - * global was announced; - * - or some time later after wl_global_remove(), due to either receiving the - * last wl_fixes_handle_ack_global_remove() or getting the last wl_registry - * where the global was announced destroyed. - * - * The withdrawn callback will never be called without prior wl_global_remove(). - * - * \sa wl_fixes_handle_ack_global_remove - * \since 1.26 - */ -WL_EXPORT void -wl_global_set_withdrawn_listener(struct wl_global *global, - wl_global_withdrawn_func_t func) -{ - global->withdrawn = func; -} - WL_EXPORT void wl_global_destroy(struct wl_global *global) { - struct wl_global_offer *offer; - - if (!global->unpublished) - wl_global_unpublish(global); + struct wl_display *display = global->display; + struct wl_resource *resource; + wl_list_for_each(resource, &display->registry_resource_list, link) + wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE, + global->name); wl_list_remove(&global->link); - - while (!wl_list_empty(&global->offer_list)) { - offer = wl_container_of(global->offer_list.next, offer, global_link); - wl_global_offer_destroy(offer); - } - free(global); } -WL_EXPORT const struct wl_interface * -wl_global_get_interface(const struct wl_global *global) -{ - return global->interface; -} - -/** Get the name of the global. - * - * \param global The global object. - * \param client Client for which to look up the global. - * \return The name of the global, or 0 if the global is not visible to the - * client. - * - * \memberof wl_global - * \since 1.22 - */ -WL_EXPORT uint32_t -wl_global_get_name(const struct wl_global *global, - const struct wl_client *client) -{ - return wl_global_is_visible(client, global) ? global->name : 0; -} - -/** Get the version of the given global. - * - * \param global The global object. - * \return The version advertised by the global. - * - * \memberof wl_global - * \since 1.21 - */ -WL_EXPORT uint32_t -wl_global_get_version(const struct wl_global *global) -{ - return global->version; -} - -/** Get the display object for the given global - * - * \param global The global object - * \return The display object the global is associated with. - * - * \memberof wl_global - * \since 1.20 - */ -WL_EXPORT struct wl_display * -wl_global_get_display(const struct wl_global *global) -{ - return global->display; -} - -WL_EXPORT void * -wl_global_get_user_data(const struct wl_global *global) -{ - return global->data; -} - -/** Set the global's user data - * - * \param global The global object - * \param data The user data pointer - * - * \since 1.17.90 - */ -WL_EXPORT void -wl_global_set_user_data(struct wl_global *global, void *data) -{ - global->data = data; -} - /** Get the current serial number * * \param display The display object * * This function returns the most recent serial number, but does not * increment it. - * + * * \memberof wl_display */ WL_EXPORT uint32_t -wl_display_get_serial(const struct wl_display *display) +wl_display_get_serial(struct wl_display *display) { return display->serial; } @@ -1699,7 +953,7 @@ wl_display_get_serial(const struct wl_display *display) * * This function increments the display serial number and returns the * new value. - * + * * \memberof wl_display */ WL_EXPORT uint32_t @@ -1719,26 +973,17 @@ wl_display_get_event_loop(struct wl_display *display) WL_EXPORT void wl_display_terminate(struct wl_display *display) { - int ret; - uint64_t terminate = 1; - - display->run = false; - - ret = write(display->terminate_efd, &terminate, sizeof(terminate)); - if (ret < 0 && errno != EAGAIN) - wl_abort("Write failed at shutdown\n"); + display->run = 0; } WL_EXPORT void wl_display_run(struct wl_display *display) { - display->run = true; + display->run = 1; while (display->run) { wl_display_flush_clients(display); - if (wl_event_loop_dispatch(display->loop, -1) < 0) { - break; - } + wl_event_loop_dispatch(display->loop, -1); } } @@ -1760,75 +1005,6 @@ wl_display_flush_clients(struct wl_display *display) } } -/** Destroy all clients connected to the display - * - * \param display The display object - * - * This function should be called right before wl_display_destroy() to ensure - * all client resources are closed properly. Destroying a client from within - * wl_display_destroy_clients() is safe, but creating one will leak resources - * and raise a warning. - * - * \memberof wl_display - */ -WL_EXPORT void -wl_display_destroy_clients(struct wl_display *display) -{ - struct wl_list tmp_client_list, *pos; - struct wl_client *client; - - /* Move the whole client list to a temporary head because some new clients - * might be added to the original head. */ - wl_list_init(&tmp_client_list); - wl_list_insert_list(&tmp_client_list, &display->client_list); - wl_list_init(&display->client_list); - - /* wl_list_for_each_safe isn't enough here: it fails if the next client is - * destroyed by the destroy handler of the current one. */ - while (!wl_list_empty(&tmp_client_list)) { - pos = tmp_client_list.next; - client = wl_container_of(pos, client, link); - - wl_client_destroy(client); - } - - if (!wl_list_empty(&display->client_list)) { - wl_log("wl_display_destroy_clients: cannot destroy all clients because " - "new ones were created by destroy callbacks\n"); - } -} - -/** Sets the default maximum size for connection buffers of new clients - * - * \param display The display object - * \param max_buffer_size The default maximum size of the connection buffers - * - * This function sets the default size of the internal connection buffers for - * new clients. It doesn't change the buffer size for existing wl_client. - * - * The connection buffer size of an existing wl_client can be adjusted using - * wl_client_set_max_buffer_size(). - * - * The actual size of the connection buffers is a power of two, the requested - * \a max_buffer_size is therefore rounded up to the nearest power of two value. - * - * The minimum buffer size is 4096. - * - * \sa wl_client_set_max_buffer_size - * - * \memberof wl_display - * \since 1.22.90 - */ -WL_EXPORT void -wl_display_set_default_max_buffer_size(struct wl_display *display, - size_t max_buffer_size) -{ - if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE) - max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE; - - display->max_buffer_size = max_buffer_size; -} - static int socket_data(int fd, uint32_t mask, void *data) { @@ -1841,7 +1017,7 @@ socket_data(int fd, uint32_t mask, void *data) client_fd = wl_os_accept_cloexec(fd, (struct sockaddr *) &name, &length); if (client_fd < 0) - wl_log("failed to accept: %s\n", strerror(errno)); + wl_log("failed to accept: %m\n"); else if (!wl_client_create(display, client_fd)) close(client_fd); @@ -1857,7 +1033,7 @@ wl_socket_lock(struct wl_socket *socket) snprintf(socket->lock_addr, sizeof socket->lock_addr, "%s%s", socket->addr.sun_path, LOCK_SUFFIX); - socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC | O_RDWR, + socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); if (socket->fd_lock < 0) { @@ -1872,7 +1048,7 @@ wl_socket_lock(struct wl_socket *socket) goto err_fd; } - if (lstat(socket->addr.sun_path, &socket_stat) < 0 ) { + if (stat(socket->addr.sun_path, &socket_stat) < 0 ) { if (errno != ENOENT) { wl_log("did not manage to stat file %s\n", socket->addr.sun_path); @@ -1902,40 +1078,34 @@ static int wl_socket_init_for_display_name(struct wl_socket *s, const char *name) { int name_size; - const char *runtime_dir = ""; - const char *separator = ""; + const char *runtime_dir; - if (name[0] != '/') { - runtime_dir = getenv("XDG_RUNTIME_DIR"); - if (!runtime_dir || runtime_dir[0] != '/') { - wl_log("error: XDG_RUNTIME_DIR is invalid or not set in" - " the environment\n"); + runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (!runtime_dir) { + wl_log("error: XDG_RUNTIME_DIR not set in the environment\n"); - /* to prevent programs reporting - * "failed to add socket: Success" */ - errno = ENOENT; - return -1; - } - separator = "/"; + /* to prevent programs reporting + * "failed to add socket: Success" */ + errno = ENOENT; + return -1; } s->addr.sun_family = AF_LOCAL; name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path, - "%s%s%s", runtime_dir, separator, name) + 1; + "%s/%s", runtime_dir, name) + 1; - if (!(name_size > 0)) - wl_abort("Error assigning path name for socket address\n"); + s->display_name = (s->addr.sun_path + name_size - 1) - strlen(name); + + assert(name_size > 0); if (name_size > (int)sizeof s->addr.sun_path) { - wl_log("error: socket path \"%s%s%s\" plus null terminator" - " exceeds 108 bytes\n", runtime_dir, separator, name); + wl_log("error: socket path \"%s/%s\" plus null terminator" + " exceeds 108 bytes\n", runtime_dir, name); *s->addr.sun_path = 0; /* to prevent programs reporting * "failed to add socket: Success" */ errno = ENAMETOOLONG; return -1; - } - - s->display_name = (s->addr.sun_path + name_size - 1) - strlen(name); + }; return 0; } @@ -1952,12 +1122,12 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s) size = offsetof (struct sockaddr_un, sun_path) + strlen(s->addr.sun_path); if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) { - wl_log("bind() failed with error: %s\n", strerror(errno)); + wl_log("bind() failed with error: %m\n"); return -1; } - if (listen(s->fd, 128) < 0) { - wl_log("listen() failed with error: %s\n", strerror(errno)); + if (listen(s->fd, 1) < 0) { + wl_log("listen() failed with error: %m\n"); return -1; } @@ -1972,30 +1142,12 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s) return 0; } - -/** Automatically pick a Wayland display socket for the clients to connect to. - * - * \param display Wayland display to which the socket should be added. - * \return The socket name if success. NULL if failed. - * - * This adds a Unix socket to Wayland display which can be used by clients to - * connect to Wayland display. The name of the socket is chosen automatically - * as the first available name in the sequence "wayland-0", "wayland-1", - * "wayland-2", ..., "wayland-32". - * - * The string returned by this function is owned by the library and should - * not be freed. - * - * \sa wl_display_add_socket - * - * \memberof wl_display - */ WL_EXPORT const char * wl_display_add_socket_auto(struct wl_display *display) { struct wl_socket *s; int displayno = 0; - char display_name[20] = ""; + char display_name[16] = ""; /* A reasonable number of maximum default sockets. If * you need more than this, use the explicit add_socket API. */ @@ -2029,80 +1181,6 @@ wl_display_add_socket_auto(struct wl_display *display) return NULL; } -/** Add a socket with an existing fd to Wayland display for the clients to connect. - * - * \param display Wayland display to which the socket should be added. - * \param sock_fd The existing socket file descriptor to be used - * \return 0 if success. -1 if failed. - * - * The existing socket fd must already be created, opened, and locked. - * The fd must be properly set to CLOEXEC and bound to a socket file - * with both bind() and listen() already called. - * - * On success, the socket fd ownership is transferred to libwayland: - * libwayland will close the socket when the display is destroyed. - * - * \memberof wl_display - */ -WL_EXPORT int -wl_display_add_socket_fd(struct wl_display *display, int sock_fd) -{ - struct wl_socket *s; - struct stat buf; - - /* Require a valid fd or fail */ - if (sock_fd < 0 || fstat(sock_fd, &buf) < 0 || !S_ISSOCK(buf.st_mode)) { - return -1; - } - - s = wl_socket_alloc(); - if (s == NULL) - return -1; - - s->source = wl_event_loop_add_fd(display->loop, sock_fd, - WL_EVENT_READABLE, - socket_data, display); - if (s->source == NULL) { - wl_log("failed to establish event source\n"); - wl_socket_destroy(s); - return -1; - } - - /* Reuse the existing fd */ - s->fd = sock_fd; - - wl_list_insert(display->socket_list.prev, &s->link); - - return 0; -} - -/** Add a socket to Wayland display for the clients to connect. - * - * \param display Wayland display to which the socket should be added. - * \param name Name of the Unix socket. - * \return 0 if success. -1 if failed. - * - * This adds a Unix socket to Wayland display which can be used by clients to - * connect to Wayland display. - * - * If NULL is passed as name, then it would look for WAYLAND_DISPLAY env - * variable for the socket name. If WAYLAND_DISPLAY is not set, then default - * wayland-0 is used. - * - * If the socket name is a relative path, the Unix socket will be created in - * the directory pointed to by environment variable XDG_RUNTIME_DIR. If - * XDG_RUNTIME_DIR is invalid or not set, then this function fails and returns -1. - * - * If the socket name is an absolute path, then it is used as-is for the - * the Unix socket. - * - * The length of the computed socket path must not exceed the maximum length - * of a Unix socket path. - * The function also fails if the user does not have write permission in the - * directory or if the path is already in use. - * - * \memberof wl_display - */ WL_EXPORT int wl_display_add_socket(struct wl_display *display, const char *name) { @@ -2139,32 +1217,14 @@ WL_EXPORT void wl_display_add_destroy_listener(struct wl_display *display, struct wl_listener *listener) { - wl_priv_signal_add(&display->destroy_signal, listener); -} - -/** Registers a listener for the client connection signal. - * When a new client object is created, \a listener will be notified, carrying - * a pointer to the new wl_client object. - * - * \ref wl_client_create - * \ref wl_display - * \ref wl_listener - * - * \param display The display object - * \param listener Signal handler object - */ -WL_EXPORT void -wl_display_add_client_created_listener(struct wl_display *display, - struct wl_listener *listener) -{ - wl_priv_signal_add(&display->create_client_signal, listener); + wl_signal_add(&display->destroy_signal, listener); } WL_EXPORT struct wl_listener * wl_display_get_destroy_listener(struct wl_display *display, wl_notify_func_t notify) { - return wl_priv_signal_get(&display->destroy_signal, notify); + return wl_signal_get(&display->destroy_signal, notify); } WL_EXPORT void @@ -2190,18 +1250,6 @@ wl_resource_set_dispatcher(struct wl_resource *resource, resource->destroy = destroy; } -/** Create a new resource object - * - * \param client The client owner of the new resource. - * \param interface The interface of the new resource. - * \param version The version of the new resource. - * \param id The id of the new resource. If 0, an available id will be used. - * - * Listeners added with \a wl_client_add_resource_created_listener will be - * notified at the end of this function. - * - * \memberof wl_resource - */ WL_EXPORT struct wl_resource * wl_resource_create(struct wl_client *client, const struct wl_interface *interface, @@ -2209,24 +1257,18 @@ wl_resource_create(struct wl_client *client, { struct wl_resource *resource; - resource = zalloc(sizeof *resource); + resource = malloc(sizeof *resource); if (resource == NULL) return NULL; - if (id == 0) { + if (id == 0) id = wl_map_insert_new(&client->objects, 0, NULL); - if (id == 0) { - free(resource); - return NULL; - } - } resource->object.id = id; resource->object.interface = interface; resource->object.implementation = NULL; - wl_signal_init(&resource->deprecated_destroy_signal); - wl_priv_signal_init(&resource->destroy_signal); + wl_signal_init(&resource->destroy_signal); resource->destroy = NULL; resource->client = client; @@ -2234,17 +1276,15 @@ wl_resource_create(struct wl_client *client, resource->version = version; resource->dispatcher = NULL; - if (wl_map_insert_at(&client->objects, 0, id, resource) < 0) { - if (errno == EINVAL) { - wl_resource_post_error(client->display_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "invalid new id %d", id); - } + if (wl_map_insert_at(&client->objects, 0, resource->object.id, resource) < 0) { + wl_resource_post_error(client->display_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid new id %d", + resource->object.id); free(resource); return NULL; } - wl_priv_signal_emit(&client->resource_created_signal, resource); return resource; } @@ -2254,60 +1294,101 @@ wl_log_set_handler_server(wl_log_func_t handler) wl_log_handler = handler; } -/** Adds a new protocol logger. - * - * When a new protocol message arrives or is sent from the server - * all the protocol logger functions will be called, carrying the - * \a user_data pointer, the type of the message (request or - * event) and the actual message. - * The lifetime of the messages passed to the logger function ends - * when they return so the messages cannot be stored and accessed - * later. - * - * \a errno is set on error. - * - * \param display The display object - * \param func The function to call to log a new protocol message - * \param user_data The user data pointer to pass to \a func - * - * \return The protocol logger object on success, NULL on failure. - * - * \sa wl_protocol_logger_destroy - * - * \memberof wl_display - */ -WL_EXPORT struct wl_protocol_logger * -wl_display_add_protocol_logger(struct wl_display *display, - wl_protocol_logger_func_t func, void *user_data) +/* Deprecated functions below. */ + +uint32_t +wl_client_add_resource(struct wl_client *client, + struct wl_resource *resource) WL_DEPRECATED; + +WL_EXPORT uint32_t +wl_client_add_resource(struct wl_client *client, + struct wl_resource *resource) { - struct wl_protocol_logger *logger; + if (resource->object.id == 0) { + resource->object.id = + wl_map_insert_new(&client->objects, + WL_MAP_ENTRY_LEGACY, resource); + } else if (wl_map_insert_at(&client->objects, WL_MAP_ENTRY_LEGACY, + resource->object.id, resource) < 0) { + wl_resource_post_error(client->display_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid new id %d", + resource->object.id); + return 0; + } - logger = zalloc(sizeof *logger); - if (!logger) - return NULL; + resource->client = client; + wl_signal_init(&resource->destroy_signal); - logger->func = func; - logger->user_data = user_data; - wl_list_insert(&display->protocol_loggers, &logger->link); - - return logger; + return resource->object.id; } -/** Destroys a protocol logger. - * - * This function destroys a protocol logger and removes it from the display - * it was added to with \a wl_display_add_protocol_logger. - * The \a logger object becomes invalid after calling this function. - * - * \sa wl_display_add_protocol_logger - * - * \memberof wl_protocol_logger - */ -WL_EXPORT void -wl_protocol_logger_destroy(struct wl_protocol_logger *logger) +struct wl_resource * +wl_client_add_object(struct wl_client *client, + const struct wl_interface *interface, + const void *implementation, + uint32_t id, void *data) WL_DEPRECATED; + +WL_EXPORT struct wl_resource * +wl_client_add_object(struct wl_client *client, + const struct wl_interface *interface, + const void *implementation, uint32_t id, void *data) { - wl_list_remove(&logger->link); - free(logger); + struct wl_resource *resource; + + resource = wl_resource_create(client, interface, -1, id); + if (resource == NULL) + wl_client_post_no_memory(client); + else + wl_resource_set_implementation(resource, + implementation, data, NULL); + + return resource; +} + +struct wl_resource * +wl_client_new_object(struct wl_client *client, + const struct wl_interface *interface, + const void *implementation, void *data) WL_DEPRECATED; + +WL_EXPORT struct wl_resource * +wl_client_new_object(struct wl_client *client, + const struct wl_interface *interface, + const void *implementation, void *data) +{ + struct wl_resource *resource; + + resource = wl_resource_create(client, interface, -1, 0); + if (resource == NULL) + wl_client_post_no_memory(client); + else + wl_resource_set_implementation(resource, + implementation, data, NULL); + + return resource; +} + +struct wl_global * +wl_display_add_global(struct wl_display *display, + const struct wl_interface *interface, + void *data, wl_global_bind_func_t bind) WL_DEPRECATED; + +WL_EXPORT struct wl_global * +wl_display_add_global(struct wl_display *display, + const struct wl_interface *interface, + void *data, wl_global_bind_func_t bind) +{ + return wl_global_create(display, interface, interface->version, data, bind); +} + +void +wl_display_remove_global(struct wl_display *display, + struct wl_global *global) WL_DEPRECATED; + +WL_EXPORT void +wl_display_remove_global(struct wl_display *display, struct wl_global *global) +{ + wl_global_destroy(global); } /** Add support for a wl_shm pixel format @@ -2351,11 +1432,9 @@ wl_display_add_shm_format(struct wl_display *display, uint32_t format) * WL_SHM_FORMAT_XRGB8888 are always supported and not included in the * array, but all formats added through wl_display_add_shm_format() * will be in the array. - * + * * \sa wl_display_add_shm_format() - * - * \private - * + * * \memberof wl_display */ struct wl_array * @@ -2363,542 +1442,3 @@ wl_display_get_additional_shm_formats(struct wl_display *display) { return &display->additional_shm_formats; } - -/** Get the list of currently connected clients - * - * \param display The display object - * - * This function returns a pointer to the list of clients currently - * connected to the display. You can iterate on the list by using - * the \a wl_client_for_each macro. - * The returned value is valid for the lifetime of the \a display. - * You must not modify the returned list, but only access it. - * - * \sa wl_client_for_each() - * \sa wl_client_get_link() - * \sa wl_client_from_link() - * - * \memberof wl_display - */ -WL_EXPORT struct wl_list * -wl_display_get_client_list(struct wl_display *display) -{ - return &display->client_list; -} - -/** Get the link by which a client is inserted in the client list - * - * \param client The client object - * - * \sa wl_client_for_each() - * \sa wl_display_get_client_list() - * \sa wl_client_from_link() - * - * \memberof wl_client - */ -WL_EXPORT struct wl_list * -wl_client_get_link(struct wl_client *client) -{ - return &client->link; -} - -/** Get a wl_client by its link - * - * \param link The link of a wl_client - * - * \sa wl_client_for_each() - * \sa wl_display_get_client_list() - * \sa wl_client_get_link() - * - * \memberof wl_client - */ -WL_EXPORT struct wl_client * -wl_client_from_link(struct wl_list *link) -{ - struct wl_client *client; - - return wl_container_of(link, client, link); -} - -/** Add a listener for the client's resource creation signal - * - * \param client The client object - * \param listener The listener to be added - * - * When a new resource is created for this client the listener - * will be notified, carrying the new resource as the data argument. - * - * \memberof wl_client - */ -WL_EXPORT void -wl_client_add_resource_created_listener(struct wl_client *client, - struct wl_listener *listener) -{ - wl_priv_signal_add(&client->resource_created_signal, listener); -} - -struct wl_resource_iterator_context { - void *user_data; - wl_client_for_each_resource_iterator_func_t it; -}; - -static enum wl_iterator_result -resource_iterator_helper(void *res, void *user_data, uint32_t flags) -{ - struct wl_resource_iterator_context *context = user_data; - struct wl_resource *resource = res; - - return context->it(resource, context->user_data); -} - -/** Iterate over all the resources of a client - * - * \param client The client object - * \param iterator The iterator function - * \param user_data The user data pointer - * - * The function pointed by \a iterator will be called for each - * resource owned by the client. The \a user_data will be passed - * as the second argument of the iterator function. - * If the \a iterator function returns \a WL_ITERATOR_CONTINUE the iteration - * will continue, if it returns \a WL_ITERATOR_STOP it will stop. - * - * Creating and destroying resources while iterating is safe, but new - * resources may or may not be picked up by the iterator. - * - * \sa wl_iterator_result - * - * \memberof wl_client - */ -WL_EXPORT void -wl_client_for_each_resource(struct wl_client *client, - wl_client_for_each_resource_iterator_func_t iterator, - void *user_data) -{ - struct wl_resource_iterator_context context = { - .user_data = user_data, - .it = iterator, - }; - - wl_map_for_each(&client->objects, resource_iterator_helper, &context); -} - -static void -handle_noop(struct wl_listener *listener, void *data) -{ - /* Do nothing */ -} - -/** Emits this signal, notifying all registered listeners. - * - * A safer version of wl_signal_emit() which can gracefully handle additions - * and deletions of any signal listener from within listener notification - * callbacks. - * - * Listeners deleted during a signal emission and which have not already been - * notified at the time of deletion are not notified by that emission. - * - * Listeners added (or readded) during signal emission are ignored by that - * emission. - * - * Note that repurposing a listener without explicitly removing it and readding - * it is not supported and can lead to unexpected behavior. - * - * \param signal The signal object that will emit the signal - * \param data The data that will be emitted with the signal - * - * \memberof wl_signal - * \since 1.20.90 - */ -WL_EXPORT void -wl_signal_emit_mutable(struct wl_signal *signal, void *data) -{ - struct wl_listener cursor; - struct wl_listener end; - - /* Add two special markers: one cursor and one end marker. This way, we - * know that we've already called listeners on the left of the cursor - * and that we don't want to call listeners on the right of the end - * marker. The 'it' function can remove any element it wants from the - * list without troubles. - * - * There was a previous attempt that used to steal the whole list of - * listeners but then that broke wl_signal_get(). - * - * wl_list_for_each_safe tries to be safe but it fails: it works fine - * if the current item is removed, but not if the next one is. */ - wl_list_insert(&signal->listener_list, &cursor.link); - cursor.notify = handle_noop; - wl_list_insert(signal->listener_list.prev, &end.link); - end.notify = handle_noop; - - while (cursor.link.next != &end.link) { - struct wl_list *pos = cursor.link.next; - struct wl_listener *l = wl_container_of(pos, l, link); - - wl_list_remove(&cursor.link); - wl_list_insert(pos, &cursor.link); - - l->notify(l, data); - } - - wl_list_remove(&cursor.link); - wl_list_remove(&end.link); -} - -/** Adjust the maximum size of the client connection buffers - * - * \param client The client object - * \param max_buffer_size The maximum size of the connection buffers - * - * The actual size of the connection buffers is a power of two, the requested - * \a max_buffer_size is therefore rounded up to the nearest power of two value. - * - * Lowering the maximum size may not take effect immediately if the current content - * of the buffer does not fit within the new size limit. - * - * The minimum buffer size is 4096. The default buffers size can be set using - * wl_display_set_default_max_buffer_size(). - * - * \sa wl_display_set_default_max_buffer_size() - * - * \memberof wl_client - * \since 1.22.90 - */ -WL_EXPORT void -wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size) -{ - if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE) - max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE; - - wl_connection_set_max_buffer_size(client->connection, max_buffer_size); -} - -/** \cond INTERNAL */ - -/** Initialize a wl_priv_signal object - * - * wl_priv_signal is a safer implementation of a signal type, with the same API - * as wl_signal, but kept as a private utility of libwayland-server. - * It is safer because listeners can be removed from within wl_priv_signal_emit() - * without corrupting the signal's list. - * - * Before passing a wl_priv_signal object to any other function it must be - * initialized by using wl_priv_signal_init(). - * - * \memberof wl_priv_signal - */ -void -wl_priv_signal_init(struct wl_priv_signal *signal) -{ - wl_list_init(&signal->listener_list); - wl_list_init(&signal->emit_list); -} - -/** Add a listener to a signal - * - * The new listener will be called when calling wl_signal_emit(). If a listener is - * added to the signal while wl_signal_emit() is running it will be called from - * the next time wl_priv_signal_emit() is called. - * To remove a listener call wl_list_remove() on its link member. - * - * \memberof wl_priv_signal - */ -void -wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener) -{ - wl_list_insert(signal->listener_list.prev, &listener->link); -} - -/** Get a listener added to a signal - * - * Returns the listener added to the given \a signal and with the given - * \a notify function, or NULL if there isn't any. - * Calling this function from within wl_priv_signal_emit() is safe and will - * return the correct value. - * - * \memberof wl_priv_signal - */ -struct wl_listener * -wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify) -{ - struct wl_listener *l; - - wl_list_for_each(l, &signal->listener_list, link) - if (l->notify == notify) - return l; - wl_list_for_each(l, &signal->emit_list, link) - if (l->notify == notify) - return l; - - return NULL; -} - -/** Emit the signal, calling all the installed listeners - * - * Iterate over all the listeners added to this \a signal and call - * their \a notify function pointer, passing on the given \a data. - * Removing or adding a listener from within wl_priv_signal_emit() - * is safe. - */ -void -wl_priv_signal_emit(struct wl_priv_signal *signal, void *data) -{ - struct wl_listener *l; - struct wl_list *pos; - - wl_list_insert_list(&signal->emit_list, &signal->listener_list); - wl_list_init(&signal->listener_list); - - /* Take every element out of the list and put them in a temporary list. - * This way, the 'it' func can remove any element it wants from the list - * without troubles, because we always get the first element, not the - * one after the current, which may be invalid. - * wl_list_for_each_safe tries to be safe but it fails: it works fine - * if the current item is removed, but not if the next one is. */ - while (!wl_list_empty(&signal->emit_list)) { - pos = signal->emit_list.next; - l = wl_container_of(pos, l, link); - - wl_list_remove(pos); - wl_list_insert(&signal->listener_list, pos); - - l->notify(l, data); - } -} - -/** Emit the signal for the last time, calling all the installed listeners - * - * Iterate over all the listeners added to this \a signal and call - * their \a notify function pointer, passing on the given \a data. - * Removing or adding a listener from within wl_priv_signal_emit() - * is safe, as is freeing the structure containing the listener. - * - * A large body of external code assumes it's ok to free a destruction - * listener without removing that listener from the list. Mixing code - * that acts like this and code that doesn't will result in list - * corruption. - * - * We resolve this by removing each item from the list and isolating it - * in another list. We discard it completely after firing the notifier. - * This should allow interoperability between code that unlinks its - * destruction listeners and code that just frees structures they're in. - * - */ -void -wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data) -{ - struct wl_listener *l; - struct wl_list *pos; - - /* During a destructor notifier isolate every list item before - * notifying. This renders harmless the long standing misuse - * of freeing listeners without removing them, but allows - * callers that do choose to remove them to interoperate with - * ones that don't. */ - while (!wl_list_empty(&signal->listener_list)) { - pos = signal->listener_list.next; - l = wl_container_of(pos, l, link); - - wl_list_remove(pos); - wl_list_init(pos); - - l->notify(l, data); - } -} - -/** \endcond INTERNAL */ - -/** \cond */ /* Deprecated functions below. */ - -WL_DEPRECATED -uint32_t -wl_client_add_resource(struct wl_client *client, - struct wl_resource *resource); - -WL_EXPORT uint32_t -wl_client_add_resource(struct wl_client *client, - struct wl_resource *resource) -{ - if (resource->object.id == 0) { - resource->object.id = - wl_map_insert_new(&client->objects, - WL_MAP_ENTRY_LEGACY, resource); - if (resource->object.id == 0) - return 0; - } else if (wl_map_insert_at(&client->objects, WL_MAP_ENTRY_LEGACY, - resource->object.id, resource) < 0) { - if (errno == EINVAL) { - wl_resource_post_error(client->display_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "invalid new id %d", - resource->object.id); - } - return 0; - } - - resource->client = client; - wl_signal_init(&resource->deprecated_destroy_signal); - - return resource->object.id; -} - -WL_DEPRECATED -struct wl_resource * -wl_client_add_object(struct wl_client *client, - const struct wl_interface *interface, - const void *implementation, - uint32_t id, void *data); - -WL_EXPORT struct wl_resource * -wl_client_add_object(struct wl_client *client, - const struct wl_interface *interface, - const void *implementation, uint32_t id, void *data) -{ - struct wl_resource *resource; - - resource = wl_resource_create(client, interface, -1, id); - if (resource == NULL) - wl_client_post_no_memory(client); - else - wl_resource_set_implementation(resource, - implementation, data, NULL); - - return resource; -} - -WL_DEPRECATED -struct wl_resource * -wl_client_new_object(struct wl_client *client, - const struct wl_interface *interface, - const void *implementation, void *data); - -WL_EXPORT struct wl_resource * -wl_client_new_object(struct wl_client *client, - const struct wl_interface *interface, - const void *implementation, void *data) -{ - struct wl_resource *resource; - - resource = wl_resource_create(client, interface, -1, 0); - if (resource == NULL) - wl_client_post_no_memory(client); - else - wl_resource_set_implementation(resource, - implementation, data, NULL); - - return resource; -} - -/** Set the client's user data - * - * User data is whatever the caller wants to store. Use dtor if - * the user data needs freeing as the very last step of destroying - * the client. - * - * \param client The client object - * \param data The user data pointer - * \param dtor Destroy function to be called after all resources have been - * destroyed and all destroy listeners have been called. Can be NULL. - * - * The argument to the destroy function is the user data pointer. If the - * destroy function is not NULL, it will be called even if user data is NULL. - * - * \since 1.22.90 - * \sa wl_client_get_user_data - */ -WL_EXPORT void -wl_client_set_user_data(struct wl_client *client, - void *data, - wl_user_data_destroy_func_t dtor) -{ - client->data = data; - client->data_dtor = dtor; -} - -/** Get the client's user data - * - * \param client The client object - * \return The user data pointer - * - * \since 1.22.90 - * \sa wl_client_set_user_data - */ -WL_EXPORT void * -wl_client_get_user_data(struct wl_client *client) -{ - return client->data; -} - -WL_DEPRECATED -struct wl_global * -wl_display_add_global(struct wl_display *display, - const struct wl_interface *interface, - void *data, wl_global_bind_func_t bind); - -WL_EXPORT struct wl_global * -wl_display_add_global(struct wl_display *display, - const struct wl_interface *interface, - void *data, wl_global_bind_func_t bind) -{ - return wl_global_create(display, interface, interface->version, data, bind); -} - -WL_DEPRECATED -void -wl_display_remove_global(struct wl_display *display, - struct wl_global *global); - -WL_EXPORT void -wl_display_remove_global(struct wl_display *display, struct wl_global *global) -{ - wl_global_destroy(global); -} - -/** Acknowledge global removal by a client - * - * \param fixes_resource The wl_fixes resource. - * \param registry_resource The wl_registry resource. - * \param global_name The unique id of the global. - * - * The compositor should call this function from the wl_fixes.ack_global_remove - * request implementation. - * - * libwayland-server automatically takes care of the implied ack-remove due - * to client disconnection or explicit wl_resource_destroy() of the wl_registry - * resource. - * - * \sa wl_global_remove - * \sa wl_global_set_withdrawn_listener - * \since 1.26 - */ -WL_EXPORT void -wl_fixes_handle_ack_global_remove(struct wl_resource *fixes_resource, - struct wl_resource *registry_resource, - uint32_t global_name) -{ - struct wl_global_offer *offer; - struct wl_registry *registry = registry_resource->data; - - offer = wl_registry_find_offer(registry, global_name); - if (!offer) { - wl_resource_post_error(fixes_resource, WL_FIXES_ERROR_INVALID_ACK_REMOVE, - "the given registry did not announce global %u", global_name); - return; - } - - if (!offer->global->unpublished) { - wl_resource_post_error(fixes_resource, WL_FIXES_ERROR_INVALID_ACK_REMOVE, - "global %u is not removed", global_name); - return; - } - - wl_global_offer_done(offer); -} - -/** \endcond */ - -/* Functions at the end of this file are deprecated. Instead of adding new - * code here, add it before the comment above that states: - * Deprecated functions below. - */ diff --git a/src/wayland-server.h b/src/wayland-server.h index 48fab1dd..38855c90 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -1,58 +1,268 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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: + * 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 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. - */ - -/** \file - * - * \brief Include the server API, deprecations and protocol C API. - * - * \warning Use of this header file is discouraged. Prefer including - * wayland-server-core.h instead, which does not include the - * server protocol header and as such only defines the library - * API, excluding the deprecated API below. + * 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 WAYLAND_SERVER_H #define WAYLAND_SERVER_H -#include -#include "wayland-server-core.h" - #ifdef __cplusplus extern "C" { #endif -/* - * The user can set this macro to hide the wl_object, wl_resource and wl_buffer - * objects alongside the associated API. +#include +#include +#include "wayland-util.h" +#include "wayland-version.h" + +enum { + WL_EVENT_READABLE = 0x01, + WL_EVENT_WRITABLE = 0x02, + WL_EVENT_HANGUP = 0x04, + WL_EVENT_ERROR = 0x08 +}; + +struct wl_event_loop; +struct wl_event_source; +typedef int (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data); +typedef int (*wl_event_loop_timer_func_t)(void *data); +typedef int (*wl_event_loop_signal_func_t)(int signal_number, void *data); +typedef void (*wl_event_loop_idle_func_t)(void *data); + +struct wl_event_loop *wl_event_loop_create(void); +void wl_event_loop_destroy(struct wl_event_loop *loop); +struct wl_event_source *wl_event_loop_add_fd(struct wl_event_loop *loop, + int fd, uint32_t mask, + wl_event_loop_fd_func_t func, + void *data); +int wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask); +struct wl_event_source *wl_event_loop_add_timer(struct wl_event_loop *loop, + wl_event_loop_timer_func_t func, + void *data); +struct wl_event_source * +wl_event_loop_add_signal(struct wl_event_loop *loop, + int signal_number, + wl_event_loop_signal_func_t func, + void *data); + +int wl_event_source_timer_update(struct wl_event_source *source, + int ms_delay); +int wl_event_source_remove(struct wl_event_source *source); +void wl_event_source_check(struct wl_event_source *source); + + +int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout); +void wl_event_loop_dispatch_idle(struct wl_event_loop *loop); +struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop, + wl_event_loop_idle_func_t func, + void *data); +int wl_event_loop_get_fd(struct wl_event_loop *loop); + +struct wl_client; +struct wl_display; +struct wl_listener; +struct wl_resource; +struct wl_global; +typedef void (*wl_notify_func_t)(struct wl_listener *listener, void *data); + +void wl_event_loop_add_destroy_listener(struct wl_event_loop *loop, + struct wl_listener * listener); +struct wl_listener *wl_event_loop_get_destroy_listener( + struct wl_event_loop *loop, + wl_notify_func_t notify); + +struct wl_display *wl_display_create(void); +void wl_display_destroy(struct wl_display *display); +struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); +int wl_display_add_socket(struct wl_display *display, const char *name); +const char *wl_display_add_socket_auto(struct wl_display *display); +void wl_display_terminate(struct wl_display *display); +void wl_display_run(struct wl_display *display); +void wl_display_flush_clients(struct wl_display *display); + +typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data, + uint32_t version, uint32_t id); + +uint32_t wl_display_get_serial(struct wl_display *display); +uint32_t wl_display_next_serial(struct wl_display *display); + +void wl_display_add_destroy_listener(struct wl_display *display, + struct wl_listener *listener); +struct wl_listener *wl_display_get_destroy_listener(struct wl_display *display, + wl_notify_func_t notify); + +struct wl_global *wl_global_create(struct wl_display *display, + const struct wl_interface *interface, + int version, + void *data, wl_global_bind_func_t bind); +void wl_global_destroy(struct wl_global *global); + +struct wl_client *wl_client_create(struct wl_display *display, int fd); +void wl_client_destroy(struct wl_client *client); +void wl_client_flush(struct wl_client *client); +void wl_client_get_credentials(struct wl_client *client, + pid_t *pid, uid_t *uid, gid_t *gid); + +void wl_client_add_destroy_listener(struct wl_client *client, + struct wl_listener *listener); +struct wl_listener *wl_client_get_destroy_listener(struct wl_client *client, + wl_notify_func_t notify); + +struct wl_resource * +wl_client_get_object(struct wl_client *client, uint32_t id); +void +wl_client_post_no_memory(struct wl_client *client); + +/** \class wl_listener * - * The structs were meant to be opaque, although we missed that in the early days. + * \brief A single listener for Wayland signals * - * NOTE: the list of structs, functions, etc in this section MUST NEVER GROW. - * Otherwise we will break forward compatibility and applications that used to - * build fine will no longer be able to do so. + * wl_listener provides the means to listen for wl_signal notifications. Many + * Wayland objects use wl_listener for notification of significant events like + * object destruction. + * + * Clients should create wl_listener objects manually and can register them as + * listeners to signals using #wl_signal_add, assuming the signal is + * directly accessible. For opaque structs like wl_event_loop, adding a + * listener should be done through provided accessor methods. A listener can + * only listen to one signal at a time. + * + * ~~~ + * struct wl_listener your_listener; + * + * your_listener.notify = your_callback_method; + * + * \comment{Direct access} + * wl_signal_add(&some_object->destroy_signal, &your_listener); + * + * \comment{Accessor access} + * wl_event_loop *loop = ...; + * wl_event_loop_add_destroy_listener(loop, &your_listener); + * ~~~ + * + * If the listener is part of a larger struct, #wl_container_of can be used + * to retrieve a pointer to it: + * + * \code + * void your_listener(struct wl_listener *listener, void *data) + * { + * struct your_data *data; + * + * your_data = wl_container_of(listener, data, your_member_name); + * } + * \endcode + * + * If you need to remove a listener from a signal, use wl_list_remove(). + * + * \code + * wl_list_remove(&your_listener.link); + * \endcode + * + * \sa wl_signal */ +struct wl_listener { + struct wl_list link; + wl_notify_func_t notify; +}; + +/** \class wl_signal + * + * \brief A source of a type of observable event + * + * Signals are recognized points where significant events can be observed. + * Compositors as well as the server can provide signals. Observers are + * wl_listener's that are added through #wl_signal_add. Signals are emitted + * using #wl_signal_emit, which will invoke all listeners until that + * listener is removed by wl_list_remove() (or whenever the signal is + * destroyed). + * + * \sa wl_listener for more information on using wl_signal + */ +struct wl_signal { + struct wl_list listener_list; +}; + +/** Initialize a new \ref wl_signal for use. + * + * \param signal The signal that will be initialized + * + * \memberof wl_signal + */ +static inline void +wl_signal_init(struct wl_signal *signal) +{ + wl_list_init(&signal->listener_list); +} + +/** Add the specified listener to this signal. + * + * \param signal The signal that will emit events to the listener + * \param listener The listener to add + * + * \memberof wl_signal + */ +static inline void +wl_signal_add(struct wl_signal *signal, struct wl_listener *listener) +{ + wl_list_insert(signal->listener_list.prev, &listener->link); +} + +/** Gets the listener struct for the specified callback. + * + * \param signal The signal that contains the specified listener + * \param notify The listener that is the target of this search + * \return the list item that corresponds to the specified listener, or NULL + * if none was found + * + * \memberof wl_signal + */ +static inline struct wl_listener * +wl_signal_get(struct wl_signal *signal, wl_notify_func_t notify) +{ + struct wl_listener *l; + + wl_list_for_each(l, &signal->listener_list, link) + if (l->notify == notify) + return l; + + return NULL; +} + +/** Emits this signal, notifying all registered listeners. + * + * \param signal The signal object that will emit the signal + * \param data The data that will be emitted with the signal + * + * \memberof wl_signal + */ +static inline void +wl_signal_emit(struct wl_signal *signal, void *data) +{ + struct wl_listener *l, *next; + + wl_list_for_each_safe(l, next, &signal->listener_list, link) + l->notify(l, data); +} + +typedef void (*wl_resource_destroy_func_t)(struct wl_resource *resource); + #ifndef WL_HIDE_DEPRECATED struct wl_object { @@ -70,42 +280,178 @@ struct wl_resource { void *data; }; -WL_DEPRECATED +struct wl_buffer { + struct wl_resource resource; + int32_t width, height; + uint32_t busy_count; +} WL_DEPRECATED; + + uint32_t wl_client_add_resource(struct wl_client *client, - struct wl_resource *resource); + struct wl_resource *resource) WL_DEPRECATED; -WL_DEPRECATED struct wl_resource * wl_client_add_object(struct wl_client *client, const struct wl_interface *interface, const void *implementation, - uint32_t id, void *data); - -WL_DEPRECATED + uint32_t id, void *data) WL_DEPRECATED; struct wl_resource * wl_client_new_object(struct wl_client *client, const struct wl_interface *interface, - const void *implementation, void *data); + const void *implementation, void *data) WL_DEPRECATED; -WL_DEPRECATED struct wl_global * wl_display_add_global(struct wl_display *display, const struct wl_interface *interface, void *data, - wl_global_bind_func_t bind); + wl_global_bind_func_t bind) WL_DEPRECATED; -WL_DEPRECATED void wl_display_remove_global(struct wl_display *display, - struct wl_global *global); + struct wl_global *global) WL_DEPRECATED; #endif +/* + * Post an event to the client's object referred to by 'resource'. + * 'opcode' is the event number generated from the protocol XML + * description (the event name). The variable arguments are the event + * parameters, in the order they appear in the protocol XML specification. + * + * The variable arguments' types are: + * - type=uint: uint32_t + * - type=int: int32_t + * - type=fixed: wl_fixed_t + * - type=string: (const char *) to a nil-terminated string + * - type=array: (struct wl_array *) + * - type=fd: int, that is an open file descriptor + * - type=new_id: (struct wl_object *) or (struct wl_resource *) + * - type=object: (struct wl_object *) or (struct wl_resource *) + */ +void wl_resource_post_event(struct wl_resource *resource, + uint32_t opcode, ...); +void wl_resource_post_event_array(struct wl_resource *resource, + uint32_t opcode, union wl_argument *args); +void wl_resource_queue_event(struct wl_resource *resource, + uint32_t opcode, ...); +void wl_resource_queue_event_array(struct wl_resource *resource, + uint32_t opcode, union wl_argument *args); + +/* msg is a printf format string, variable args are its args. */ +void wl_resource_post_error(struct wl_resource *resource, + uint32_t code, const char *msg, ...) + __attribute__ ((format (printf, 3, 4))); +void wl_resource_post_no_memory(struct wl_resource *resource); + +#include "wayland-server-protocol.h" + +struct wl_display * +wl_client_get_display(struct wl_client *client); + +struct wl_resource * +wl_resource_create(struct wl_client *client, + const struct wl_interface *interface, + int version, uint32_t id); +void +wl_resource_set_implementation(struct wl_resource *resource, + const void *implementation, + void *data, + wl_resource_destroy_func_t destroy); +void +wl_resource_set_dispatcher(struct wl_resource *resource, + wl_dispatcher_func_t dispatcher, + const void *implementation, + void *data, + wl_resource_destroy_func_t destroy); + +void +wl_resource_destroy(struct wl_resource *resource); +uint32_t +wl_resource_get_id(struct wl_resource *resource); +struct wl_list * +wl_resource_get_link(struct wl_resource *resource); +struct wl_resource * +wl_resource_from_link(struct wl_list *resource); +struct wl_resource * +wl_resource_find_for_client(struct wl_list *list, struct wl_client *client); +struct wl_client * +wl_resource_get_client(struct wl_resource *resource); +void +wl_resource_set_user_data(struct wl_resource *resource, void *data); +void * +wl_resource_get_user_data(struct wl_resource *resource); +int +wl_resource_get_version(struct wl_resource *resource); +void +wl_resource_set_destructor(struct wl_resource *resource, + wl_resource_destroy_func_t destroy); +int +wl_resource_instance_of(struct wl_resource *resource, + const struct wl_interface *interface, + const void *implementation); + +void +wl_resource_add_destroy_listener(struct wl_resource *resource, + struct wl_listener * listener); +struct wl_listener * +wl_resource_get_destroy_listener(struct wl_resource *resource, + wl_notify_func_t notify); + +#define wl_resource_for_each(resource, list) \ + for (resource = 0, resource = wl_resource_from_link((list)->next); \ + wl_resource_get_link(resource) != (list); \ + resource = wl_resource_from_link(wl_resource_get_link(resource)->next)) + +#define wl_resource_for_each_safe(resource, tmp, list) \ + for (resource = 0, tmp = 0, \ + resource = wl_resource_from_link((list)->next), \ + tmp = wl_resource_from_link((list)->next->next); \ + wl_resource_get_link(resource) != (list); \ + resource = tmp, \ + tmp = wl_resource_from_link(wl_resource_get_link(resource)->next)) + +struct wl_shm_buffer; + +void +wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer); + +void +wl_shm_buffer_end_access(struct wl_shm_buffer *buffer); + +struct wl_shm_buffer * +wl_shm_buffer_get(struct wl_resource *resource); + +void * +wl_shm_buffer_get_data(struct wl_shm_buffer *buffer); + +int32_t +wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer); + +uint32_t +wl_shm_buffer_get_format(struct wl_shm_buffer *buffer); + +int32_t +wl_shm_buffer_get_width(struct wl_shm_buffer *buffer); + +int32_t +wl_shm_buffer_get_height(struct wl_shm_buffer *buffer); + +int +wl_display_init_shm(struct wl_display *display); + +uint32_t * +wl_display_add_shm_format(struct wl_display *display, uint32_t format); + +struct wl_shm_buffer * +wl_shm_buffer_create(struct wl_client *client, + uint32_t id, int32_t width, int32_t height, + int32_t stride, uint32_t format); + +void wl_log_set_handler_server(wl_log_func_t handler); + #ifdef __cplusplus } #endif -#include "wayland-server-protocol.h" - #endif diff --git a/src/wayland-server.pc.in b/src/wayland-server.pc.in new file mode 100644 index 00000000..50dff533 --- /dev/null +++ b/src/wayland-server.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +datarootdir=@datarootdir@ +pkgdatadir=@datadir@/@PACKAGE@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Wayland Server +Description: Server side implementation of the Wayland protocol +Version: @WAYLAND_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lwayland-server diff --git a/src/wayland-shm.c b/src/wayland-shm.c index 3ac4add2..3fce678e 100644 --- a/src/wayland-shm.c +++ b/src/wayland-shm.c @@ -1,26 +1,23 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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: + * 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 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. + * 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. * * Authors: * Kristian Høgsberg @@ -30,23 +27,15 @@ #define _GNU_SOURCE -#include "config.h" - -#include #include #include -#include #include #include -#include #include +#include #include #include -#include -#include -#include "wayland-os.h" -#include "wayland-util.h" #include "wayland-private.h" #include "wayland-server.h" @@ -59,35 +48,13 @@ static struct sigaction wl_shm_old_sigbus_action; struct wl_shm_pool { struct wl_resource *resource; - int internal_refcount; - int external_refcount; + int refcount; char *data; - ssize_t size; - ssize_t new_size; -#ifndef MREMAP_MAYMOVE - /* The following three fields are needed for mremap() emulation. */ - int mmap_fd; - int mmap_flags; - int mmap_prot; -#endif - bool sigbus_is_impossible; + int32_t size; }; -/** \class wl_shm_buffer - * - * \brief A SHM buffer - * - * wl_shm_buffer provides a helper for accessing the contents of a wl_buffer - * resource created via the wl_shm interface. - * - * A wl_shm_buffer becomes invalid as soon as its #wl_resource is destroyed. - */ struct wl_shm_buffer { struct wl_resource *resource; - int internal_refcount; - int external_refcount; - struct wl_client *client; - struct wl_listener client_destroy_listener; int32_t width, height; int32_t stride; uint32_t format; @@ -101,106 +68,25 @@ struct wl_shm_sigbus_data { int fallback_mapping_used; }; -static void * -shm_pool_grow_mapping(struct wl_shm_pool *pool) -{ - void *data; - -#ifdef MREMAP_MAYMOVE - data = mremap(pool->data, pool->size, pool->new_size, MREMAP_MAYMOVE); -#else - data = wl_os_mremap_maymove(pool->mmap_fd, pool->data, &pool->size, - pool->new_size, pool->mmap_prot, - pool->mmap_flags); - if (pool->size != 0 && pool->resource != NULL) { - wl_resource_post_error(pool->resource, - WL_SHM_ERROR_INVALID_FD, - "leaked old mapping"); - } -#endif - return data; -} - static void -shm_pool_finish_resize(struct wl_shm_pool *pool) +shm_pool_unref(struct wl_shm_pool *pool) { - void *data; - - if (pool->size == pool->new_size) - return; - - data = shm_pool_grow_mapping(pool); - if (data == MAP_FAILED) { - if (pool->resource != NULL) - wl_resource_post_error(pool->resource, - WL_SHM_ERROR_INVALID_FD, - "failed mremap"); - return; - } - - pool->data = data; - pool->size = pool->new_size; -} - -static void -shm_pool_unref(struct wl_shm_pool *pool, bool external) -{ - if (external) { - pool->external_refcount--; - if (pool->external_refcount < 0) - wl_abort("Requested to unref an external reference to " - "pool but none found\n"); - if (pool->external_refcount == 0) - shm_pool_finish_resize(pool); - } else { - pool->internal_refcount--; - if (pool->internal_refcount < 0) - wl_abort("Requested to unref an internal reference to " - "pool but none found\n"); - } - - if (pool->internal_refcount + pool->external_refcount > 0) + pool->refcount--; + if (pool->refcount) return; munmap(pool->data, pool->size); -#ifndef MREMAP_MAYMOVE - close(pool->mmap_fd); -#endif free(pool); } -static void -shm_buffer_unref(struct wl_shm_buffer *buffer, bool external) -{ - if (external) { - buffer->external_refcount--; - if (buffer->external_refcount < 0) { - wl_abort("Requested to unref an external reference to " - "buffer but none found\n"); - } - } else { - buffer->internal_refcount--; - if (buffer->internal_refcount < 0) { - wl_abort("Requested to unref an internal reference to " - "buffer but none found\n"); - } - } - - if (buffer->internal_refcount + buffer->external_refcount > 0) - return; - - if (buffer->client) - wl_list_remove(&buffer->client_destroy_listener.link); - shm_pool_unref(buffer->pool, false); - free(buffer); -} - static void destroy_buffer(struct wl_resource *resource) { struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource); - shm_buffer_unref(buffer, false); + if (buffer->pool) + shm_pool_unref(buffer->pool); + free(buffer); } static void @@ -213,7 +99,7 @@ static const struct wl_buffer_interface shm_buffer_interface = { shm_buffer_destroy }; -static bool +static int format_is_supported(struct wl_client *client, uint32_t format) { struct wl_display *display = wl_client_get_display(client); @@ -223,26 +109,15 @@ format_is_supported(struct wl_client *client, uint32_t format) switch (format) { case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_XRGB8888: - return true; + return 1; default: formats = wl_display_get_additional_shm_formats(display); wl_array_for_each(p, formats) - if (*p == format) - return true; + if(*p == format) + return 1; } - return false; -} - - -static void -shm_buffer_client_destroy_notify(struct wl_listener *listener, void *data) -{ - struct wl_shm_buffer *buffer = - wl_container_of(listener, buffer, client_destroy_listener); - - buffer->client = NULL; - wl_list_remove(&buffer->client_destroy_listener.link); + return 0; } static void @@ -262,7 +137,7 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource, } if (offset < 0 || width <= 0 || height <= 0 || stride < width || - INT32_MAX / stride < height || + INT32_MAX / stride <= height || offset > pool->size - stride * height) { wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_STRIDE, @@ -271,33 +146,25 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource, return; } - buffer = zalloc(sizeof *buffer); + buffer = malloc(sizeof *buffer); if (buffer == NULL) { wl_client_post_no_memory(client); return; } - buffer->client = client; - buffer->client_destroy_listener.notify = - shm_buffer_client_destroy_notify; - wl_client_add_destroy_listener(buffer->client, - &buffer->client_destroy_listener); - - buffer->internal_refcount = 1; - buffer->external_refcount = 0; buffer->width = width; buffer->height = height; buffer->format = format; buffer->stride = stride; buffer->offset = offset; buffer->pool = pool; - pool->internal_refcount++; + pool->refcount++; buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id); if (buffer->resource == NULL) { wl_client_post_no_memory(client); - shm_pool_unref(pool, false); + shm_pool_unref(pool); free(buffer); return; } @@ -312,8 +179,7 @@ destroy_pool(struct wl_resource *resource) { struct wl_shm_pool *pool = wl_resource_get_user_data(resource); - pool->resource = NULL; - shm_pool_unref(pool, false); + shm_pool_unref(pool); } static void @@ -327,6 +193,7 @@ shm_pool_resize(struct wl_client *client, struct wl_resource *resource, int32_t size) { struct wl_shm_pool *pool = wl_resource_get_user_data(resource); + void *data; if (size < pool->size) { wl_resource_post_error(resource, @@ -335,18 +202,19 @@ shm_pool_resize(struct wl_client *client, struct wl_resource *resource, return; } - pool->new_size = size; + data = mremap(pool->data, pool->size, size, MREMAP_MAYMOVE); + if (data == MAP_FAILED) { + wl_resource_post_error(resource, + WL_SHM_ERROR_INVALID_FD, + "failed mremap"); + return; + } - /* If the compositor has taken references on this pool it - * may be caching pointers into it. In that case we - * defer the resize (which may move the entire mapping) - * until the compositor finishes dereferencing the pool. - */ - if (pool->external_refcount == 0) - shm_pool_finish_resize(pool); + pool->data = data; + pool->size = size; } -static const struct wl_shm_pool_interface shm_pool_interface = { +struct wl_shm_pool_interface shm_pool_interface = { shm_pool_create_buffer, shm_pool_destroy, shm_pool_resize @@ -357,63 +225,34 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, uint32_t id, int fd, int32_t size) { struct wl_shm_pool *pool; - struct stat statbuf; - int seals; - int prot; - int flags; - uint32_t version; - if (size <= 0) { - wl_resource_post_error(resource, - WL_SHM_ERROR_INVALID_STRIDE, - "invalid size (%d)", size); - goto err_close; - } - - pool = zalloc(sizeof *pool); + pool = malloc(sizeof *pool); if (pool == NULL) { wl_client_post_no_memory(client); goto err_close; } -#ifdef HAVE_MEMFD_CREATE - seals = fcntl(fd, F_GET_SEALS); - if (seals == -1) - seals = 0; - - if ((seals & F_SEAL_SHRINK) && fstat(fd, &statbuf) >= 0) - pool->sigbus_is_impossible = statbuf.st_size >= size; - else - pool->sigbus_is_impossible = false; -#else - pool->sigbus_is_impossible = false; -#endif - - pool->internal_refcount = 1; - pool->external_refcount = 0; - pool->size = size; - pool->new_size = size; - prot = PROT_READ | PROT_WRITE; - flags = MAP_SHARED; - pool->data = mmap(NULL, size, prot, flags, fd, 0); - if (pool->data == MAP_FAILED) { - wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD, - "failed mmap fd %d: %s", fd, - strerror(errno)); + if (size <= 0) { + wl_resource_post_error(resource, + WL_SHM_ERROR_INVALID_STRIDE, + "invalid size (%d)", size); goto err_free; } -#ifndef MREMAP_MAYMOVE - /* We may need to keep the fd, prot and flags to emulate mremap(). */ - pool->mmap_fd = fd; - pool->mmap_prot = prot; - pool->mmap_flags = flags; -#else - close(fd); -#endif - version = wl_resource_get_version(resource); + pool->refcount = 1; + pool->size = size; + pool->data = mmap(NULL, size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (pool->data == MAP_FAILED) { + wl_resource_post_error(resource, + WL_SHM_ERROR_INVALID_FD, + "failed mmap fd %d", fd); + goto err_close; + } + close(fd); + pool->resource = - wl_resource_create(client, &wl_shm_pool_interface, version, id); + wl_resource_create(client, &wl_shm_pool_interface, 1, id); if (!pool->resource) { wl_client_post_no_memory(client); munmap(pool->data, pool->size); @@ -427,21 +266,14 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, return; -err_free: - free(pool); err_close: close(fd); -} - -static void -shm_release(struct wl_client *client, struct wl_resource *resource) -{ - wl_resource_destroy(resource); +err_free: + free(pool); } static const struct wl_shm_interface shm_interface = { - shm_create_pool, - shm_release, + shm_create_pool }; static void @@ -453,7 +285,7 @@ bind_shm(struct wl_client *client, struct wl_array *additional_formats; uint32_t *p; - resource = wl_resource_create(client, &wl_shm_interface, version, id); + resource = wl_resource_create(client, &wl_shm_interface, 1, id); if (!resource) { wl_client_post_no_memory(client); return; @@ -472,12 +304,47 @@ bind_shm(struct wl_client *client, WL_EXPORT int wl_display_init_shm(struct wl_display *display) { - if (!wl_global_create(display, &wl_shm_interface, 2, NULL, bind_shm)) + if (!wl_global_create(display, &wl_shm_interface, 1, NULL, bind_shm)) return -1; return 0; } +WL_EXPORT struct wl_shm_buffer * +wl_shm_buffer_create(struct wl_client *client, + uint32_t id, int32_t width, int32_t height, + int32_t stride, uint32_t format) +{ + struct wl_shm_buffer *buffer; + + if (!format_is_supported(client, format)) + return NULL; + + buffer = malloc(sizeof *buffer + stride * height); + if (buffer == NULL) + return NULL; + + buffer->width = width; + buffer->height = height; + buffer->format = format; + buffer->stride = stride; + buffer->offset = 0; + buffer->pool = NULL; + + buffer->resource = + wl_resource_create(client, &wl_buffer_interface, 1, id); + if (buffer->resource == NULL) { + free(buffer); + return NULL; + } + + wl_resource_set_implementation(buffer->resource, + &shm_buffer_interface, + buffer, destroy_buffer); + + return buffer; +} + WL_EXPORT struct wl_shm_buffer * wl_shm_buffer_get(struct wl_resource *resource) { @@ -492,7 +359,7 @@ wl_shm_buffer_get(struct wl_resource *resource) } WL_EXPORT int32_t -wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer) +wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer) { return buffer->stride; } @@ -505,123 +372,42 @@ wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer) * Returns a pointer which can be used to read the data contained in * the given SHM buffer. * - * As this buffer is memory-mapped, reading from it may generate + * As this buffer is memory-mapped, reading it from may generate * SIGBUS signals. This can happen if the client claims that the * buffer is larger than it is or if something truncates the * underlying file. To prevent this signal from causing the compositor - * to crash you should call wl_shm_buffer_begin_access() and - * wl_shm_buffer_end_access() around code that reads from the memory. + * to crash you should call wl_shm_buffer_begin_access and + * wl_shm_buffer_end_access around code that reads from the memory. * * \memberof wl_shm_buffer */ WL_EXPORT void * wl_shm_buffer_get_data(struct wl_shm_buffer *buffer) { - if (buffer->pool->external_refcount && - (buffer->pool->size != buffer->pool->new_size)) - wl_log("Buffer address requested when its parent pool " - "has an external reference and a deferred resize " - "pending.\n"); - return buffer->pool->data + buffer->offset; + if (buffer->pool) + return buffer->pool->data + buffer->offset; + else + return buffer + 1; } WL_EXPORT uint32_t -wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer) +wl_shm_buffer_get_format(struct wl_shm_buffer *buffer) { return buffer->format; } WL_EXPORT int32_t -wl_shm_buffer_get_width(const struct wl_shm_buffer *buffer) +wl_shm_buffer_get_width(struct wl_shm_buffer *buffer) { return buffer->width; } WL_EXPORT int32_t -wl_shm_buffer_get_height(const struct wl_shm_buffer *buffer) +wl_shm_buffer_get_height(struct wl_shm_buffer *buffer) { return buffer->height; } -/** Reference a shm_buffer - * - * \param buffer The buffer object - * - * Returns a pointer to the buffer and increases the refcount. - * - * The compositor must remember to call wl_shm_buffer_unref() when - * it no longer needs the reference to ensure proper destruction - * of the buffer. - * - * \memberof wl_shm_buffer - * \sa wl_shm_buffer_unref - */ -WL_EXPORT struct wl_shm_buffer * -wl_shm_buffer_ref(struct wl_shm_buffer *buffer) -{ - buffer->external_refcount++; - return buffer; -} - -/** Unreference a shm_buffer - * - * \param buffer The buffer object - * - * Drops a reference to a buffer object. - * - * This is only necessary if the compositor has explicitly - * taken a reference with wl_shm_buffer_ref(), otherwise - * the buffer will be automatically destroyed when appropriate. - * - * \memberof wl_shm_buffer - * \sa wl_shm_buffer_ref - */ -WL_EXPORT void -wl_shm_buffer_unref(struct wl_shm_buffer *buffer) -{ - shm_buffer_unref(buffer, true); -} - -/** Get a reference to a shm_buffer's shm_pool - * - * \param buffer The buffer object - * - * Returns a pointer to a buffer's shm_pool and increases the - * shm_pool refcount. - * - * The compositor must remember to call wl_shm_pool_unref() when - * it no longer needs the reference to ensure proper destruction - * of the pool. - * - * \memberof wl_shm_buffer - * \sa wl_shm_pool_unref - */ -WL_EXPORT struct wl_shm_pool * -wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer) -{ - buffer->pool->external_refcount++; - return buffer->pool; -} - -/** Unreference a shm_pool - * - * \param pool The pool object - * - * Drops a reference to a wl_shm_pool object. - * - * This is only necessary if the compositor has explicitly - * taken a reference with wl_shm_buffer_ref_pool(), otherwise - * the pool will be automatically destroyed when appropriate. - * - * \memberof wl_shm_pool - * \sa wl_shm_buffer_ref_pool - */ -WL_EXPORT void -wl_shm_pool_unref(struct wl_shm_pool *pool) -{ - shm_pool_unref(pool, true); -} - static void reraise_sigbus(void) { @@ -659,8 +445,10 @@ sigbus_handler(int signum, siginfo_t *info, void *context) sigbus_data->fallback_mapping_used = 1; /* This should replace the previous mapping */ - if (mmap(pool->data, pool->size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0, 0) == MAP_FAILED) { + if (mmap(pool->data, pool->size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, + 0, 0) == (void *) -1) { reraise_sigbus(); return; } @@ -700,7 +488,7 @@ init_sigbus_data_key(void) * In order to make the compositor robust against clients that change * the size of the underlying file or lie about its size, you should * protect access to the buffer by calling this function before - * reading from the memory and call wl_shm_buffer_end_access() + * reading from the memory and call wl_shm_buffer_end_access * afterwards. This will install a signal handler for SIGBUS which * will prevent the compositor from crashing. * @@ -711,15 +499,15 @@ init_sigbus_data_key(void) * * If a SIGBUS signal is received for an address within the range of * the SHM pool of the given buffer then the client will be sent an - * error event when wl_shm_buffer_end_access() is called. If the signal + * error event when wl_shm_buffer_end_access is called. If the signal * is for an address outside that range then the signal handler will * reraise the signal which would will likely cause the compositor to * terminate. * * It is safe to nest calls to these functions as long as the nested - * calls are all accessing the same pool. The number of calls to - * wl_shm_buffer_end_access() must match the number of calls to - * wl_shm_buffer_begin_access(). These functions are thread-safe and it + * calls are all accessing the same buffer. The number of calls to + * wl_shm_buffer_end_access must match the number of calls to + * wl_shm_buffer_begin_access. These functions are thread-safe and it * is allowed to simultaneously access different buffers or the same * buffer from multiple threads. * @@ -731,33 +519,31 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer) struct wl_shm_pool *pool = buffer->pool; struct wl_shm_sigbus_data *sigbus_data; - if (pool->sigbus_is_impossible) - return; - pthread_once(&wl_shm_sigbus_once, init_sigbus_data_key); sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key); if (sigbus_data == NULL) { - sigbus_data = zalloc(sizeof *sigbus_data); + sigbus_data = malloc(sizeof *sigbus_data); if (sigbus_data == NULL) return; + memset(sigbus_data, 0, sizeof *sigbus_data); + pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data); } - if (!(sigbus_data->current_pool == NULL || - sigbus_data->current_pool == pool)) - wl_abort("Incorrect pool passed for current thread\n"); + assert(sigbus_data->current_pool == NULL || + sigbus_data->current_pool == pool); sigbus_data->current_pool = pool; sigbus_data->access_count++; } -/** Ends the access to a buffer started by wl_shm_buffer_begin_access() +/** Ends the access to a buffer started by wl_shm_buffer_begin_access * * \param buffer The SHM buffer * - * This should be called after wl_shm_buffer_begin_access() once the + * This should be called after wl_shm_buffer_begin_access once the * buffer is no longer being accessed. If a SIGBUS signal was * generated in-between these two calls then the resource for the * given buffer will be sent an error. @@ -767,49 +553,19 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer) WL_EXPORT void wl_shm_buffer_end_access(struct wl_shm_buffer *buffer) { - struct wl_shm_pool *pool = buffer->pool; - struct wl_shm_sigbus_data *sigbus_data; + struct wl_shm_sigbus_data *sigbus_data = + pthread_getspecific(wl_shm_sigbus_data_key); - if (pool->sigbus_is_impossible) - return; - - sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key); - if (!(sigbus_data && sigbus_data->access_count >= 1)) - wl_abort("sigbus_data is NULL or wl_shm_buffer_begin_access " - "wasn't called before\n"); + assert(sigbus_data && sigbus_data->access_count >= 1); if (--sigbus_data->access_count == 0) { if (sigbus_data->fallback_mapping_used) { - if (buffer->resource) { - wl_resource_post_error(buffer->resource, - WL_SHM_ERROR_INVALID_FD, - "error accessing SHM buffer"); - } else if (buffer->client) { - wl_client_post_implementation_error(buffer->client, - "Error accessing SHM buffer of a " - "wl_buffer resource which has " - "already been destroyed"); - } + wl_resource_post_error(buffer->resource, + WL_SHM_ERROR_INVALID_FD, + "error accessing SHM buffer"); sigbus_data->fallback_mapping_used = 0; } sigbus_data->current_pool = NULL; } } - -/** \cond */ /* Deprecated functions below. */ - -WL_EXPORT struct wl_shm_buffer * -wl_shm_buffer_create(struct wl_client *client, - uint32_t id, int32_t width, int32_t height, - int32_t stride, uint32_t format) -{ - return NULL; -} - -/** \endcond */ - -/* Functions at the end of this file are deprecated. Instead of adding new - * code here, add it before the comment above that states: - * Deprecated functions below. - */ diff --git a/src/wayland-util.c b/src/wayland-util.c index 15e157d7..b099882b 100644 --- a/src/wayland-util.c +++ b/src/wayland-util.c @@ -2,29 +2,25 @@ * Copyright © 2008-2011 Kristian Høgsberg * Copyright © 2011 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: + * 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 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. + * 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 #include #include #include @@ -34,6 +30,8 @@ #include "wayland-util.h" #include "wayland-private.h" +struct wl_object global_zombie_object; + WL_EXPORT void wl_list_init(struct wl_list *list) { @@ -103,7 +101,6 @@ WL_EXPORT void wl_array_release(struct wl_array *array) { free(array->data); - array->data = WL_ARRAY_POISON_PTR; } WL_EXPORT void * @@ -121,21 +118,18 @@ wl_array_add(struct wl_array *array, size_t size) alloc *= 2; if (array->alloc < alloc) { - if (array->alloc == 0 && array->data != NULL) - wl_abort("data is non-NULL with zero alloc"); - if (array->alloc > 0) data = realloc(array->data, alloc); - else + else data = malloc(alloc); if (data == NULL) - return NULL; + return 0; array->data = data; array->alloc = alloc; } - p = (char *)array->data + array->size; + p = array->data + array->size; array->size += size; return p; @@ -151,71 +145,39 @@ wl_array_copy(struct wl_array *array, struct wl_array *source) array->size = source->size; } - if (source->size > 0) - memcpy(array->data, source->data, source->size); - + memcpy(array->data, source->data, source->size); return 0; } -/** \cond */ - -int -wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b) -{ - /* In most cases the pointer equality test is sufficient. - * However, in some cases, depending on how things are split - * across shared objects, we can end up with multiple - * instances of the interface metadata constants. So if the - * pointers match, the interfaces are equal, if they don't - * match we have to compare the interface names. - */ - return a == b || strcmp(a->name, b->name) == 0; -} - union map_entry { uintptr_t next; void *data; }; -static inline bool -map_entry_is_free(union map_entry entry) -{ - return entry.next & 0x1; -} +#define map_entry_is_free(entry) ((entry).next & 0x1) +#define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3)) +#define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1) -static inline void * -map_entry_get_data(union map_entry entry) -{ - return (void *)(entry.next & ~(uintptr_t)0x3); -} - -static inline uint32_t -map_entry_get_flags(union map_entry entry) -{ - return (entry.next >> 1) & 0x1; -} - -void +WL_EXPORT void wl_map_init(struct wl_map *map, uint32_t side) { memset(map, 0, sizeof *map); map->side = side; } -void +WL_EXPORT void wl_map_release(struct wl_map *map) { wl_array_release(&map->client_entries); wl_array_release(&map->server_entries); } -uint32_t +WL_EXPORT uint32_t wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data) { union map_entry *start, *entry; struct wl_array *entries; uint32_t base; - uint32_t count; if (map->side == WL_MAP_CLIENT_SIDE) { entries = &map->client_entries; @@ -236,29 +198,13 @@ wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data) start = entries->data; } - /* wl_array only grows, so if we have too many objects at - * this point there's no way to clean up. We could be more - * pro-active about trying to avoid this allocation, but - * it doesn't really matter because at this point there is - * nothing to be done but disconnect the client and delete - * the whole array either way. - */ - count = entry - start; - if (count > WL_MAP_MAX_OBJECTS) { - /* entry->data is freshly malloced garbage, so we'd - * better make it a NULL so wl_map_for_each doesn't - * dereference it later. */ - entry->data = NULL; - errno = ENOSPC; - return 0; - } entry->data = data; entry->next |= (flags & 0x1) << 1; - return count + base; + return (entry - start) + base; } -int +WL_EXPORT int wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data) { union map_entry *start; @@ -272,21 +218,12 @@ wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data) i -= WL_SERVER_ID_START; } - if (i > WL_MAP_MAX_OBJECTS) { - errno = ENOSPC; - return -1; - } - count = entries->size / sizeof *start; - if (count < i) { - errno = EINVAL; + if (count < i) return -1; - } - if (count == i) { - if (!wl_array_add(entries, sizeof *start)) - return -1; - } + if (count == i) + wl_array_add(entries, sizeof *start); start = entries->data; start[i].data = data; @@ -295,7 +232,7 @@ wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data) return 0; } -int +WL_EXPORT int wl_map_reserve_new(struct wl_map *map, uint32_t i) { union map_entry *start; @@ -303,43 +240,30 @@ wl_map_reserve_new(struct wl_map *map, uint32_t i) struct wl_array *entries; if (i < WL_SERVER_ID_START) { - if (map->side == WL_MAP_CLIENT_SIDE) { - errno = EINVAL; + if (map->side == WL_MAP_CLIENT_SIDE) return -1; - } entries = &map->client_entries; } else { - if (map->side == WL_MAP_SERVER_SIDE) { - errno = EINVAL; + if (map->side == WL_MAP_SERVER_SIDE) return -1; - } entries = &map->server_entries; i -= WL_SERVER_ID_START; } - if (i > WL_MAP_MAX_OBJECTS) { - errno = ENOSPC; - return -1; - } - count = entries->size / sizeof *start; - if (count < i) { - errno = EINVAL; + + if (count < i) return -1; - } if (count == i) { - if (!wl_array_add(entries, sizeof *start)) - return -1; - + wl_array_add(entries, sizeof *start); start = entries->data; start[i].data = NULL; } else { start = entries->data; if (start[i].data != NULL) { - errno = EINVAL; return -1; } } @@ -347,7 +271,7 @@ wl_map_reserve_new(struct wl_map *map, uint32_t i) return 0; } -void +WL_EXPORT void wl_map_remove(struct wl_map *map, uint32_t i) { union map_entry *start; @@ -371,7 +295,7 @@ wl_map_remove(struct wl_map *map, uint32_t i) map->free_list = (i << 1) | 1; } -void * +WL_EXPORT void * wl_map_lookup(struct wl_map *map, uint32_t i) { union map_entry *start; @@ -394,7 +318,7 @@ wl_map_lookup(struct wl_map *map, uint32_t i) return NULL; } -uint32_t +WL_EXPORT uint32_t wl_map_lookup_flags(struct wl_map *map, uint32_t i) { union map_entry *start; @@ -417,38 +341,24 @@ wl_map_lookup_flags(struct wl_map *map, uint32_t i) return 0; } -static enum wl_iterator_result +static void for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data) { - enum wl_iterator_result ret = WL_ITERATOR_CONTINUE; - union map_entry entry, *start; - size_t count; + union map_entry *start, *end, *p; - for (size_t idx = 0; ; idx++) { - count = entries->size / sizeof(union map_entry); - if (idx >= count) - break; + start = entries->data; + end = (union map_entry *) ((char *) entries->data + entries->size); - start = (union map_entry *) entries->data; - entry = start[idx]; - if (entry.data && !map_entry_is_free(entry)) { - ret = func(map_entry_get_data(entry), data, map_entry_get_flags(entry)); - if (ret != WL_ITERATOR_CONTINUE) - break; - } - } - - return ret; + for (p = start; p < end; p++) + if (p->data && !map_entry_is_free(*p)) + func(map_entry_get_data(*p), data); } -void +WL_EXPORT void wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data) { - enum wl_iterator_result ret; - - ret = for_each_helper(&map->client_entries, func, data); - if (ret == WL_ITERATOR_CONTINUE) - for_each_helper(&map->server_entries, func, data); + for_each_helper(&map->client_entries, func, data); + for_each_helper(&map->server_entries, func, data); } static void @@ -468,17 +378,3 @@ wl_log(const char *fmt, ...) wl_log_handler(fmt, argp); va_end(argp); } - -void -wl_abort(const char *fmt, ...) -{ - va_list argp; - - va_start(argp, fmt); - wl_log_handler(fmt, argp); - va_end(argp); - - abort(); -} - -/** \endcond */ diff --git a/src/wayland-util.h b/src/wayland-util.h index 98c72fde..fd32826d 100644 --- a/src/wayland-util.h +++ b/src/wayland-util.h @@ -1,26 +1,23 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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: + * 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 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. + * 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. */ /** \file wayland-util.h @@ -31,450 +28,149 @@ #ifndef WAYLAND_UTIL_H #define WAYLAND_UTIL_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include #include #include -#ifdef __cplusplus -extern "C" { -#endif - -/** Visibility attribute */ +/* GCC visibility */ #if defined(__GNUC__) && __GNUC__ >= 4 #define WL_EXPORT __attribute__ ((visibility("default"))) #else #define WL_EXPORT #endif -/** Deprecated attribute */ -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || (defined(__cplusplus) && __cplusplus >= 201402L) -#define WL_DEPRECATED [[deprecated]] -#elif defined(__GNUC__) && __GNUC__ >= 4 +/* Deprecated attribute */ +#if defined(__GNUC__) && __GNUC__ >= 4 #define WL_DEPRECATED __attribute__ ((deprecated)) #else #define WL_DEPRECATED #endif -/** - * Printf-style argument attribute - * - * \param x Ordinality of the format string argument - * \param y Ordinality of the argument to check against the format string - * - * \sa https://gcc.gnu.org/onlinedocs/gcc-3.2.1/gcc/Function-Attributes.html - */ +/* Printf annotation */ #if defined(__GNUC__) && __GNUC__ >= 4 #define WL_PRINTF(x, y) __attribute__((__format__(__printf__, x, y))) #else #define WL_PRINTF(x, y) #endif -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L -#define WL_TYPEOF(expr) typeof(expr) -#else -#define WL_TYPEOF(expr) __typeof__(expr) -#endif - -/** \class wl_object - * - * \brief A protocol object. - * - * A `wl_object` is an opaque struct identifying the protocol object - * underlying a `wl_proxy` or `wl_resource`. - * - * \note Functions accessing a `wl_object` are not normally used by client code. - * Clients should normally use the higher level interface generated by the - * scanner to interact with compositor objects. - * - */ -struct wl_object; - -/** - * The maximum size of a protocol message. - * - * If a message size exceeds this value, the connection will be dropped. - * Servers will send an invalid_method error before disconnecting. - */ -#define WL_MAX_MESSAGE_SIZE 4096 - -/** - * Protocol message signature - * - * A wl_message describes the signature of an actual protocol message, such as a - * request or event, that adheres to the Wayland protocol wire format. The - * protocol implementation uses a wl_message within its demarshal machinery for - * decoding messages between a compositor and its clients. In a sense, a - * wl_message is to a protocol message like a class is to an object. - * - * The `name` of a wl_message is the name of the corresponding protocol message. - * - * The `signature` is an ordered list of symbols representing the data types - * of message arguments and, optionally, a protocol version and indicators for - * nullability. A leading integer in the `signature` indicates the _since_ - * version of the protocol message. A `?` preceding a data type symbol indicates - * that the following argument type is nullable. While it is a protocol violation - * to send messages with non-nullable arguments set to `NULL`, event handlers in - * clients might still get called with non-nullable object arguments set to - * `NULL`. This can happen when the client destroyed the object being used as - * argument on its side and an event referencing that object was sent before the - * server knew about its destruction. As this race cannot be prevented, clients - * should - as a general rule - program their event handlers such that they can - * handle object arguments declared non-nullable being `NULL` gracefully. - * - * When no arguments accompany a message, `signature` is an empty string. - * - * Symbols: - * - * * `i`: int - * * `u`: uint - * * `f`: fixed - * * `s`: string - * * `o`: object - * * `n`: new_id - * * `a`: array - * * `h`: fd - * * `?`: following argument (`o` or `s`) is nullable - * - * While demarshaling primitive arguments is straightforward, when demarshaling - * messages containing `object` or `new_id` arguments, the protocol - * implementation often must determine the type of the object. The `types` of a - * wl_message is an array of wl_interface references that correspond to `o` and - * `n` arguments in `signature`, with `NULL` placeholders for arguments with - * non-object types. - * - * Consider the protocol event wl_display `delete_id` that has a single `uint` - * argument. The wl_message is: - * - * \code - * { "delete_id", "u", [NULL] } - * \endcode - * - * Here, the message `name` is `"delete_id"`, the `signature` is `"u"`, and the - * argument `types` is `[NULL]`, indicating that the `uint` argument has no - * corresponding wl_interface since it is a primitive argument. - * - * In contrast, consider a `wl_foo` interface supporting protocol request `bar` - * that has existed since version 2, and has two arguments: a `uint` and an - * object of type `wl_baz_interface` that may be `NULL`. Such a `wl_message` - * might be: - * - * \code - * { "bar", "2u?o", [NULL, &wl_baz_interface] } - * \endcode - * - * Here, the message `name` is `"bar"`, and the `signature` is `"2u?o"`. Notice - * how the `2` indicates the protocol version, the `u` indicates the first - * argument type is `uint`, and the `?o` indicates that the second argument - * is an object that may be `NULL`. Lastly, the argument `types` array indicates - * that no wl_interface corresponds to the first argument, while the type - * `wl_baz_interface` corresponds to the second argument. - * - * \sa wl_argument - * \sa wl_interface - * \sa Wire Format - */ struct wl_message { - /** Message name */ const char *name; - /** Message signature */ const char *signature; - /** Object argument interfaces */ const struct wl_interface **types; }; -/** - * Protocol object interface - * - * A wl_interface describes the API of a protocol object defined in the Wayland - * protocol specification. The protocol implementation uses a wl_interface - * within its marshalling machinery for encoding client requests. - * - * The `name` of a wl_interface is the name of the corresponding protocol - * interface, and `version` represents the version of the interface. The members - * `method_count` and `event_count` represent the number of `methods` (requests) - * and `events` in the respective wl_message members. - * - * For example, consider a protocol interface `foo`, marked as version `1`, with - * two requests and one event. - * - * \code{.xml} - * - * - * - * - * - * \endcode - * - * Given two wl_message arrays `foo_requests` and `foo_events`, a wl_interface - * for `foo` might be: - * - * \code - * struct wl_interface foo_interface = { - * "foo", 1, - * 2, foo_requests, - * 1, foo_events - * }; - * \endcode - * - * \note The server side of the protocol may define interface implementation - * types that incorporate the term `interface` in their name. Take - * care to not confuse these server-side `struct`s with a wl_interface - * variable whose name also ends in `interface`. For example, while the - * server may define a type `struct wl_foo_interface`, the client may - * define a `struct wl_interface wl_foo_interface`. - * - * \sa wl_message - * \sa wl_proxy - * \sa Interfaces - * \sa Versioning - */ struct wl_interface { - /** Interface name */ const char *name; - /** Interface version */ int version; - /** Number of methods (requests) */ int method_count; - /** Method (request) signatures */ const struct wl_message *methods; - /** Number of events */ int event_count; - /** Event signatures */ const struct wl_message *events; }; /** \class wl_list * - * \brief Doubly-linked list + * \brief doubly-linked list * - * On its own, an instance of `struct wl_list` represents the sentinel head of - * a doubly-linked list, and must be initialized using wl_list_init(). - * When empty, the list head's `next` and `prev` members point to the list head - * itself, otherwise `next` references the first element in the list, and `prev` - * refers to the last element in the list. + * The list head is of "struct wl_list" type, and must be initialized + * using wl_list_init(). All entries in the list must be of the same + * type. The item type must have a "struct wl_list" member. This + * member will be initialized by wl_list_insert(). There is no need to + * call wl_list_init() on the individual item. To query if the list is + * empty in O(1), use wl_list_empty(). * - * Use the `struct wl_list` type to represent both the list head and the links - * between elements within the list. Use wl_list_empty() to determine if the - * list is empty in O(1). + * Let's call the list reference "struct wl_list foo_list", the item type as + * "item_t", and the item member as "struct wl_list link". * - * All elements in the list must be of the same type. The element type must have - * a `struct wl_list` member, often named `link` by convention. Prior to - * insertion, there is no need to initialize an element's `link` - invoking - * wl_list_init() on an individual list element's `struct wl_list` member is - * unnecessary if the very next operation is wl_list_insert(). However, a - * common idiom is to initialize an element's `link` prior to removal - ensure - * safety by invoking wl_list_init() before wl_list_remove(). + * The following code will initialize a list: * - * Consider a list reference `struct wl_list foo_list`, an element type as - * `struct element`, and an element's link member as `struct wl_list link`. + * struct wl_list foo_list; * - * The following code initializes a list and adds three elements to it. + * struct item_t { + * int foo; + * struct wl_list link; + * }; + * struct item_t item1, item2, item3; * - * \code - * struct wl_list foo_list; + * wl_list_init(&foo_list); + * wl_list_insert(&foo_list, &item1.link); Pushes item1 at the head + * wl_list_insert(&foo_list, &item2.link); Pushes item2 at the head + * wl_list_insert(&item2.link, &item3.link); Pushes item3 after item2 * - * struct element { - * int foo; - * struct wl_list link; - * }; - * struct element e1, e2, e3; + * The list now looks like [item2, item3, item1] * - * wl_list_init(&foo_list); - * wl_list_insert(&foo_list, &e1.link); // e1 is the first element - * wl_list_insert(&foo_list, &e2.link); // e2 is now the first element - * wl_list_insert(&e2.link, &e3.link); // insert e3 after e2 - * \endcode + * Will iterate the list in ascending order: * - * The list now looks like [e2, e3, e1]. - * - * The `wl_list` API provides some iterator macros. For example, to iterate - * a list in ascending order: - * - * \code - * struct element *e; - * wl_list_for_each(e, foo_list, link) { - * do_something_with_element(e); - * } - * \endcode - * - * See the documentation of each iterator for details. - * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h + * item_t *item; + * wl_list_for_each(item, foo_list, link) { + * Do_something_with_item(item); + * } */ struct wl_list { - /** Previous list element */ struct wl_list *prev; - /** Next list element */ struct wl_list *next; }; -/** - * Initializes the list. - * - * \param list List to initialize - * - * \memberof wl_list - */ -void -wl_list_init(struct wl_list *list); +void wl_list_init(struct wl_list *list); +void wl_list_insert(struct wl_list *list, struct wl_list *elm); +void wl_list_remove(struct wl_list *elm); +int wl_list_length(const struct wl_list *list); +int wl_list_empty(const struct wl_list *list); +void wl_list_insert_list(struct wl_list *list, struct wl_list *other); /** - * Inserts an element into the list, after the element represented by \p list. - * When \p list is a reference to the list itself (the head), set the containing - * struct of \p elm as the first element in the list. + * Retrieves a pointer to the containing struct of a given member item. * - * \note If \p elm is already part of a list, inserting it again will lead to - * list corruption. - * - * \param list List element after which the new element is inserted - * \param elm Link of the containing struct to insert into the list - * - * \memberof wl_list - */ -void -wl_list_insert(struct wl_list *list, struct wl_list *elm); - -/** - * Removes an element from the list. - * - * \note This operation leaves \p elm in an invalid state. - * - * \param elm Link of the containing struct to remove from the list - * - * \memberof wl_list - */ -void -wl_list_remove(struct wl_list *elm); - -/** - * Determines the length of the list. - * - * \note This is an O(n) operation. - * - * \param list List whose length is to be determined - * - * \return Number of elements in the list - * - * \memberof wl_list - */ -int -wl_list_length(const struct wl_list *list); - -/** - * Determines if the list is empty. - * - * \param list List whose emptiness is to be determined - * - * \return 1 if empty, or 0 if not empty - * - * \memberof wl_list - */ -int -wl_list_empty(const struct wl_list *list); - -/** - * Inserts all of the elements of one list into another, after the element - * represented by \p list. - * - * \note This leaves \p other in an invalid state. - * - * \param list List element after which the other list elements will be inserted - * \param other List of elements to insert - * - * \memberof wl_list - */ -void -wl_list_insert_list(struct wl_list *list, struct wl_list *other); - -/** - * Retrieves a pointer to a containing struct, given a member name. - * - * This macro allows "conversion" from a pointer to a member to its containing + * This macro allows conversion from a pointer to a item to its containing * struct. This is useful if you have a contained item like a wl_list, - * wl_listener, or wl_signal, provided via a callback or other means, and would + * wl_listener, or wl_signal, provided via a callback or other means and would * like to retrieve the struct that contains it. * * To demonstrate, the following example retrieves a pointer to * `example_container` given only its `destroy_listener` member: * - * \code + * ~~~ * struct example_container { - * struct wl_listener destroy_listener; - * // other members... + * struct wl_listener destroy_listener; + * \comment{other members...} * }; * * void example_container_destroy(struct wl_listener *listener, void *data) * { - * struct example_container *ctr; + * struct example_container *ctr; * - * ctr = wl_container_of(listener, ctr, destroy_listener); - * // destroy ctr... + * ctr = wl_container_of(listener, ctr, destroy_listener); + * \comment{destroy ctr...} * } - * \endcode + * ~~~ * - * \note `sample` need not be a valid pointer. A null or uninitialised pointer - * is sufficient. + * \param ptr A valid pointer to the contained item. * - * \param ptr Valid pointer to the contained member - * \param sample Pointer to a struct whose type contains \p ptr - * \param member Named location of \p ptr within the \p sample type + * \param sample A pointer to the type of content that the list item + * stores. Sample does not need be a valid pointer; a null or + * an uninitialised pointer will suffice. * - * \return The container for the specified pointer + * \param member The named location of ptr within the sample type. + * + * \return The container for the specified pointer. */ #define wl_container_of(ptr, sample, member) \ - (WL_TYPEOF(sample))((char *)(ptr) - \ - offsetof(WL_TYPEOF(*sample), member)) + (__typeof__(sample))((char *)(ptr) - \ + offsetof(__typeof__(*sample), member)) +/* If the above macro causes problems on your compiler you might be + * able to find an alternative name for the non-standard __typeof__ + * operator and add a special case here */ -/** - * Iterates over a list. - * - * This macro expresses a for-each iterator for wl_list. Given a list and - * wl_list link member name (often named `link` by convention), this macro - * assigns each element in the list to \p pos, which can then be referenced in - * a trailing code block. For example, given a wl_list of `struct message` - * elements: - * - * \code - * struct message { - * char *contents; - * wl_list link; - * }; - * - * struct wl_list *message_list; - * // Assume message_list now "contains" many messages - * - * struct message *m; - * wl_list_for_each(m, message_list, link) { - * do_something_with_message(m); - * } - * \endcode - * - * \param pos Cursor that each list element will be assigned to - * \param head Head of the list to iterate over - * \param member Name of the link member within the element struct - * - * \relates wl_list - */ #define wl_list_for_each(pos, head, member) \ for (pos = wl_container_of((head)->next, pos, member); \ &pos->member != (head); \ pos = wl_container_of(pos->member.next, pos, member)) -/** - * Iterates over a list, safe against removal of the list element. - * - * \note Only removal of the current element, \p pos, is safe. Removing - * any other element during traversal may lead to a loop malfunction. - * - * \sa wl_list_for_each() - * - * \param pos Cursor that each list element will be assigned to - * \param tmp Temporary pointer of the same type as \p pos - * \param head Head of the list to iterate over - * \param member Name of the link member within the element struct - * - * \relates wl_list - */ #define wl_list_for_each_safe(pos, tmp, head, member) \ for (pos = wl_container_of((head)->next, pos, member), \ tmp = wl_container_of((pos)->member.next, tmp, member); \ @@ -482,37 +178,11 @@ wl_list_insert_list(struct wl_list *list, struct wl_list *other); pos = tmp, \ tmp = wl_container_of(pos->member.next, tmp, member)) -/** - * Iterates backwards over a list. - * - * \sa wl_list_for_each() - * - * \param pos Cursor that each list element will be assigned to - * \param head Head of the list to iterate over - * \param member Name of the link member within the element struct - * - * \relates wl_list - */ #define wl_list_for_each_reverse(pos, head, member) \ for (pos = wl_container_of((head)->prev, pos, member); \ &pos->member != (head); \ pos = wl_container_of(pos->member.prev, pos, member)) -/** - * Iterates backwards over a list, safe against removal of the list element. - * - * \note Only removal of the current element, \p pos, is safe. Removing - * any other element during traversal may lead to a loop malfunction. - * - * \sa wl_list_for_each() - * - * \param pos Cursor that each list element will be assigned to - * \param tmp Temporary pointer of the same type as \p pos - * \param head Head of the list to iterate over - * \param member Name of the link member within the element struct - * - * \relates wl_list - */ #define wl_list_for_each_reverse_safe(pos, tmp, head, member) \ for (pos = wl_container_of((head)->prev, pos, member), \ tmp = wl_container_of((pos)->member.prev, tmp, member); \ @@ -520,246 +190,100 @@ wl_list_insert_list(struct wl_list *list, struct wl_list *other); pos = tmp, \ tmp = wl_container_of(pos->member.prev, tmp, member)) -/** - * \class wl_array - * - * Dynamic array - * - * A wl_array is a dynamic array that can only grow until released. It is - * intended for relatively small allocations whose size is variable or not known - * in advance. While construction of a wl_array does not require all elements to - * be of the same size, wl_array_for_each() does require all elements to have - * the same type and size. - * - */ struct wl_array { - /** Array size */ size_t size; - /** Allocated space */ size_t alloc; - /** Array data */ void *data; }; -/** - * Initializes the array. - * - * \param array Array to initialize - * - * \memberof wl_array - */ -void -wl_array_init(struct wl_array *array); - -/** - * Releases the array data. - * - * \note Leaves the array in an invalid state. - * - * \param array Array whose data is to be released - * - * \memberof wl_array - */ -void -wl_array_release(struct wl_array *array); - -/** - * Increases the size of the array by \p size bytes. - * - * \param array Array whose size is to be increased - * \param size Number of bytes to increase the size of the array by - * - * \return A pointer to the beginning of the newly appended space, or NULL when - * resizing fails. - * - * \memberof wl_array - */ -void * -wl_array_add(struct wl_array *array, size_t size); - -/** - * Copies the contents of \p source to \p array. - * - * \param array Destination array to copy to - * \param source Source array to copy from - * - * \return 0 on success, or -1 on failure - * - * \memberof wl_array - */ -int -wl_array_copy(struct wl_array *array, struct wl_array *source); - -/** - * Iterates over an array. - * - * This macro expresses a for-each iterator for wl_array. It assigns each - * element in the array to \p pos, which can then be referenced in a trailing - * code block. \p pos must be a pointer to the array element type, and all - * array elements must be of the same type and size. - * - * \param pos Cursor that each array element will be assigned to - * \param array Array to iterate over - * - * \relates wl_array - * \sa wl_list_for_each() - */ #define wl_array_for_each(pos, array) \ for (pos = (array)->data; \ - (array)->size != 0 && \ (const char *) pos < ((const char *) (array)->data + (array)->size); \ (pos)++) -/** - * Fixed-point number - * - * A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits - * of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t` - * as an opaque struct with methods that facilitate conversion to and from - * `double` and `int` types. - */ +void wl_array_init(struct wl_array *array); +void wl_array_release(struct wl_array *array); +void *wl_array_add(struct wl_array *array, size_t size); +int wl_array_copy(struct wl_array *array, struct wl_array *source); + typedef int32_t wl_fixed_t; -/** - * Converts a fixed-point number to a floating-point number. - * - * \param f Fixed-point number to convert - * - * \return Floating-point representation of the fixed-point argument - */ static inline double -wl_fixed_to_double(wl_fixed_t f) +wl_fixed_to_double (wl_fixed_t f) { - return f / 256.0; + union { + double d; + int64_t i; + } u; + + u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f; + + return u.d - (3LL << 43); } -/** - * Converts a floating-point number to a fixed-point number. - * - * \param d Floating-point number to convert - * - * \return Fixed-point representation of the floating-point argument - */ static inline wl_fixed_t wl_fixed_from_double(double d) { - return (wl_fixed_t) (round(d * 256.0)); + union { + double d; + int64_t i; + } u; + + u.d = d + (3LL << (51 - 8)); + + return u.i; } -/** - * Converts a fixed-point number to an integer. - * - * \param f Fixed-point number to convert - * - * \return Integer component of the fixed-point argument - */ -static inline int -wl_fixed_to_int(wl_fixed_t f) +static inline int wl_fixed_to_int(wl_fixed_t f) { return f / 256; } - -/** - * Converts an integer to a fixed-point number. - * - * \param i Integer to convert - * - * \return Fixed-point representation of the integer argument - */ -static inline wl_fixed_t -wl_fixed_from_int(int i) +static inline wl_fixed_t wl_fixed_from_int(int i) { return i * 256; } /** - * Protocol message argument data types + * \brief A union representing all of the basic data types that can be passed + * along the wayland wire format. * - * This union represents all of the argument types in the Wayland protocol wire - * format. The protocol implementation uses wl_argument within its marshalling - * machinery for dispatching messages between a client and a compositor. - * - * \sa wl_message - * \sa wl_interface - * \sa Wire Format + * This union represents all of the basic data types that can be passed in the + * wayland wire format. It is used by dispatchers and runtime-friendly + * versions of the event and request marshaling functions. */ union wl_argument { - int32_t i; /**< `int` */ - uint32_t u; /**< `uint` */ - wl_fixed_t f; /**< `fixed` */ - const char *s; /**< `string` */ - struct wl_object *o; /**< `object` */ - uint32_t n; /**< `new_id` */ - struct wl_array *a; /**< `array` */ - int32_t h; /**< `fd` */ + int32_t i; /**< signed integer */ + uint32_t u; /**< unsigned integer */ + wl_fixed_t f; /**< fixed point */ + const char *s; /**< string */ + struct wl_object *o; /**< object */ + uint32_t n; /**< new_id */ + struct wl_array *a; /**< array */ + int32_t h; /**< file descriptor */ }; /** - * Dispatcher function type alias + * \brief A function pointer type for a dispatcher. * * A dispatcher is a function that handles the emitting of callbacks in client - * code. For programs directly using the C library, this is done by using - * libffi to call function pointers. When binding to languages other than C, + * code. For programs directly using the C library, this is done by using + * libffi to call function pointers. When binding to languages other than C, * dispatchers provide a way to abstract the function calling process to be * friendlier to other function calling systems. * - * A dispatcher takes five arguments: The first is the dispatcher-specific - * implementation associated with the target object. The second is the object - * upon which the callback is being invoked (either wl_proxy or wl_resource). - * The third and fourth arguments are the opcode and the wl_message - * corresponding to the callback. The final argument is an array of arguments - * received from the other process via the wire protocol. - * - * \param user_data Dispatcher-specific implementation data - * \param target Callback invocation target (wl_proxy or `wl_resource`) - * \param opcode Callback opcode - * \param msg Callback message signature - * \param args Array of received arguments - * - * \return 0 on success, or -1 on failure + * A dispatcher takes five arguments: The first is the dispatcher-specific + * implementation data associated with the target object. The second is the + * object on which the callback is being invoked (either wl_proxy or + * wl_resource). The third and fourth arguments are the opcode the wl_messsage + * structure corresponding to the callback being emitted. The final argument + * is an array of arguments recieved from the other process via the wire + * protocol. */ -typedef int (*wl_dispatcher_func_t)(const void *user_data, void *target, - uint32_t opcode, const struct wl_message *msg, - union wl_argument *args); +typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t, + const struct wl_message *, + union wl_argument *); -/** - * Log function type alias - * - * The C implementation of the Wayland protocol abstracts the details of - * logging. Users may customize the logging behavior, with a function conforming - * to the `wl_log_func_t` type, via `wl_log_set_handler_client` and - * `wl_log_set_handler_server`. - * - * A `wl_log_func_t` must conform to the expectations of `vprintf`, and - * expects two arguments: a string to write and a corresponding variable - * argument list. While the string to write may contain format specifiers and - * use values in the variable argument list, the behavior of any `wl_log_func_t` - * depends on the implementation. - * - * \note Take care to not confuse this with `wl_protocol_logger_func_t`, which - * is a specific server-side logger for requests and events. - * - * \param fmt String to write to the log, containing optional format - * specifiers - * \param args Variable argument list - * - * \sa wl_log_set_handler_client - * \sa wl_log_set_handler_server - */ -typedef void (*wl_log_func_t)(const char *fmt, va_list args) WL_PRINTF(1, 0); - -/** - * Return value of an iterator function - * - * \sa wl_client_for_each_resource_iterator_func_t - * \sa wl_client_for_each_resource - */ -enum wl_iterator_result { - /** Stop the iteration */ - WL_ITERATOR_STOP, - /** Continue the iteration */ - WL_ITERATOR_CONTINUE -}; +typedef void (*wl_log_func_t)(const char *, va_list) WL_PRINTF(1, 0); #ifdef __cplusplus } diff --git a/src/wayland-version.h.in b/src/wayland-version.h.in index c5d786e2..9a746caf 100644 --- a/src/wayland-version.h.in +++ b/src/wayland-version.h.in @@ -1,26 +1,23 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 WAYLAND_VERSION_H diff --git a/tests/array-test.c b/tests/array-test.c index 78dfbb0a..c457e422 100644 --- a/tests/array-test.c +++ b/tests/array-test.c @@ -1,60 +1,45 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 #include -#include -#include "wayland-util.h" #include "wayland-private.h" #include "test-runner.h" TEST(array_init) { - struct wl_array array; + const int iterations = 4122; /* this is arbitrary */ + int i; - /* fill with garbage to emulate uninitialized memory */ - memset(&array, 0x57, sizeof array); + /* Init array an arbitray amount of times and verify the + * defaults are sensible. */ - wl_array_init(&array); - assert(array.size == 0); - assert(array.alloc == 0); - assert(array.data == 0); -} - -TEST(array_release) -{ - struct wl_array array; - void *ptr; - - wl_array_init(&array); - ptr = wl_array_add(&array, 1); - assert(ptr != NULL); - assert(array.data != NULL); - - wl_array_release(&array); - assert(array.data == WL_ARRAY_POISON_PTR); + for (i = 0; i < iterations; i++) { + struct wl_array array; + wl_array_init(&array); + assert(array.size == 0); + assert(array.alloc == 0); + assert(array.data == 0); + } } TEST(array_add) @@ -87,7 +72,8 @@ TEST(array_add) /* verify the data */ for (i = 0; i < iterations; ++i) { - struct mydata* check = (struct mydata*)array.data + i; + const int index = datasize * i; + struct mydata* check = (struct mydata*)(array.data + index); assert(check->a == i * 3); assert(check->b == 20000 - i); @@ -120,8 +106,9 @@ TEST(array_copy) /* check the copy */ for (i = 0; i < iterations; i++) { - int *s = (int *)source.data + i; - int *c = (int *)copy.data + i; + const int index = sizeof(int) * i; + int *s = (int *)(source.data + index); + int *c = (int *)(copy.data + index); assert(*s == *c); /* verify the values are the same */ assert(s != c); /* ensure the addresses aren't the same */ @@ -136,8 +123,7 @@ TEST(array_for_each) { static const int elements[] = { 77, 12, 45192, 53280, 334455 }; struct wl_array array; - int *p; - int i; + int *p, i; wl_array_init(&array); for (i = 0; i < 5; i++) { @@ -147,10 +133,8 @@ TEST(array_for_each) } i = 0; - wl_array_for_each(p, &array) { - assert(*p == elements[i]); - i++; - } + wl_array_for_each(p, &array) + assert(*p == elements[i++]); assert(i == 5); wl_array_release(&array); diff --git a/tests/client-test.c b/tests/client-test.c index 5585c0cd..fde38778 100644 --- a/tests/client-test.c +++ b/tests/client-test.c @@ -1,26 +1,23 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 @@ -40,61 +37,23 @@ struct client_destroy_listener { struct wl_listener listener; - bool done; - struct wl_listener late_listener; - bool late_done; - struct wl_listener resource_listener; - bool resource_done; + int done; }; static void client_destroy_notify(struct wl_listener *l, void *data) { struct client_destroy_listener *listener = - wl_container_of(l, listener, listener); + container_of(l, struct client_destroy_listener, listener); - listener->done = true; - assert(!listener->resource_done); - assert(!listener->late_done); -} - -static void -client_resource_destroy_notify(struct wl_listener *l, void *data) -{ - struct client_destroy_listener *listener = - wl_container_of(l, listener, resource_listener); - - assert(listener->done); - listener->resource_done = true; - assert(!listener->late_done); -} - -static void -client_late_destroy_notify(struct wl_listener *l, void *data) -{ - struct client_destroy_listener *listener = - wl_container_of(l, listener, late_listener); - - assert(listener->done); - assert(listener->resource_done); - listener->late_done = true; -} - -static void -client_user_data_destroy(void *data) -{ - bool *user_data_destroyed = data; - - *user_data_destroyed = true; + listener->done = 1; } TEST(client_destroy_listener) { struct wl_display *display; struct wl_client *client; - struct wl_resource *resource; struct client_destroy_listener a, b; - bool user_data_destroyed = false; int s[2]; assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); @@ -103,54 +62,23 @@ TEST(client_destroy_listener) client = wl_client_create(display, s[0]); assert(client); - wl_client_set_user_data(client, &user_data_destroyed, client_user_data_destroy); - assert(wl_client_get_user_data(client) == &user_data_destroyed); - - resource = wl_resource_create(client, &wl_callback_interface, 1, 0); - assert(resource); - a.listener.notify = client_destroy_notify; - a.done = false; - a.resource_listener.notify = client_resource_destroy_notify; - a.resource_done = false; - a.late_listener.notify = client_late_destroy_notify; - a.late_done = false; + a.done = 0; wl_client_add_destroy_listener(client, &a.listener); - wl_resource_add_destroy_listener(resource, &a.resource_listener); - wl_client_add_destroy_late_listener(client, &a.late_listener); assert(wl_client_get_destroy_listener(client, client_destroy_notify) == &a.listener); - assert(wl_resource_get_destroy_listener(resource, client_resource_destroy_notify) == - &a.resource_listener); - assert(wl_client_get_destroy_late_listener(client, client_late_destroy_notify) == - &a.late_listener); b.listener.notify = client_destroy_notify; - b.done = false; - b.resource_listener.notify = client_resource_destroy_notify; - b.resource_done = false; - b.late_listener.notify = client_late_destroy_notify; - b.late_done = false; + b.done = 0; wl_client_add_destroy_listener(client, &b.listener); - wl_resource_add_destroy_listener(resource, &b.resource_listener); - wl_client_add_destroy_late_listener(client, &b.late_listener); wl_list_remove(&a.listener.link); - wl_list_remove(&a.resource_listener.link); - wl_list_remove(&a.late_listener.link); - - assert(!user_data_destroyed); wl_client_destroy(client); assert(!a.done); - assert(!a.resource_done); - assert(!a.late_done); assert(b.done); - assert(b.resource_done); - assert(b.late_done); - assert(user_data_destroyed); close(s[0]); close(s[1]); @@ -158,50 +86,3 @@ TEST(client_destroy_listener) wl_display_destroy(display); } -static void -client_destroy_remove_link_notify(struct wl_listener *l, void *data) -{ - struct wl_client *client = data; - struct client_destroy_listener *listener = - wl_container_of(l, listener, listener); - - /* The client destruction signal should not be emitted more than once. */ - assert(!listener->done); - listener->done = true; - - /* The client should have been removed from the display's list. */ - assert(wl_list_empty(wl_client_get_link(client))); -} - -/* - * Tests that wl_client_destroy() will remove the client from the display's - * client list to prevent client access during destruction. - */ -TEST(client_destroy_removes_link) -{ - struct wl_display *display; - struct wl_client *client; - struct client_destroy_listener destroy_listener; - int s[2]; - - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); - display = wl_display_create(); - assert(display); - client = wl_client_create(display, s[0]); - assert(client); - - destroy_listener.listener.notify = client_destroy_remove_link_notify; - destroy_listener.done = false; - wl_client_add_destroy_listener(client, &destroy_listener.listener); - - assert(wl_client_get_destroy_listener(client, - client_destroy_remove_link_notify) == &destroy_listener.listener); - - wl_client_destroy(client); - assert(destroy_listener.done); - - close(s[0]); - close(s[1]); - - wl_display_destroy(display); -} diff --git a/tests/compositor-introspection-test.c b/tests/compositor-introspection-test.c deleted file mode 100644 index 064d2530..00000000 --- a/tests/compositor-introspection-test.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com - * - * 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 -#include -#include -#include -#include -#include -#include - -#include "wayland-client.h" -#include "wayland-server.h" -#include "test-runner.h" - -/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */ -static const char * -require_xdg_runtime_dir(void) -{ - char *val = getenv("XDG_RUNTIME_DIR"); - assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test"); - - return val; -} - -struct compositor { - struct wl_display *display; - struct wl_listener listener; - struct wl_client *client; -}; - -static void -client_created(struct wl_listener *listener, void *data) -{ - struct compositor *c = wl_container_of(listener, c, listener); - c->client = data; -} - -static void -check_client_list(struct compositor *compositor) -{ - struct wl_list *client_list; - struct wl_client *client, *client_it; - int num_clients = 0; - - client_list = wl_display_get_client_list(compositor->display); - wl_client_for_each(client_it, client_list) { - num_clients++; - client = client_it; - } - assert(num_clients == 1); - /* 'client_it' is not valid here, so we took a copy of the client in the loop. - * We could also do this assert in the loop directly, but in case it fails it is - * easier to understand the problem when we know that the previous assert passed, - * so that there is only one client but the wrong one. */ - assert(compositor->client == client); -} - -static const char * -setup_compositor(struct compositor *compositor) -{ - const char *socket; - - require_xdg_runtime_dir(); - - compositor->display = wl_display_create(); - socket = wl_display_add_socket_auto(compositor->display); - - compositor->listener.notify = client_created; - wl_display_add_client_created_listener(compositor->display, &compositor->listener); - - return socket; -} - -static void -cleanup_compositor(struct compositor *compositor) -{ - wl_client_destroy(compositor->client); - wl_display_destroy(compositor->display); -} - -TEST(new_client_connect) -{ - const char *socket; - struct compositor compositor = { 0 }; - struct { - struct wl_display *display; - } client; - - socket = setup_compositor(&compositor); - - client.display = wl_display_connect(socket); - - wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100); - - assert(compositor.client != NULL); - - check_client_list(&compositor); - - - - wl_display_disconnect(client.display); - cleanup_compositor(&compositor); -} - -struct resource_listener { - struct wl_listener listener; - int count; -}; - -static void -resource_created(struct wl_listener *listener, void *data) -{ - struct resource_listener *l; - l = wl_container_of(listener, l, listener); - l->count++; -} - -TEST(new_resource) -{ - const char *socket; - struct compositor compositor = { 0 }; - struct { - struct wl_display *display; - struct wl_callback *cb; - } client; - struct resource_listener resource_listener; - - socket = setup_compositor(&compositor); - client.display = wl_display_connect(socket); - wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100); - - resource_listener.count = 0; - resource_listener.listener.notify = resource_created; - wl_client_add_resource_created_listener(compositor.client, - &resource_listener.listener); - - client.cb = wl_display_sync(client.display); - wl_display_flush(client.display); - wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100); - - assert(resource_listener.count == 1); - - wl_callback_destroy(client.cb); - wl_display_disconnect(client.display); - cleanup_compositor(&compositor); - - /* This is defined to be safe also after client destruction */ - wl_list_remove(&resource_listener.listener.link); -} diff --git a/tests/connection-test.c b/tests/connection-test.c index aed97a0a..659bf68b 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -1,33 +1,29 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 #include #include #include -#include #include #include #include @@ -35,11 +31,9 @@ #include #include #include -#include #include "wayland-private.h" #include "test-runner.h" -#include "test-compositor.h" static const char message[] = "Hello, world"; @@ -50,7 +44,7 @@ setup(int *s) assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); - connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE); + connection = wl_connection_create(s[0]); assert(connection); return connection; @@ -63,7 +57,6 @@ TEST(connection_create) connection = setup(s); wl_connection_destroy(connection); - close(s[0]); close(s[1]); } @@ -81,7 +74,6 @@ TEST(connection_write) assert(memcmp(message, buffer, sizeof message) == 0); wl_connection_destroy(connection); - close(s[0]); close(s[1]); } @@ -100,7 +92,6 @@ TEST(connection_data) wl_connection_consume(connection, sizeof message); wl_connection_destroy(connection); - close(s[0]); close(s[1]); } @@ -126,45 +117,9 @@ TEST(connection_queue) assert(memcmp(message, buffer + sizeof message, sizeof message) == 0); wl_connection_destroy(connection); - close(s[0]); close(s[1]); } -static void -va_list_wrapper(const char *signature, union wl_argument *args, int count, ...) -{ - va_list ap; - va_start(ap, count); - wl_argument_from_va_list(signature, args, count, ap); - va_end(ap); -} - -TEST(argument_from_va_list) -{ - union wl_argument args[WL_CLOSURE_MAX_ARGS]; - struct wl_object fake_object, fake_new_object; - struct wl_array fake_array; - - va_list_wrapper("i", args, 1, 100); - assert(args[0].i == 100); - - va_list_wrapper("is", args, 2, 101, "value"); - assert(args[0].i == 101); - assert(strcmp(args[1].s, "value") == 0); - - va_list_wrapper("?iuf?sonah", args, 8, - 102, 103, wl_fixed_from_int(104), "value", - &fake_object, &fake_new_object, &fake_array, 106); - assert(args[0].i == 102); - assert(args[1].u == 103); - assert(args[2].f == wl_fixed_from_int(104)); - assert(strcmp(args[3].s, "value") == 0); - assert(args[4].o == &fake_object); - assert(args[5].o == &fake_new_object); - assert(args[6].a == &fake_array); - assert(args[7].h == 106); -} - struct marshal_data { struct wl_connection *read_connection; struct wl_connection *write_connection; @@ -183,19 +138,17 @@ setup_marshal_data(struct marshal_data *data) { assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); - data->read_connection = wl_connection_create(data->s[0], - WL_BUFFER_DEFAULT_MAX_SIZE); + data->read_connection = wl_connection_create(data->s[0]); assert(data->read_connection); - data->write_connection = wl_connection_create(data->s[1], - WL_BUFFER_DEFAULT_MAX_SIZE); + data->write_connection = wl_connection_create(data->s[1]); assert(data->write_connection); } static void release_marshal_data(struct marshal_data *data) { - close(wl_connection_destroy(data->read_connection)); - close(wl_connection_destroy(data->write_connection)); + wl_connection_destroy(data->read_connection); + wl_connection_destroy(data->write_connection); } static void @@ -247,6 +200,9 @@ TEST(connection_marshal) marshal(&data, "n", 12, &object); assert(data.buffer[2] == object.id); + marshal(&data, "?n", 12, NULL); + assert(data.buffer[2] == 0); + array.data = (void *) text; array.size = sizeof text; marshal(&data, "a", 20, &array); @@ -261,7 +217,7 @@ expected_fail_marshal(int expected_error, const char *format, ...) { struct wl_closure *closure; static const uint32_t opcode = 4444; - static const struct wl_interface test_interface = { + static const struct wl_interface test_interface = { .name = "test_object" }; static struct wl_object sender = { 0 }; @@ -279,25 +235,6 @@ expected_fail_marshal(int expected_error, const char *format, ...) assert(errno == expected_error); } -static void -marshal_send(struct marshal_data *data, const char *format, ...) -{ - struct wl_closure *closure; - static const uint32_t opcode = 4444; - static struct wl_object sender = { NULL, NULL, 1234 }; - struct wl_message message = { "test", format, NULL }; - va_list ap; - - va_start(ap, format); - closure = wl_closure_vmarshal(&sender, opcode, ap, &message); - va_end(ap); - - assert(closure); - assert(wl_closure_send(closure, data->write_connection) == 0); - - wl_closure_destroy(closure); -} - static void expected_fail_marshal_send(struct marshal_data *data, int expected_error, const char *format, ...) @@ -323,6 +260,7 @@ TEST(connection_marshal_nullables) { struct marshal_data data; struct wl_object object; + struct wl_array array; const char text[] = "curry"; setup_marshal_data(&data); @@ -334,6 +272,9 @@ TEST(connection_marshal_nullables) marshal(&data, "?o", 12, NULL); assert(data.buffer[2] == 0); + marshal(&data, "?a", 12, NULL); + assert(data.buffer[2] == 0); + marshal(&data, "?s", 12, NULL); assert(data.buffer[2] == 0); @@ -341,6 +282,12 @@ TEST(connection_marshal_nullables) marshal(&data, "?o", 12, &object); assert(data.buffer[2] == object.id); + array.data = (void *) text; + array.size = sizeof text; + marshal(&data, "?a", 20, &array); + assert(data.buffer[2] == array.size); + assert(memcmp(&data.buffer[3], text, array.size) == 0); + marshal(&data, "?s", 20, text); assert(data.buffer[2] == sizeof text); assert(strcmp((char *) &data.buffer[3], text) == 0); @@ -402,7 +349,7 @@ demarshal(struct marshal_data *data, const char *format, struct wl_closure *closure; struct wl_map objects; struct wl_object object = { NULL, &func, 0 }; - int size = msg[1] >> 16; + int size = msg[1]; assert(write(data->s[1], msg, size) == size); assert(wl_connection_read(data->read_connection) == size); @@ -425,49 +372,47 @@ TEST(connection_demarshal) data.value.u = 8000; msg[0] = 400200; /* object id */ - msg[1] = 12 << 16; /* size = 12, opcode = 0 */ + msg[1] = 12; /* size = 12, opcode = 0 */ msg[2] = data.value.u; demarshal(&data, "u", msg, (void *) validate_demarshal_u); data.value.i = -557799; msg[0] = 400200; - msg[1] = 12 << 16; + msg[1] = 12; msg[2] = data.value.i; demarshal(&data, "i", msg, (void *) validate_demarshal_i); data.value.s = "superdude"; msg[0] = 400200; - msg[1] = 24 << 16; + msg[1] = 24; msg[2] = 10; - msg[3 + msg[2]/4] = 0; memcpy(&msg[3], data.value.s, msg[2]); demarshal(&data, "s", msg, (void *) validate_demarshal_s); data.value.s = "superdude"; msg[0] = 400200; - msg[1] = 24 << 16; + msg[1] = 24; msg[2] = 10; - msg[3 + msg[2]/4] = 0; memcpy(&msg[3], data.value.s, msg[2]); demarshal(&data, "?s", msg, (void *) validate_demarshal_s); data.value.i = wl_fixed_from_double(-90000.2390); msg[0] = 400200; - msg[1] = 12 << 16; + msg[1] = 12; msg[2] = data.value.i; demarshal(&data, "f", msg, (void *) validate_demarshal_f); data.value.s = NULL; msg[0] = 400200; - msg[1] = 12 << 16; + msg[1] = 12; msg[2] = 0; - demarshal(&data, "?s", msg, (void *) validate_demarshal_s); + demarshal(&data, "?s", msg, (void *) validate_demarshal_s); release_marshal_data(&data); } static void -marshal_demarshal(struct marshal_data *data, +marshal_demarshal(struct marshal_data *data, void (*func)(void), int size, const char *format, ...) { struct wl_closure *closure; @@ -543,87 +488,6 @@ TEST(connection_marshal_demarshal) release_marshal_data(&data); } -static void -expected_fail_demarshal(struct marshal_data *data, const char *format, - const uint32_t *msg, int expected_error) -{ - struct wl_message message = { "test", format, NULL }; - struct wl_closure *closure; - struct wl_map objects; - int size = (msg[1] >> 16); - - assert(write(data->s[1], msg, size) == size); - assert(wl_connection_read(data->read_connection) == size); - - wl_map_init(&objects, WL_MAP_SERVER_SIDE); - closure = wl_connection_demarshal(data->read_connection, - size, &objects, &message); - - assert(closure == NULL); - assert(errno == expected_error); -} - -TEST(connection_demarshal_null_strings) -{ - struct marshal_data data; - uint32_t msg[3]; - - setup_marshal_data(&data); - - data.value.s = NULL; - msg[0] = 400200; /* object id */ - msg[1] = 12 << 16; /* size = 12, opcode = 0 */ - msg[2] = 0; /* string length = 0 */ - demarshal(&data, "?s", msg, (void *) validate_demarshal_s); - - expected_fail_demarshal(&data, "s", msg, EINVAL); - - release_marshal_data(&data); -} - -/* These tests are verifying that the demarshaling code will gracefully handle - * clients lying about string and array lengths and giving values near - * UINT32_MAX. Before fixes f7fdface and f5b9e3b9 this test would crash on - * 32bit systems. - */ -TEST(connection_demarshal_failures) -{ - struct marshal_data data; - unsigned int i; - uint32_t msg[3]; - - const uint32_t overflowing_values[] = { - /* Values very close to UINT32_MAX. Before f5b9e3b9 these - * would cause integer overflow in DIV_ROUNDUP. */ - 0xffffffff, 0xfffffffe, 0xfffffffd, 0xfffffffc, - - /* Values at various offsets from UINT32_MAX. Before f7fdface - * these would overflow the "p" pointer on 32bit systems, - * effectively subtracting the offset from it. It had good - * chance to cause crash depending on what was stored at that - * offset before "p". */ - 0xfffff000, 0xffffd000, 0xffffc000, 0xffffb000 - }; - - setup_marshal_data(&data); - - /* sender_id, does not matter */ - msg[0] = 0; - - /* (size << 16 | opcode), opcode is 0, does not matter */ - msg[1] = sizeof(msg) << 16; - - for (i = 0; i < ARRAY_LENGTH(overflowing_values); i++) { - /* length of the string or array */ - msg[2] = overflowing_values[i]; - - expected_fail_demarshal(&data, "s", msg, EINVAL); - expected_fail_demarshal(&data, "a", msg, EINVAL); - } - - release_marshal_data(&data); -} - TEST(connection_marshal_alot) { struct marshal_data data; @@ -631,7 +495,7 @@ TEST(connection_marshal_alot) int i; setup_marshal_data(&data); - + /* We iterate enough to make sure we wrap the circular buffers * for both regular data an fds. */ @@ -665,46 +529,6 @@ TEST(connection_marshal_too_big) free(big_string); } -TEST(connection_marshal_big_enough) -{ - struct marshal_data data; - char *big_string = malloc(5000); - - assert(big_string); - - memset(big_string, ' ', 4999); - big_string[4999] = '\0'; - - setup_marshal_data(&data); - wl_connection_set_max_buffer_size(data.write_connection, 5120); - - marshal_send(&data, "s", big_string); - - release_marshal_data(&data); - free(big_string); -} - -TEST(connection_marshal_unbounded_boundary_size) -{ - /* A string of length 8178 requires a buffer size of exactly 2^13. */ - struct marshal_data data; - char *big_string = malloc(8178); - assert(big_string); - - memset(big_string, ' ', 8177); - big_string[8177] = '\0'; - - setup_marshal_data(&data); - - /* Set the max size to 0 (unbounded). */ - wl_connection_set_max_buffer_size(data.write_connection, 0); - - marshal_send(&data, "s", big_string); - - release_marshal_data(&data); - free(big_string); -} - static void marshal_helper(const char *format, void *handler, ...) { @@ -734,8 +558,8 @@ suu_handler(void *data, struct wl_object *object, int *done = data; assert(strcmp(s, "foo") == 0); - assert(u1 == 500); - assert(u2 == 404040); + assert(u1 = 500); + assert(u2 = 404040); *done = 1; } @@ -743,167 +567,3 @@ TEST(invoke_closure) { marshal_helper("suu", suu_handler, "foo", 500, 404040); } - -static void -leak_closure(void) -{ - struct wl_callback *cb; - struct pollfd pfd; - struct client *c = client_connect(); - - cb = wl_display_sync(c->wl_display); - assert(cb); - assert(wl_display_flush(c->wl_display) > 0); - - /* we don't need it, it is referenced */ - wl_callback_destroy(cb); - - pfd.fd = wl_display_get_fd(c->wl_display); - pfd.events = POLLIN; - - test_set_timeout(2); - assert(poll(&pfd, 1, -1) == 1); - - /* read events, but do not dispatch them */ - assert(wl_display_prepare_read(c->wl_display) == 0); - assert(wl_display_read_events(c->wl_display) == 0); - - /* - * now we have wl_callback.done and wl_display.delete_id queued; - * if we now release the queue (in wl_display_disconnect()) - * we should not leak memory - */ - - client_disconnect(c); -} - -TEST(closure_leaks) -{ - struct display *d = display_create(); - - client_create_noarg(d, leak_closure); - display_run(d); - - display_destroy(d); -} - -static void -leak_after_error(void) -{ - struct client *c = client_connect(); - - /* this should return -1, because we'll send error - * from server. */ - assert(stop_display(c, 1) == -1); - assert(wl_display_dispatch_pending(c->wl_display) == -1); - assert(wl_display_get_error(c->wl_display) == ENOMEM); - - /* after we got error, we have display_resume event - * in the queue. It should be freed in wl_display_disconnect(). - * Let's see! */ - - wl_proxy_destroy((struct wl_proxy *) c->tc); - wl_display_disconnect(c->wl_display); - free(c); -} - -TEST(closure_leaks_after_error) -{ - struct display *d = display_create(); - struct client_info *cl; - - cl = client_create_noarg(d, leak_after_error); - display_run(d); - - wl_client_post_no_memory(cl->wl_client); - display_resume(d); - - display_destroy(d); -} - -/** Raw read from socket expecting wl_display.error - * - * \param sockfd The socket to read from. - * \param expected_error The expected wl_display error code. - * - * Reads the socket and manually parses one message, expecting it to be a - * wl_display.error with the wl_display as the originating object. - * Asserts that the received error code is expected_error. - */ -static void -expect_error_recv(int sockfd, uint32_t expected_error) -{ - uint32_t buf[1024]; - ssize_t slen; - uint32_t opcode; - int str_len; - - slen = recv(sockfd, buf, sizeof buf, 0); - assert(slen >= 2 * (ssize_t)sizeof (uint32_t)); - opcode = buf[1] & 0xffff; - fprintf(stderr, "Received %zd bytes, object %u, opcode %u\n", - slen, buf[0], opcode); - - /* check error event */ - assert(buf[0] == 1); - assert(opcode == WL_DISPLAY_ERROR); - - str_len = buf[4]; - assert(str_len > 0); - assert(str_len <= slen - 5 * (ssize_t)sizeof (uint32_t)); - fprintf(stderr, "Error event on object %u, code %u, message \"%*s\"\n", - buf[2], buf[3], str_len, (const char *)&buf[5]); - - assert(buf[3] == expected_error); -} - -/* A test for https://gitlab.freedesktop.org/wayland/wayland/issues/52 - * trying to provoke a read from uninitialized memory in - * wl_connection_demarshal() for sender_id and opcode. - * - * This test might not fail as is even with #52 unfixed, since there is no way - * to detect what happens and the crash with zero size depends on stack content. - * However, running under Valgrind would point out invalid reads and use of - * uninitialized values. - */ -TEST(request_bogus_size) -{ - struct wl_display *display; - struct wl_client *client; - int s[2]; - uint32_t msg[3]; - int bogus_size; - - test_set_timeout(1); - - /* - * The manufactured message has real size 12. Test all bogus sizes - * smaller than that, and zero as the last one since wl_closure_init - * handles zero specially and having garbage in the stack makes it more - * likely to crash in wl_connection_demarshal. - */ - for (bogus_size = 11; bogus_size >= 0; bogus_size--) { - fprintf(stderr, "* bogus size %d\n", bogus_size); - - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); - display = wl_display_create(); - assert(display); - client = wl_client_create(display, s[0]); - assert(client); - - /* manufacture a request that lies about its size */ - msg[0] = 1; /* sender id: wl_display */ - msg[1] = (bogus_size << 16) | WL_DISPLAY_SYNC; /* size and opcode */ - msg[2] = 2; /* sync argument: new_id for wl_callback */ - - assert(send(s[1], msg, sizeof msg, 0) == sizeof msg); - - wl_event_loop_dispatch(wl_display_get_event_loop(display), 0); - - expect_error_recv(s[1], WL_DISPLAY_ERROR_INVALID_METHOD); - - /* Do not wl_client_destroy, the error already caused it. */ - close(s[1]); - wl_display_destroy(display); - } -} diff --git a/tests/cpp-compile-test.cpp b/tests/cpp-compile-test.cpp deleted file mode 100644 index 1e84e637..00000000 --- a/tests/cpp-compile-test.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* This source should compile fine with C++ compiler */ -#include "wayland-server-protocol.h" - -int main() { return 0; } - diff --git a/tests/data/README.md b/tests/data/README.md deleted file mode 100644 index 14813453..00000000 --- a/tests/data/README.md +++ /dev/null @@ -1,3 +0,0 @@ -To re-generate the test data, run: - - ninja -C build/ gen-scanner-test diff --git a/tests/data/bad-identifier-arg.xml b/tests/data/bad-identifier-arg.xml deleted file mode 100644 index ac2a6b76..00000000 --- a/tests/data/bad-identifier-arg.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/data/bad-identifier-entry.xml b/tests/data/bad-identifier-entry.xml deleted file mode 100644 index 6ea2fae0..00000000 --- a/tests/data/bad-identifier-entry.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tests/data/bad-identifier-enum.xml b/tests/data/bad-identifier-enum.xml deleted file mode 100644 index 3225384e..00000000 --- a/tests/data/bad-identifier-enum.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/data/bad-identifier-event.xml b/tests/data/bad-identifier-event.xml deleted file mode 100644 index 9708e3bc..00000000 --- a/tests/data/bad-identifier-event.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/data/bad-identifier-interface.xml b/tests/data/bad-identifier-interface.xml deleted file mode 100644 index 17404c5e..00000000 --- a/tests/data/bad-identifier-interface.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/data/bad-identifier-protocol.xml b/tests/data/bad-identifier-protocol.xml deleted file mode 100644 index 1aafb32d..00000000 --- a/tests/data/bad-identifier-protocol.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/data/bad-identifier-request.xml b/tests/data/bad-identifier-request.xml deleted file mode 100644 index a68c8aac..00000000 --- a/tests/data/bad-identifier-request.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/tests/data/empty-client.h b/tests/data/empty-client.h deleted file mode 100644 index bf1264a4..00000000 --- a/tests/data/empty-client.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SCANNER TEST */ - -#ifndef EMPTY_CLIENT_PROTOCOL_H -#define EMPTY_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_empty The empty protocol - * @section page_ifaces_empty Interfaces - * - @subpage page_iface_empty - - */ -struct empty; - -#ifndef EMPTY_INTERFACE -#define EMPTY_INTERFACE -/** - * @page page_iface_empty empty - * @section page_iface_empty_api API - * See @ref iface_empty. - */ -/** - * @defgroup iface_empty The empty interface - */ -extern const struct wl_interface empty_interface; -#endif - -#define EMPTY_EMPTY 0 - - -/** - * @ingroup iface_empty - */ -#define EMPTY_EMPTY_SINCE_VERSION 1 - -/** @ingroup iface_empty */ -static inline void -empty_set_user_data(struct empty *empty, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) empty, user_data); -} - -/** @ingroup iface_empty */ -static inline void * -empty_get_user_data(struct empty *empty) -{ - return wl_proxy_get_user_data((struct wl_proxy *) empty); -} - -static inline uint32_t -empty_get_version(struct empty *empty) -{ - return wl_proxy_get_version((struct wl_proxy *) empty); -} - -/** @ingroup iface_empty */ -static inline void -empty_destroy(struct empty *empty) -{ - wl_proxy_destroy((struct wl_proxy *) empty); -} - -/** - * @ingroup iface_empty - */ -static inline void -empty_empty(struct empty *empty) -{ - wl_proxy_marshal_flags((struct wl_proxy *) empty, - EMPTY_EMPTY, NULL, wl_proxy_get_version((struct wl_proxy *) empty), 0); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/empty-code.c b/tests/data/empty-code.c deleted file mode 100644 index 67382d20..00000000 --- a/tests/data/empty-code.c +++ /dev/null @@ -1,21 +0,0 @@ -/* SCANNER TEST */ - -#include -#include -#include -#include "wayland-util.h" - - -static const struct wl_interface *empty_types[] = { -}; - -static const struct wl_message empty_requests[] = { - { "empty", "", empty_types + 0 }, -}; - -WL_EXPORT const struct wl_interface empty_interface = { - "empty", 1, - 1, empty_requests, - 0, NULL, -}; - diff --git a/tests/data/empty-server.h b/tests/data/empty-server.h deleted file mode 100644 index 4baf6d6b..00000000 --- a/tests/data/empty-server.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SCANNER TEST */ - -#ifndef EMPTY_SERVER_PROTOCOL_H -#define EMPTY_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_empty The empty protocol - * @section page_ifaces_empty Interfaces - * - @subpage page_iface_empty - - */ -struct empty; - -#ifndef EMPTY_INTERFACE -#define EMPTY_INTERFACE -/** - * @page page_iface_empty empty - * @section page_iface_empty_api API - * See @ref iface_empty. - */ -/** - * @defgroup iface_empty The empty interface - */ -extern const struct wl_interface empty_interface; -#endif - -/** - * @ingroup iface_empty - * @struct empty_interface - */ -struct empty_interface { - /** - */ - void (*empty)(struct wl_client *client, - struct wl_resource *resource); -}; - - -/** - * @ingroup iface_empty - */ -#define EMPTY_EMPTY_SINCE_VERSION 1 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/empty.xml b/tests/data/empty.xml deleted file mode 100644 index 2549d8fc..00000000 --- a/tests/data/empty.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/tests/data/example-client.h b/tests/data/example-client.h deleted file mode 100644 index a14b5e00..00000000 --- a/tests/data/example-client.h +++ /dev/null @@ -1,5625 +0,0 @@ -/* SCANNER TEST */ - -#ifndef WAYLAND_CLIENT_PROTOCOL_H -#define WAYLAND_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_wayland The wayland protocol - * @section page_ifaces_wayland Interfaces - * - @subpage page_iface_wl_display - core global object - * - @subpage page_iface_wl_registry - global registry object - * - @subpage page_iface_wl_callback - callback object - * - @subpage page_iface_wl_compositor - the compositor singleton - * - @subpage page_iface_wl_shm_pool - a shared memory pool - * - @subpage page_iface_wl_shm - shared memory support - * - @subpage page_iface_wl_buffer - content for a wl_surface - * - @subpage page_iface_wl_data_offer - offer to transfer data - * - @subpage page_iface_wl_data_source - offer to transfer data - * - @subpage page_iface_wl_data_device - data transfer device - * - @subpage page_iface_wl_data_device_manager - data transfer interface - * - @subpage page_iface_wl_shell - create desktop-style surfaces - * - @subpage page_iface_wl_shell_surface - desktop-style metadata interface - * - @subpage page_iface_wl_surface - an onscreen surface - * - @subpage page_iface_wl_seat - group of input devices - * - @subpage page_iface_wl_pointer - pointer input device - * - @subpage page_iface_wl_keyboard - keyboard input device - * - @subpage page_iface_wl_touch - touchscreen input device - * - @subpage page_iface_wl_output - compositor output region - * - @subpage page_iface_wl_region - region interface - * - @subpage page_iface_wl_subcompositor - sub-surface compositing - * - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface - * @section page_copyright_wayland Copyright - *
- *
- * Copyright © 2008-2011 Kristian Høgsberg
- * Copyright © 2010-2011 Intel Corporation
- * Copyright © 2012-2013 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.
- * 
- */ -struct wl_buffer; -struct wl_callback; -struct wl_compositor; -struct wl_data_device; -struct wl_data_device_manager; -struct wl_data_offer; -struct wl_data_source; -struct wl_display; -struct wl_keyboard; -struct wl_output; -struct wl_pointer; -struct wl_region; -struct wl_registry; -struct wl_seat; -struct wl_shell; -struct wl_shell_surface; -struct wl_shm; -struct wl_shm_pool; -struct wl_subcompositor; -struct wl_subsurface; -struct wl_surface; -struct wl_touch; - -#ifndef WL_DISPLAY_INTERFACE -#define WL_DISPLAY_INTERFACE -/** - * @page page_iface_wl_display wl_display - * @section page_iface_wl_display_desc Description - * - * The core global object. This is a special singleton object. It - * is used for internal Wayland protocol features. - * @section page_iface_wl_display_api API - * See @ref iface_wl_display. - */ -/** - * @defgroup iface_wl_display The wl_display interface - * - * The core global object. This is a special singleton object. It - * is used for internal Wayland protocol features. - */ -extern const struct wl_interface wl_display_interface; -#endif -#ifndef WL_REGISTRY_INTERFACE -#define WL_REGISTRY_INTERFACE -/** - * @page page_iface_wl_registry wl_registry - * @section page_iface_wl_registry_desc Description - * - * The singleton global registry object. The server has a number of - * global objects that are available to all clients. These objects - * typically represent an actual object in the server (for example, - * an input device) or they are singleton objects that provide - * extension functionality. - * - * When a client creates a registry object, the registry object - * will emit a global event for each global currently in the - * registry. Globals come and go as a result of device or - * monitor hotplugs, reconfiguration or other events, and the - * registry will send out global and global_remove events to - * keep the client up to date with the changes. To mark the end - * of the initial burst of events, the client can use the - * wl_display.sync request immediately after calling - * wl_display.get_registry. - * - * A client can bind to a global object by using the bind - * request. This creates a client-side handle that lets the object - * emit events to the client and lets the client invoke requests on - * the object. - * @section page_iface_wl_registry_api API - * See @ref iface_wl_registry. - */ -/** - * @defgroup iface_wl_registry The wl_registry interface - * - * The singleton global registry object. The server has a number of - * global objects that are available to all clients. These objects - * typically represent an actual object in the server (for example, - * an input device) or they are singleton objects that provide - * extension functionality. - * - * When a client creates a registry object, the registry object - * will emit a global event for each global currently in the - * registry. Globals come and go as a result of device or - * monitor hotplugs, reconfiguration or other events, and the - * registry will send out global and global_remove events to - * keep the client up to date with the changes. To mark the end - * of the initial burst of events, the client can use the - * wl_display.sync request immediately after calling - * wl_display.get_registry. - * - * A client can bind to a global object by using the bind - * request. This creates a client-side handle that lets the object - * emit events to the client and lets the client invoke requests on - * the object. - */ -extern const struct wl_interface wl_registry_interface; -#endif -#ifndef WL_CALLBACK_INTERFACE -#define WL_CALLBACK_INTERFACE -/** - * @page page_iface_wl_callback wl_callback - * @section page_iface_wl_callback_desc Description - * - * Clients can handle the 'done' event to get notified when - * the related request is done. - * @section page_iface_wl_callback_api API - * See @ref iface_wl_callback. - */ -/** - * @defgroup iface_wl_callback The wl_callback interface - * - * Clients can handle the 'done' event to get notified when - * the related request is done. - */ -extern const struct wl_interface wl_callback_interface; -#endif -#ifndef WL_COMPOSITOR_INTERFACE -#define WL_COMPOSITOR_INTERFACE -/** - * @page page_iface_wl_compositor wl_compositor - * @section page_iface_wl_compositor_desc Description - * - * A compositor. This object is a singleton global. The - * compositor is in charge of combining the contents of multiple - * surfaces into one displayable output. - * @section page_iface_wl_compositor_api API - * See @ref iface_wl_compositor. - */ -/** - * @defgroup iface_wl_compositor The wl_compositor interface - * - * A compositor. This object is a singleton global. The - * compositor is in charge of combining the contents of multiple - * surfaces into one displayable output. - */ -extern const struct wl_interface wl_compositor_interface; -#endif -#ifndef WL_SHM_POOL_INTERFACE -#define WL_SHM_POOL_INTERFACE -/** - * @page page_iface_wl_shm_pool wl_shm_pool - * @section page_iface_wl_shm_pool_desc Description - * - * The wl_shm_pool object encapsulates a piece of memory shared - * between the compositor and client. Through the wl_shm_pool - * object, the client can allocate shared memory wl_buffer objects. - * All objects created through the same pool share the same - * underlying mapped memory. Reusing the mapped memory avoids the - * setup/teardown overhead and is useful when interactively resizing - * a surface or for many small buffers. - * @section page_iface_wl_shm_pool_api API - * See @ref iface_wl_shm_pool. - */ -/** - * @defgroup iface_wl_shm_pool The wl_shm_pool interface - * - * The wl_shm_pool object encapsulates a piece of memory shared - * between the compositor and client. Through the wl_shm_pool - * object, the client can allocate shared memory wl_buffer objects. - * All objects created through the same pool share the same - * underlying mapped memory. Reusing the mapped memory avoids the - * setup/teardown overhead and is useful when interactively resizing - * a surface or for many small buffers. - */ -extern const struct wl_interface wl_shm_pool_interface; -#endif -#ifndef WL_SHM_INTERFACE -#define WL_SHM_INTERFACE -/** - * @page page_iface_wl_shm wl_shm - * @section page_iface_wl_shm_desc Description - * - * A singleton global object that provides support for shared - * memory. - * - * Clients can create wl_shm_pool objects using the create_pool - * request. - * - * At connection setup time, the wl_shm object emits one or more - * format events to inform clients about the valid pixel formats - * that can be used for buffers. - * @section page_iface_wl_shm_api API - * See @ref iface_wl_shm. - */ -/** - * @defgroup iface_wl_shm The wl_shm interface - * - * A singleton global object that provides support for shared - * memory. - * - * Clients can create wl_shm_pool objects using the create_pool - * request. - * - * At connection setup time, the wl_shm object emits one or more - * format events to inform clients about the valid pixel formats - * that can be used for buffers. - */ -extern const struct wl_interface wl_shm_interface; -#endif -#ifndef WL_BUFFER_INTERFACE -#define WL_BUFFER_INTERFACE -/** - * @page page_iface_wl_buffer wl_buffer - * @section page_iface_wl_buffer_desc Description - * - * A buffer provides the content for a wl_surface. Buffers are - * created through factory interfaces such as wl_drm, wl_shm or - * similar. It has a width and a height and can be attached to a - * wl_surface, but the mechanism by which a client provides and - * updates the contents is defined by the buffer factory interface. - * @section page_iface_wl_buffer_api API - * See @ref iface_wl_buffer. - */ -/** - * @defgroup iface_wl_buffer The wl_buffer interface - * - * A buffer provides the content for a wl_surface. Buffers are - * created through factory interfaces such as wl_drm, wl_shm or - * similar. It has a width and a height and can be attached to a - * wl_surface, but the mechanism by which a client provides and - * updates the contents is defined by the buffer factory interface. - */ -extern const struct wl_interface wl_buffer_interface; -#endif -#ifndef WL_DATA_OFFER_INTERFACE -#define WL_DATA_OFFER_INTERFACE -/** - * @page page_iface_wl_data_offer wl_data_offer - * @section page_iface_wl_data_offer_desc Description - * - * A wl_data_offer represents a piece of data offered for transfer - * by another client (the source client). It is used by the - * copy-and-paste and drag-and-drop mechanisms. The offer - * describes the different mime types that the data can be - * converted to and provides the mechanism for transferring the - * data directly from the source client. - * @section page_iface_wl_data_offer_api API - * See @ref iface_wl_data_offer. - */ -/** - * @defgroup iface_wl_data_offer The wl_data_offer interface - * - * A wl_data_offer represents a piece of data offered for transfer - * by another client (the source client). It is used by the - * copy-and-paste and drag-and-drop mechanisms. The offer - * describes the different mime types that the data can be - * converted to and provides the mechanism for transferring the - * data directly from the source client. - */ -extern const struct wl_interface wl_data_offer_interface; -#endif -#ifndef WL_DATA_SOURCE_INTERFACE -#define WL_DATA_SOURCE_INTERFACE -/** - * @page page_iface_wl_data_source wl_data_source - * @section page_iface_wl_data_source_desc Description - * - * The wl_data_source object is the source side of a wl_data_offer. - * It is created by the source client in a data transfer and - * provides a way to describe the offered data and a way to respond - * to requests to transfer the data. - * @section page_iface_wl_data_source_api API - * See @ref iface_wl_data_source. - */ -/** - * @defgroup iface_wl_data_source The wl_data_source interface - * - * The wl_data_source object is the source side of a wl_data_offer. - * It is created by the source client in a data transfer and - * provides a way to describe the offered data and a way to respond - * to requests to transfer the data. - */ -extern const struct wl_interface wl_data_source_interface; -#endif -#ifndef WL_DATA_DEVICE_INTERFACE -#define WL_DATA_DEVICE_INTERFACE -/** - * @page page_iface_wl_data_device wl_data_device - * @section page_iface_wl_data_device_desc Description - * - * There is one wl_data_device per seat which can be obtained - * from the global wl_data_device_manager singleton. - * - * A wl_data_device provides access to inter-client data transfer - * mechanisms such as copy-and-paste and drag-and-drop. - * @section page_iface_wl_data_device_api API - * See @ref iface_wl_data_device. - */ -/** - * @defgroup iface_wl_data_device The wl_data_device interface - * - * There is one wl_data_device per seat which can be obtained - * from the global wl_data_device_manager singleton. - * - * A wl_data_device provides access to inter-client data transfer - * mechanisms such as copy-and-paste and drag-and-drop. - */ -extern const struct wl_interface wl_data_device_interface; -#endif -#ifndef WL_DATA_DEVICE_MANAGER_INTERFACE -#define WL_DATA_DEVICE_MANAGER_INTERFACE -/** - * @page page_iface_wl_data_device_manager wl_data_device_manager - * @section page_iface_wl_data_device_manager_desc Description - * - * The wl_data_device_manager is a singleton global object that - * provides access to inter-client data transfer mechanisms such as - * copy-and-paste and drag-and-drop. These mechanisms are tied to - * a wl_seat and this interface lets a client get a wl_data_device - * corresponding to a wl_seat. - * - * Depending on the version bound, the objects created from the bound - * wl_data_device_manager object will have different requirements for - * functioning properly. See wl_data_source.set_actions, - * wl_data_offer.accept and wl_data_offer.finish for details. - * @section page_iface_wl_data_device_manager_api API - * See @ref iface_wl_data_device_manager. - */ -/** - * @defgroup iface_wl_data_device_manager The wl_data_device_manager interface - * - * The wl_data_device_manager is a singleton global object that - * provides access to inter-client data transfer mechanisms such as - * copy-and-paste and drag-and-drop. These mechanisms are tied to - * a wl_seat and this interface lets a client get a wl_data_device - * corresponding to a wl_seat. - * - * Depending on the version bound, the objects created from the bound - * wl_data_device_manager object will have different requirements for - * functioning properly. See wl_data_source.set_actions, - * wl_data_offer.accept and wl_data_offer.finish for details. - */ -extern const struct wl_interface wl_data_device_manager_interface; -#endif -#ifndef WL_SHELL_INTERFACE -#define WL_SHELL_INTERFACE -/** - * @page page_iface_wl_shell wl_shell - * @section page_iface_wl_shell_desc Description - * - * This interface is implemented by servers that provide - * desktop-style user interfaces. - * - * It allows clients to associate a wl_shell_surface with - * a basic surface. - * @section page_iface_wl_shell_api API - * See @ref iface_wl_shell. - */ -/** - * @defgroup iface_wl_shell The wl_shell interface - * - * This interface is implemented by servers that provide - * desktop-style user interfaces. - * - * It allows clients to associate a wl_shell_surface with - * a basic surface. - */ -extern const struct wl_interface wl_shell_interface; -#endif -#ifndef WL_SHELL_SURFACE_INTERFACE -#define WL_SHELL_SURFACE_INTERFACE -/** - * @page page_iface_wl_shell_surface wl_shell_surface - * @section page_iface_wl_shell_surface_desc Description - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides requests to treat surfaces like toplevel, fullscreen - * or popup windows, move, resize or maximize them, associate - * metadata like title and class, etc. - * - * On the server side the object is automatically destroyed when - * the related wl_surface is destroyed. On the client side, - * wl_shell_surface_destroy() must be called before destroying - * the wl_surface object. - * @section page_iface_wl_shell_surface_api API - * See @ref iface_wl_shell_surface. - */ -/** - * @defgroup iface_wl_shell_surface The wl_shell_surface interface - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides requests to treat surfaces like toplevel, fullscreen - * or popup windows, move, resize or maximize them, associate - * metadata like title and class, etc. - * - * On the server side the object is automatically destroyed when - * the related wl_surface is destroyed. On the client side, - * wl_shell_surface_destroy() must be called before destroying - * the wl_surface object. - */ -extern const struct wl_interface wl_shell_surface_interface; -#endif -#ifndef WL_SURFACE_INTERFACE -#define WL_SURFACE_INTERFACE -/** - * @page page_iface_wl_surface wl_surface - * @section page_iface_wl_surface_desc Description - * - * A surface is a rectangular area that is displayed on the screen. - * It has a location, size and pixel contents. - * - * The size of a surface (and relative positions on it) is described - * in surface-local coordinates, which may differ from the buffer - * coordinates of the pixel content, in case a buffer_transform - * or a buffer_scale is used. - * - * A surface without a "role" is fairly useless: a compositor does - * not know where, when or how to present it. The role is the - * purpose of a wl_surface. Examples of roles are a cursor for a - * pointer (as set by wl_pointer.set_cursor), a drag icon - * (wl_data_device.start_drag), a sub-surface - * (wl_subcompositor.get_subsurface), and a window as defined by a - * shell protocol (e.g. wl_shell.get_shell_surface). - * - * A surface can have only one role at a time. Initially a - * wl_surface does not have a role. Once a wl_surface is given a - * role, it is set permanently for the whole lifetime of the - * wl_surface object. Giving the current role again is allowed, - * unless explicitly forbidden by the relevant interface - * specification. - * - * Surface roles are given by requests in other interfaces such as - * wl_pointer.set_cursor. The request should explicitly mention - * that this request gives a role to a wl_surface. Often, this - * request also creates a new protocol object that represents the - * role and adds additional functionality to wl_surface. When a - * client wants to destroy a wl_surface, they must destroy this 'role - * object' before the wl_surface. - * - * Destroying the role object does not remove the role from the - * wl_surface, but it may stop the wl_surface from "playing the role". - * For instance, if a wl_subsurface object is destroyed, the wl_surface - * it was created for will be unmapped and forget its position and - * z-order. It is allowed to create a wl_subsurface for the same - * wl_surface again, but it is not allowed to use the wl_surface as - * a cursor (cursor is a different role than sub-surface, and role - * switching is not allowed). - * @section page_iface_wl_surface_api API - * See @ref iface_wl_surface. - */ -/** - * @defgroup iface_wl_surface The wl_surface interface - * - * A surface is a rectangular area that is displayed on the screen. - * It has a location, size and pixel contents. - * - * The size of a surface (and relative positions on it) is described - * in surface-local coordinates, which may differ from the buffer - * coordinates of the pixel content, in case a buffer_transform - * or a buffer_scale is used. - * - * A surface without a "role" is fairly useless: a compositor does - * not know where, when or how to present it. The role is the - * purpose of a wl_surface. Examples of roles are a cursor for a - * pointer (as set by wl_pointer.set_cursor), a drag icon - * (wl_data_device.start_drag), a sub-surface - * (wl_subcompositor.get_subsurface), and a window as defined by a - * shell protocol (e.g. wl_shell.get_shell_surface). - * - * A surface can have only one role at a time. Initially a - * wl_surface does not have a role. Once a wl_surface is given a - * role, it is set permanently for the whole lifetime of the - * wl_surface object. Giving the current role again is allowed, - * unless explicitly forbidden by the relevant interface - * specification. - * - * Surface roles are given by requests in other interfaces such as - * wl_pointer.set_cursor. The request should explicitly mention - * that this request gives a role to a wl_surface. Often, this - * request also creates a new protocol object that represents the - * role and adds additional functionality to wl_surface. When a - * client wants to destroy a wl_surface, they must destroy this 'role - * object' before the wl_surface. - * - * Destroying the role object does not remove the role from the - * wl_surface, but it may stop the wl_surface from "playing the role". - * For instance, if a wl_subsurface object is destroyed, the wl_surface - * it was created for will be unmapped and forget its position and - * z-order. It is allowed to create a wl_subsurface for the same - * wl_surface again, but it is not allowed to use the wl_surface as - * a cursor (cursor is a different role than sub-surface, and role - * switching is not allowed). - */ -extern const struct wl_interface wl_surface_interface; -#endif -#ifndef WL_SEAT_INTERFACE -#define WL_SEAT_INTERFACE -/** - * @page page_iface_wl_seat wl_seat - * @section page_iface_wl_seat_desc Description - * - * A seat is a group of keyboards, pointer and touch devices. This - * object is published as a global during start up, or when such a - * device is hot plugged. A seat typically has a pointer and - * maintains a keyboard focus and a pointer focus. - * @section page_iface_wl_seat_api API - * See @ref iface_wl_seat. - */ -/** - * @defgroup iface_wl_seat The wl_seat interface - * - * A seat is a group of keyboards, pointer and touch devices. This - * object is published as a global during start up, or when such a - * device is hot plugged. A seat typically has a pointer and - * maintains a keyboard focus and a pointer focus. - */ -extern const struct wl_interface wl_seat_interface; -#endif -#ifndef WL_POINTER_INTERFACE -#define WL_POINTER_INTERFACE -/** - * @page page_iface_wl_pointer wl_pointer - * @section page_iface_wl_pointer_desc Description - * - * The wl_pointer interface represents one or more input devices, - * such as mice, which control the pointer location and pointer_focus - * of a seat. - * - * The wl_pointer interface generates motion, enter and leave - * events for the surfaces that the pointer is located over, - * and button and axis events for button presses, button releases - * and scrolling. - * @section page_iface_wl_pointer_api API - * See @ref iface_wl_pointer. - */ -/** - * @defgroup iface_wl_pointer The wl_pointer interface - * - * The wl_pointer interface represents one or more input devices, - * such as mice, which control the pointer location and pointer_focus - * of a seat. - * - * The wl_pointer interface generates motion, enter and leave - * events for the surfaces that the pointer is located over, - * and button and axis events for button presses, button releases - * and scrolling. - */ -extern const struct wl_interface wl_pointer_interface; -#endif -#ifndef WL_KEYBOARD_INTERFACE -#define WL_KEYBOARD_INTERFACE -/** - * @page page_iface_wl_keyboard wl_keyboard - * @section page_iface_wl_keyboard_desc Description - * - * The wl_keyboard interface represents one or more keyboards - * associated with a seat. - * @section page_iface_wl_keyboard_api API - * See @ref iface_wl_keyboard. - */ -/** - * @defgroup iface_wl_keyboard The wl_keyboard interface - * - * The wl_keyboard interface represents one or more keyboards - * associated with a seat. - */ -extern const struct wl_interface wl_keyboard_interface; -#endif -#ifndef WL_TOUCH_INTERFACE -#define WL_TOUCH_INTERFACE -/** - * @page page_iface_wl_touch wl_touch - * @section page_iface_wl_touch_desc Description - * - * The wl_touch interface represents a touchscreen - * associated with a seat. - * - * Touch interactions can consist of one or more contacts. - * For each contact, a series of events is generated, starting - * with a down event, followed by zero or more motion events, - * and ending with an up event. Events relating to the same - * contact point can be identified by the ID of the sequence. - * @section page_iface_wl_touch_api API - * See @ref iface_wl_touch. - */ -/** - * @defgroup iface_wl_touch The wl_touch interface - * - * The wl_touch interface represents a touchscreen - * associated with a seat. - * - * Touch interactions can consist of one or more contacts. - * For each contact, a series of events is generated, starting - * with a down event, followed by zero or more motion events, - * and ending with an up event. Events relating to the same - * contact point can be identified by the ID of the sequence. - */ -extern const struct wl_interface wl_touch_interface; -#endif -#ifndef WL_OUTPUT_INTERFACE -#define WL_OUTPUT_INTERFACE -/** - * @page page_iface_wl_output wl_output - * @section page_iface_wl_output_desc Description - * - * An output describes part of the compositor geometry. The - * compositor works in the 'compositor coordinate system' and an - * output corresponds to a rectangular area in that space that is - * actually visible. This typically corresponds to a monitor that - * displays part of the compositor space. This object is published - * as global during start up, or when a monitor is hotplugged. - * @section page_iface_wl_output_api API - * See @ref iface_wl_output. - */ -/** - * @defgroup iface_wl_output The wl_output interface - * - * An output describes part of the compositor geometry. The - * compositor works in the 'compositor coordinate system' and an - * output corresponds to a rectangular area in that space that is - * actually visible. This typically corresponds to a monitor that - * displays part of the compositor space. This object is published - * as global during start up, or when a monitor is hotplugged. - */ -extern const struct wl_interface wl_output_interface; -#endif -#ifndef WL_REGION_INTERFACE -#define WL_REGION_INTERFACE -/** - * @page page_iface_wl_region wl_region - * @section page_iface_wl_region_desc Description - * - * A region object describes an area. - * - * Region objects are used to describe the opaque and input - * regions of a surface. - * @section page_iface_wl_region_api API - * See @ref iface_wl_region. - */ -/** - * @defgroup iface_wl_region The wl_region interface - * - * A region object describes an area. - * - * Region objects are used to describe the opaque and input - * regions of a surface. - */ -extern const struct wl_interface wl_region_interface; -#endif -#ifndef WL_SUBCOMPOSITOR_INTERFACE -#define WL_SUBCOMPOSITOR_INTERFACE -/** - * @page page_iface_wl_subcompositor wl_subcompositor - * @section page_iface_wl_subcompositor_desc Description - * - * The global interface exposing sub-surface compositing capabilities. - * A wl_surface, that has sub-surfaces associated, is called the - * parent surface. Sub-surfaces can be arbitrarily nested and create - * a tree of sub-surfaces. - * - * The root surface in a tree of sub-surfaces is the main - * surface. The main surface cannot be a sub-surface, because - * sub-surfaces must always have a parent. - * - * A main surface with its sub-surfaces forms a (compound) window. - * For window management purposes, this set of wl_surface objects is - * to be considered as a single window, and it should also behave as - * such. - * - * The aim of sub-surfaces is to offload some of the compositing work - * within a window from clients to the compositor. A prime example is - * a video player with decorations and video in separate wl_surface - * objects. This should allow the compositor to pass YUV video buffer - * processing to dedicated overlay hardware when possible. - * @section page_iface_wl_subcompositor_api API - * See @ref iface_wl_subcompositor. - */ -/** - * @defgroup iface_wl_subcompositor The wl_subcompositor interface - * - * The global interface exposing sub-surface compositing capabilities. - * A wl_surface, that has sub-surfaces associated, is called the - * parent surface. Sub-surfaces can be arbitrarily nested and create - * a tree of sub-surfaces. - * - * The root surface in a tree of sub-surfaces is the main - * surface. The main surface cannot be a sub-surface, because - * sub-surfaces must always have a parent. - * - * A main surface with its sub-surfaces forms a (compound) window. - * For window management purposes, this set of wl_surface objects is - * to be considered as a single window, and it should also behave as - * such. - * - * The aim of sub-surfaces is to offload some of the compositing work - * within a window from clients to the compositor. A prime example is - * a video player with decorations and video in separate wl_surface - * objects. This should allow the compositor to pass YUV video buffer - * processing to dedicated overlay hardware when possible. - */ -extern const struct wl_interface wl_subcompositor_interface; -#endif -#ifndef WL_SUBSURFACE_INTERFACE -#define WL_SUBSURFACE_INTERFACE -/** - * @page page_iface_wl_subsurface wl_subsurface - * @section page_iface_wl_subsurface_desc Description - * - * An additional interface to a wl_surface object, which has been - * made a sub-surface. A sub-surface has one parent surface. A - * sub-surface's size and position are not limited to that of the parent. - * Particularly, a sub-surface is not automatically clipped to its - * parent's area. - * - * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied - * and the parent surface is mapped. The order of which one happens - * first is irrelevant. A sub-surface is hidden if the parent becomes - * hidden, or if a NULL wl_buffer is applied. These rules apply - * recursively through the tree of surfaces. - * - * The behaviour of a wl_surface.commit request on a sub-surface - * depends on the sub-surface's mode. The possible modes are - * synchronized and desynchronized, see methods - * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized - * mode caches the wl_surface state to be applied when the parent's - * state gets applied, and desynchronized mode applies the pending - * wl_surface state directly. A sub-surface is initially in the - * synchronized mode. - * - * Sub-surfaces have also other kind of state, which is managed by - * wl_subsurface requests, as opposed to wl_surface requests. This - * state includes the sub-surface position relative to the parent - * surface (wl_subsurface.set_position), and the stacking order of - * the parent and its sub-surfaces (wl_subsurface.place_above and - * .place_below). This state is applied when the parent surface's - * wl_surface state is applied, regardless of the sub-surface's mode. - * As the exception, set_sync and set_desync are effective immediately. - * - * The main surface can be thought to be always in desynchronized mode, - * since it does not have a parent in the sub-surfaces sense. - * - * Even if a sub-surface is in desynchronized mode, it will behave as - * in synchronized mode, if its parent surface behaves as in - * synchronized mode. This rule is applied recursively throughout the - * tree of surfaces. This means, that one can set a sub-surface into - * synchronized mode, and then assume that all its child and grand-child - * sub-surfaces are synchronized, too, without explicitly setting them. - * - * If the wl_surface associated with the wl_subsurface is destroyed, the - * wl_subsurface object becomes inert. Note, that destroying either object - * takes effect immediately. If you need to synchronize the removal - * of a sub-surface to the parent surface update, unmap the sub-surface - * first by attaching a NULL wl_buffer, update parent, and then destroy - * the sub-surface. - * - * If the parent wl_surface object is destroyed, the sub-surface is - * unmapped. - * @section page_iface_wl_subsurface_api API - * See @ref iface_wl_subsurface. - */ -/** - * @defgroup iface_wl_subsurface The wl_subsurface interface - * - * An additional interface to a wl_surface object, which has been - * made a sub-surface. A sub-surface has one parent surface. A - * sub-surface's size and position are not limited to that of the parent. - * Particularly, a sub-surface is not automatically clipped to its - * parent's area. - * - * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied - * and the parent surface is mapped. The order of which one happens - * first is irrelevant. A sub-surface is hidden if the parent becomes - * hidden, or if a NULL wl_buffer is applied. These rules apply - * recursively through the tree of surfaces. - * - * The behaviour of a wl_surface.commit request on a sub-surface - * depends on the sub-surface's mode. The possible modes are - * synchronized and desynchronized, see methods - * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized - * mode caches the wl_surface state to be applied when the parent's - * state gets applied, and desynchronized mode applies the pending - * wl_surface state directly. A sub-surface is initially in the - * synchronized mode. - * - * Sub-surfaces have also other kind of state, which is managed by - * wl_subsurface requests, as opposed to wl_surface requests. This - * state includes the sub-surface position relative to the parent - * surface (wl_subsurface.set_position), and the stacking order of - * the parent and its sub-surfaces (wl_subsurface.place_above and - * .place_below). This state is applied when the parent surface's - * wl_surface state is applied, regardless of the sub-surface's mode. - * As the exception, set_sync and set_desync are effective immediately. - * - * The main surface can be thought to be always in desynchronized mode, - * since it does not have a parent in the sub-surfaces sense. - * - * Even if a sub-surface is in desynchronized mode, it will behave as - * in synchronized mode, if its parent surface behaves as in - * synchronized mode. This rule is applied recursively throughout the - * tree of surfaces. This means, that one can set a sub-surface into - * synchronized mode, and then assume that all its child and grand-child - * sub-surfaces are synchronized, too, without explicitly setting them. - * - * If the wl_surface associated with the wl_subsurface is destroyed, the - * wl_subsurface object becomes inert. Note, that destroying either object - * takes effect immediately. If you need to synchronize the removal - * of a sub-surface to the parent surface update, unmap the sub-surface - * first by attaching a NULL wl_buffer, update parent, and then destroy - * the sub-surface. - * - * If the parent wl_surface object is destroyed, the sub-surface is - * unmapped. - */ -extern const struct wl_interface wl_subsurface_interface; -#endif - -#ifndef WL_DISPLAY_ERROR_ENUM -#define WL_DISPLAY_ERROR_ENUM -/** - * @ingroup iface_wl_display - * global error values - * - * These errors are global and can be emitted in response to any - * server request. - */ -enum wl_display_error { - /** - * server couldn't find object - */ - WL_DISPLAY_ERROR_INVALID_OBJECT = 0, - /** - * method doesn't exist on the specified interface - */ - WL_DISPLAY_ERROR_INVALID_METHOD = 1, - /** - * server is out of memory - */ - WL_DISPLAY_ERROR_NO_MEMORY = 2, -}; -#endif /* WL_DISPLAY_ERROR_ENUM */ - -/** - * @ingroup iface_wl_display - * @struct wl_display_listener - */ -struct wl_display_listener { - /** - * fatal error event - * - * The error event is sent out when a fatal (non-recoverable) - * error has occurred. The object_id argument is the object where - * the error occurred, most often in response to a request to that - * object. The code identifies the error and is defined by the - * object interface. As such, each interface defines its own set of - * error codes. The message is a brief description of the error, - * for (debugging) convenience. - * @param object_id object where the error occurred - * @param code error code - * @param message error description - */ - void (*error)(void *data, - struct wl_display *wl_display, - void *object_id, - uint32_t code, - const char *message); - /** - * acknowledge object ID deletion - * - * This event is used internally by the object ID management - * logic. When a client deletes an object, the server will send - * this event to acknowledge that it has seen the delete request. - * When the client receives this event, it will know that it can - * safely reuse the object ID. - * @param id deleted object ID - */ - void (*delete_id)(void *data, - struct wl_display *wl_display, - uint32_t id); -}; - -/** - * @ingroup iface_wl_display - */ -static inline int -wl_display_add_listener(struct wl_display *wl_display, - const struct wl_display_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_display, - (void (**)(void)) listener, data); -} - -#define WL_DISPLAY_SYNC 0 -#define WL_DISPLAY_GET_REGISTRY 1 - -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_ERROR_SINCE_VERSION 1 -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_DELETE_ID_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_SYNC_SINCE_VERSION 1 -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_GET_REGISTRY_SINCE_VERSION 1 - -/** @ingroup iface_wl_display */ -static inline void -wl_display_set_user_data(struct wl_display *wl_display, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_display, user_data); -} - -/** @ingroup iface_wl_display */ -static inline void * -wl_display_get_user_data(struct wl_display *wl_display) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_display); -} - -static inline uint32_t -wl_display_get_version(struct wl_display *wl_display) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_display); -} - -/** - * @ingroup iface_wl_display - * - * The sync request asks the server to emit the 'done' event - * on the returned wl_callback object. Since requests are - * handled in-order and events are delivered in-order, this can - * be used as a barrier to ensure all previous requests and the - * resulting events have been handled. - * - * The object returned by this request will be destroyed by the - * compositor after the callback is fired and as such the client must not - * attempt to use it after that point. - * - * The callback_data passed in the callback is the event serial. - */ -static inline struct wl_callback * -wl_display_sync(struct wl_display *wl_display) -{ - struct wl_proxy *callback; - - callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_display, - WL_DISPLAY_SYNC, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL); - - return (struct wl_callback *) callback; -} - -/** - * @ingroup iface_wl_display - * - * This request creates a registry object that allows the client - * to list and bind the global objects available from the - * compositor. - */ -static inline struct wl_registry * -wl_display_get_registry(struct wl_display *wl_display) -{ - struct wl_proxy *registry; - - registry = wl_proxy_marshal_flags((struct wl_proxy *) wl_display, - WL_DISPLAY_GET_REGISTRY, &wl_registry_interface, wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL); - - return (struct wl_registry *) registry; -} - -/** - * @ingroup iface_wl_registry - * @struct wl_registry_listener - */ -struct wl_registry_listener { - /** - * announce global object - * - * Notify the client of global objects. - * - * The event notifies the client that a global object with the - * given name is now available, and it implements the given version - * of the given interface. - * @param name numeric name of the global object - * @param interface interface implemented by the object - * @param version interface version - */ - void (*global)(void *data, - struct wl_registry *wl_registry, - uint32_t name, - const char *interface, - uint32_t version); - /** - * announce removal of global object - * - * Notify the client of removed global objects. - * - * This event notifies the client that the global identified by - * name is no longer available. If the client bound to the global - * using the bind request, the client should now destroy that - * object. - * - * The object remains valid and requests to the object will be - * ignored until the client destroys it, to avoid races between the - * global going away and a client sending a request to it. - * @param name numeric name of the global object - */ - void (*global_remove)(void *data, - struct wl_registry *wl_registry, - uint32_t name); -}; - -/** - * @ingroup iface_wl_registry - */ -static inline int -wl_registry_add_listener(struct wl_registry *wl_registry, - const struct wl_registry_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_registry, - (void (**)(void)) listener, data); -} - -#define WL_REGISTRY_BIND 0 - -/** - * @ingroup iface_wl_registry - */ -#define WL_REGISTRY_GLOBAL_SINCE_VERSION 1 -/** - * @ingroup iface_wl_registry - */ -#define WL_REGISTRY_GLOBAL_REMOVE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_registry - */ -#define WL_REGISTRY_BIND_SINCE_VERSION 1 - -/** @ingroup iface_wl_registry */ -static inline void -wl_registry_set_user_data(struct wl_registry *wl_registry, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_registry, user_data); -} - -/** @ingroup iface_wl_registry */ -static inline void * -wl_registry_get_user_data(struct wl_registry *wl_registry) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_registry); -} - -static inline uint32_t -wl_registry_get_version(struct wl_registry *wl_registry) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_registry); -} - -/** @ingroup iface_wl_registry */ -static inline void -wl_registry_destroy(struct wl_registry *wl_registry) -{ - wl_proxy_destroy((struct wl_proxy *) wl_registry); -} - -/** - * @ingroup iface_wl_registry - * - * Binds a new, client-created object to the server using the - * specified name as the identifier. - */ -static inline void * -wl_registry_bind(struct wl_registry *wl_registry, uint32_t name, const struct wl_interface *interface, uint32_t version) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_registry, - WL_REGISTRY_BIND, interface, version, 0, name, interface->name, version, NULL); - - return (void *) id; -} - -/** - * @ingroup iface_wl_callback - * @struct wl_callback_listener - */ -struct wl_callback_listener { - /** - * done event - * - * Notify the client when the related request is done. - * @param callback_data request-specific data for the callback - */ - void (*done)(void *data, - struct wl_callback *wl_callback, - uint32_t callback_data); -}; - -/** - * @ingroup iface_wl_callback - */ -static inline int -wl_callback_add_listener(struct wl_callback *wl_callback, - const struct wl_callback_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_callback, - (void (**)(void)) listener, data); -} - -/** - * @ingroup iface_wl_callback - */ -#define WL_CALLBACK_DONE_SINCE_VERSION 1 - - -/** @ingroup iface_wl_callback */ -static inline void -wl_callback_set_user_data(struct wl_callback *wl_callback, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_callback, user_data); -} - -/** @ingroup iface_wl_callback */ -static inline void * -wl_callback_get_user_data(struct wl_callback *wl_callback) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_callback); -} - -static inline uint32_t -wl_callback_get_version(struct wl_callback *wl_callback) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_callback); -} - -/** @ingroup iface_wl_callback */ -static inline void -wl_callback_destroy(struct wl_callback *wl_callback) -{ - wl_proxy_destroy((struct wl_proxy *) wl_callback); -} - -#define WL_COMPOSITOR_CREATE_SURFACE 0 -#define WL_COMPOSITOR_CREATE_REGION 1 - - -/** - * @ingroup iface_wl_compositor - */ -#define WL_COMPOSITOR_CREATE_SURFACE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_compositor - */ -#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1 - -/** @ingroup iface_wl_compositor */ -static inline void -wl_compositor_set_user_data(struct wl_compositor *wl_compositor, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_compositor, user_data); -} - -/** @ingroup iface_wl_compositor */ -static inline void * -wl_compositor_get_user_data(struct wl_compositor *wl_compositor) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_compositor); -} - -static inline uint32_t -wl_compositor_get_version(struct wl_compositor *wl_compositor) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_compositor); -} - -/** @ingroup iface_wl_compositor */ -static inline void -wl_compositor_destroy(struct wl_compositor *wl_compositor) -{ - wl_proxy_destroy((struct wl_proxy *) wl_compositor); -} - -/** - * @ingroup iface_wl_compositor - * - * Ask the compositor to create a new surface. - */ -static inline struct wl_surface * -wl_compositor_create_surface(struct wl_compositor *wl_compositor) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor, - WL_COMPOSITOR_CREATE_SURFACE, &wl_surface_interface, wl_proxy_get_version((struct wl_proxy *) wl_compositor), 0, NULL); - - return (struct wl_surface *) id; -} - -/** - * @ingroup iface_wl_compositor - * - * Ask the compositor to create a new region. - */ -static inline struct wl_region * -wl_compositor_create_region(struct wl_compositor *wl_compositor) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor, - WL_COMPOSITOR_CREATE_REGION, &wl_region_interface, wl_proxy_get_version((struct wl_proxy *) wl_compositor), 0, NULL); - - return (struct wl_region *) id; -} - -#define WL_SHM_POOL_CREATE_BUFFER 0 -#define WL_SHM_POOL_DESTROY 1 -#define WL_SHM_POOL_RESIZE 2 - - -/** - * @ingroup iface_wl_shm_pool - */ -#define WL_SHM_POOL_CREATE_BUFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shm_pool - */ -#define WL_SHM_POOL_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shm_pool - */ -#define WL_SHM_POOL_RESIZE_SINCE_VERSION 1 - -/** @ingroup iface_wl_shm_pool */ -static inline void -wl_shm_pool_set_user_data(struct wl_shm_pool *wl_shm_pool, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_shm_pool, user_data); -} - -/** @ingroup iface_wl_shm_pool */ -static inline void * -wl_shm_pool_get_user_data(struct wl_shm_pool *wl_shm_pool) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_shm_pool); -} - -static inline uint32_t -wl_shm_pool_get_version(struct wl_shm_pool *wl_shm_pool) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_shm_pool); -} - -/** - * @ingroup iface_wl_shm_pool - * - * Create a wl_buffer object from the pool. - * - * The buffer is created offset bytes into the pool and has - * width and height as specified. The stride argument specifies - * the number of bytes from the beginning of one row to the beginning - * of the next. The format is the pixel format of the buffer and - * must be one of those advertised through the wl_shm.format event. - * - * A buffer will keep a reference to the pool it was created from - * so it is valid to destroy the pool immediately after creating - * a buffer from it. - */ -static inline struct wl_buffer * -wl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool, - WL_SHM_POOL_CREATE_BUFFER, &wl_buffer_interface, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), 0, NULL, offset, width, height, stride, format); - - return (struct wl_buffer *) id; -} - -/** - * @ingroup iface_wl_shm_pool - * - * Destroy the shared memory pool. - * - * The mmapped memory will be released when all - * buffers that have been created from this pool - * are gone. - */ -static inline void -wl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool, - WL_SHM_POOL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_shm_pool - * - * This request will cause the server to remap the backing memory - * for the pool from the file descriptor passed when the pool was - * created, but using the new size. This request can only be - * used to make the pool bigger. - */ -static inline void -wl_shm_pool_resize(struct wl_shm_pool *wl_shm_pool, int32_t size) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool, - WL_SHM_POOL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), 0, size); -} - -#ifndef WL_SHM_ERROR_ENUM -#define WL_SHM_ERROR_ENUM -/** - * @ingroup iface_wl_shm - * wl_shm error values - * - * These errors can be emitted in response to wl_shm requests. - */ -enum wl_shm_error { - /** - * buffer format is not known - */ - WL_SHM_ERROR_INVALID_FORMAT = 0, - /** - * invalid size or stride during pool or buffer creation - */ - WL_SHM_ERROR_INVALID_STRIDE = 1, - /** - * mmapping the file descriptor failed - */ - WL_SHM_ERROR_INVALID_FD = 2, -}; -#endif /* WL_SHM_ERROR_ENUM */ - -#ifndef WL_SHM_FORMAT_ENUM -#define WL_SHM_FORMAT_ENUM -/** - * @ingroup iface_wl_shm - * pixel formats - * - * This describes the memory layout of an individual pixel. - * - * All renderers should support argb8888 and xrgb8888 but any other - * formats are optional and may not be supported by the particular - * renderer in use. - * - * The drm format codes match the macros defined in drm_fourcc.h. - * The formats actually supported by the compositor will be - * reported by the format event. - */ -enum wl_shm_format { - /** - * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian - */ - WL_SHM_FORMAT_ARGB8888 = 0, - /** - * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian - */ - WL_SHM_FORMAT_XRGB8888 = 1, - /** - * 8-bit color index format, [7:0] C - */ - WL_SHM_FORMAT_C8 = 0x20203843, - /** - * 8-bit RGB format, [7:0] R:G:B 3:3:2 - */ - WL_SHM_FORMAT_RGB332 = 0x38424752, - /** - * 8-bit BGR format, [7:0] B:G:R 2:3:3 - */ - WL_SHM_FORMAT_BGR233 = 0x38524742, - /** - * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian - */ - WL_SHM_FORMAT_XRGB4444 = 0x32315258, - /** - * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian - */ - WL_SHM_FORMAT_XBGR4444 = 0x32314258, - /** - * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian - */ - WL_SHM_FORMAT_RGBX4444 = 0x32315852, - /** - * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian - */ - WL_SHM_FORMAT_BGRX4444 = 0x32315842, - /** - * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian - */ - WL_SHM_FORMAT_ARGB4444 = 0x32315241, - /** - * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian - */ - WL_SHM_FORMAT_ABGR4444 = 0x32314241, - /** - * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian - */ - WL_SHM_FORMAT_RGBA4444 = 0x32314152, - /** - * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian - */ - WL_SHM_FORMAT_BGRA4444 = 0x32314142, - /** - * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian - */ - WL_SHM_FORMAT_XRGB1555 = 0x35315258, - /** - * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian - */ - WL_SHM_FORMAT_XBGR1555 = 0x35314258, - /** - * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian - */ - WL_SHM_FORMAT_RGBX5551 = 0x35315852, - /** - * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian - */ - WL_SHM_FORMAT_BGRX5551 = 0x35315842, - /** - * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian - */ - WL_SHM_FORMAT_ARGB1555 = 0x35315241, - /** - * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian - */ - WL_SHM_FORMAT_ABGR1555 = 0x35314241, - /** - * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian - */ - WL_SHM_FORMAT_RGBA5551 = 0x35314152, - /** - * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian - */ - WL_SHM_FORMAT_BGRA5551 = 0x35314142, - /** - * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian - */ - WL_SHM_FORMAT_RGB565 = 0x36314752, - /** - * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian - */ - WL_SHM_FORMAT_BGR565 = 0x36314742, - /** - * 24-bit RGB format, [23:0] R:G:B little endian - */ - WL_SHM_FORMAT_RGB888 = 0x34324752, - /** - * 24-bit BGR format, [23:0] B:G:R little endian - */ - WL_SHM_FORMAT_BGR888 = 0x34324742, - /** - * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian - */ - WL_SHM_FORMAT_XBGR8888 = 0x34324258, - /** - * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian - */ - WL_SHM_FORMAT_RGBX8888 = 0x34325852, - /** - * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian - */ - WL_SHM_FORMAT_BGRX8888 = 0x34325842, - /** - * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian - */ - WL_SHM_FORMAT_ABGR8888 = 0x34324241, - /** - * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian - */ - WL_SHM_FORMAT_RGBA8888 = 0x34324152, - /** - * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian - */ - WL_SHM_FORMAT_BGRA8888 = 0x34324142, - /** - * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian - */ - WL_SHM_FORMAT_XRGB2101010 = 0x30335258, - /** - * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian - */ - WL_SHM_FORMAT_XBGR2101010 = 0x30334258, - /** - * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian - */ - WL_SHM_FORMAT_RGBX1010102 = 0x30335852, - /** - * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian - */ - WL_SHM_FORMAT_BGRX1010102 = 0x30335842, - /** - * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian - */ - WL_SHM_FORMAT_ARGB2101010 = 0x30335241, - /** - * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian - */ - WL_SHM_FORMAT_ABGR2101010 = 0x30334241, - /** - * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian - */ - WL_SHM_FORMAT_RGBA1010102 = 0x30334152, - /** - * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian - */ - WL_SHM_FORMAT_BGRA1010102 = 0x30334142, - /** - * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_YUYV = 0x56595559, - /** - * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_YVYU = 0x55595659, - /** - * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_UYVY = 0x59565955, - /** - * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_VYUY = 0x59555956, - /** - * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian - */ - WL_SHM_FORMAT_AYUV = 0x56555941, - /** - * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane - */ - WL_SHM_FORMAT_NV12 = 0x3231564e, - /** - * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane - */ - WL_SHM_FORMAT_NV21 = 0x3132564e, - /** - * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane - */ - WL_SHM_FORMAT_NV16 = 0x3631564e, - /** - * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane - */ - WL_SHM_FORMAT_NV61 = 0x3136564e, - /** - * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV410 = 0x39565559, - /** - * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU410 = 0x39555659, - /** - * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV411 = 0x31315559, - /** - * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU411 = 0x31315659, - /** - * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV420 = 0x32315559, - /** - * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU420 = 0x32315659, - /** - * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV422 = 0x36315559, - /** - * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU422 = 0x36315659, - /** - * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV444 = 0x34325559, - /** - * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU444 = 0x34325659, -}; -#endif /* WL_SHM_FORMAT_ENUM */ - -/** - * @ingroup iface_wl_shm - * @struct wl_shm_listener - */ -struct wl_shm_listener { - /** - * pixel format description - * - * Informs the client about a valid pixel format that can be used - * for buffers. Known formats include argb8888 and xrgb8888. - * @param format buffer pixel format - */ - void (*format)(void *data, - struct wl_shm *wl_shm, - uint32_t format); -}; - -/** - * @ingroup iface_wl_shm - */ -static inline int -wl_shm_add_listener(struct wl_shm *wl_shm, - const struct wl_shm_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_shm, - (void (**)(void)) listener, data); -} - -#define WL_SHM_CREATE_POOL 0 - -/** - * @ingroup iface_wl_shm - */ -#define WL_SHM_FORMAT_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shm - */ -#define WL_SHM_CREATE_POOL_SINCE_VERSION 1 - -/** @ingroup iface_wl_shm */ -static inline void -wl_shm_set_user_data(struct wl_shm *wl_shm, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_shm, user_data); -} - -/** @ingroup iface_wl_shm */ -static inline void * -wl_shm_get_user_data(struct wl_shm *wl_shm) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_shm); -} - -static inline uint32_t -wl_shm_get_version(struct wl_shm *wl_shm) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_shm); -} - -/** @ingroup iface_wl_shm */ -static inline void -wl_shm_destroy(struct wl_shm *wl_shm) -{ - wl_proxy_destroy((struct wl_proxy *) wl_shm); -} - -/** - * @ingroup iface_wl_shm - * - * Create a new wl_shm_pool object. - * - * The pool can be used to create shared memory based buffer - * objects. The server will mmap size bytes of the passed file - * descriptor, to use as backing memory for the pool. - */ -static inline struct wl_shm_pool * -wl_shm_create_pool(struct wl_shm *wl_shm, int32_t fd, int32_t size) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shm, - WL_SHM_CREATE_POOL, &wl_shm_pool_interface, wl_proxy_get_version((struct wl_proxy *) wl_shm), 0, NULL, fd, size); - - return (struct wl_shm_pool *) id; -} - -/** - * @ingroup iface_wl_buffer - * @struct wl_buffer_listener - */ -struct wl_buffer_listener { - /** - * compositor releases buffer - * - * Sent when this wl_buffer is no longer used by the compositor. - * The client is now free to reuse or destroy this buffer and its - * backing storage. - * - * If a client receives a release event before the frame callback - * requested in the same wl_surface.commit that attaches this - * wl_buffer to a surface, then the client is immediately free to - * reuse the buffer and its backing storage, and does not need a - * second buffer for the next surface content update. Typically - * this is possible, when the compositor maintains a copy of the - * wl_surface contents, e.g. as a GL texture. This is an important - * optimization for GL(ES) compositors with wl_shm clients. - */ - void (*release)(void *data, - struct wl_buffer *wl_buffer); -}; - -/** - * @ingroup iface_wl_buffer - */ -static inline int -wl_buffer_add_listener(struct wl_buffer *wl_buffer, - const struct wl_buffer_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_buffer, - (void (**)(void)) listener, data); -} - -#define WL_BUFFER_DESTROY 0 - -/** - * @ingroup iface_wl_buffer - */ -#define WL_BUFFER_RELEASE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_buffer - */ -#define WL_BUFFER_DESTROY_SINCE_VERSION 1 - -/** @ingroup iface_wl_buffer */ -static inline void -wl_buffer_set_user_data(struct wl_buffer *wl_buffer, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_buffer, user_data); -} - -/** @ingroup iface_wl_buffer */ -static inline void * -wl_buffer_get_user_data(struct wl_buffer *wl_buffer) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_buffer); -} - -static inline uint32_t -wl_buffer_get_version(struct wl_buffer *wl_buffer) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_buffer); -} - -/** - * @ingroup iface_wl_buffer - * - * Destroy a buffer. If and how you need to release the backing - * storage is defined by the buffer factory interface. - * - * For possible side-effects to a surface, see wl_surface.attach. - */ -static inline void -wl_buffer_destroy(struct wl_buffer *wl_buffer) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_buffer, - WL_BUFFER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_buffer), WL_MARSHAL_FLAG_DESTROY); -} - -#ifndef WL_DATA_OFFER_ERROR_ENUM -#define WL_DATA_OFFER_ERROR_ENUM -enum wl_data_offer_error { - /** - * finish request was called untimely - */ - WL_DATA_OFFER_ERROR_INVALID_FINISH = 0, - /** - * action mask contains invalid values - */ - WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1, - /** - * action argument has an invalid value - */ - WL_DATA_OFFER_ERROR_INVALID_ACTION = 2, - /** - * offer doesn't accept this request - */ - WL_DATA_OFFER_ERROR_INVALID_OFFER = 3, -}; -#endif /* WL_DATA_OFFER_ERROR_ENUM */ - -/** - * @ingroup iface_wl_data_offer - * @struct wl_data_offer_listener - */ -struct wl_data_offer_listener { - /** - * advertise offered mime type - * - * Sent immediately after creating the wl_data_offer object. One - * event per offered mime type. - * @param mime_type offered mime type - */ - void (*offer)(void *data, - struct wl_data_offer *wl_data_offer, - const char *mime_type); - /** - * notify the source-side available actions - * - * This event indicates the actions offered by the data source. - * It will be sent right after wl_data_device.enter, or anytime the - * source side changes its offered actions through - * wl_data_source.set_actions. - * @param source_actions actions offered by the data source - * @since 3 - */ - void (*source_actions)(void *data, - struct wl_data_offer *wl_data_offer, - uint32_t source_actions); - /** - * notify the selected action - * - * This event indicates the action selected by the compositor - * after matching the source/destination side actions. Only one - * action (or none) will be offered here. - * - * This event can be emitted multiple times during the - * drag-and-drop operation in response to destination side action - * changes through wl_data_offer.set_actions. - * - * This event will no longer be emitted after wl_data_device.drop - * happened on the drag-and-drop destination, the client must honor - * the last action received, or the last preferred one set through - * wl_data_offer.set_actions when handling an "ask" action. - * - * Compositors may also change the selected action on the fly, - * mainly in response to keyboard modifier changes during the - * drag-and-drop operation. - * - * The most recent action received is always the valid one. Prior - * to receiving wl_data_device.drop, the chosen action may change - * (e.g. due to keyboard modifiers being pressed). At the time of - * receiving wl_data_device.drop the drag-and-drop destination must - * honor the last action received. - * - * Action changes may still happen after wl_data_device.drop, - * especially on "ask" actions, where the drag-and-drop destination - * may choose another action afterwards. Action changes happening - * at this stage are always the result of inter-client negotiation, - * the compositor shall no longer be able to induce a different - * action. - * - * Upon "ask" actions, it is expected that the drag-and-drop - * destination may potentially choose a different action and/or - * mime type, based on wl_data_offer.source_actions and finally - * chosen by the user (e.g. popping up a menu with the available - * options). The final wl_data_offer.set_actions and - * wl_data_offer.accept requests must happen before the call to - * wl_data_offer.finish. - * @param dnd_action action selected by the compositor - * @since 3 - */ - void (*action)(void *data, - struct wl_data_offer *wl_data_offer, - uint32_t dnd_action); -}; - -/** - * @ingroup iface_wl_data_offer - */ -static inline int -wl_data_offer_add_listener(struct wl_data_offer *wl_data_offer, - const struct wl_data_offer_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_data_offer, - (void (**)(void)) listener, data); -} - -#define WL_DATA_OFFER_ACCEPT 0 -#define WL_DATA_OFFER_RECEIVE 1 -#define WL_DATA_OFFER_DESTROY 2 -#define WL_DATA_OFFER_FINISH 3 -#define WL_DATA_OFFER_SET_ACTIONS 4 - -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_OFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_ACTION_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_ACCEPT_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_RECEIVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_FINISH_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION 3 - -/** @ingroup iface_wl_data_offer */ -static inline void -wl_data_offer_set_user_data(struct wl_data_offer *wl_data_offer, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_data_offer, user_data); -} - -/** @ingroup iface_wl_data_offer */ -static inline void * -wl_data_offer_get_user_data(struct wl_data_offer *wl_data_offer) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_data_offer); -} - -static inline uint32_t -wl_data_offer_get_version(struct wl_data_offer *wl_data_offer) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_data_offer); -} - -/** - * @ingroup iface_wl_data_offer - * - * Indicate that the client can accept the given mime type, or - * NULL for not accepted. - * - * For objects of version 2 or older, this request is used by the - * client to give feedback whether the client can receive the given - * mime type, or NULL if none is accepted; the feedback does not - * determine whether the drag-and-drop operation succeeds or not. - * - * For objects of version 3 or newer, this request determines the - * final result of the drag-and-drop operation. If the end result - * is that no mime types were accepted, the drag-and-drop operation - * will be cancelled and the corresponding drag source will receive - * wl_data_source.cancelled. Clients may still use this event in - * conjunction with wl_data_source.action for feedback. - */ -static inline void -wl_data_offer_accept(struct wl_data_offer *wl_data_offer, uint32_t serial, const char *mime_type) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer, - WL_DATA_OFFER_ACCEPT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, serial, mime_type); -} - -/** - * @ingroup iface_wl_data_offer - * - * To transfer the offered data, the client issues this request - * and indicates the mime type it wants to receive. The transfer - * happens through the passed file descriptor (typically created - * with the pipe system call). The source client writes the data - * in the mime type representation requested and then closes the - * file descriptor. - * - * The receiving client reads from the read end of the pipe until - * EOF and then closes its end, at which point the transfer is - * complete. - * - * This request may happen multiple times for different mime types, - * both before and after wl_data_device.drop. Drag-and-drop destination - * clients may preemptively fetch data or examine it more closely to - * determine acceptance. - */ -static inline void -wl_data_offer_receive(struct wl_data_offer *wl_data_offer, const char *mime_type, int32_t fd) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer, - WL_DATA_OFFER_RECEIVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, mime_type, fd); -} - -/** - * @ingroup iface_wl_data_offer - * - * Destroy the data offer. - */ -static inline void -wl_data_offer_destroy(struct wl_data_offer *wl_data_offer) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer, - WL_DATA_OFFER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_data_offer - * - * Notifies the compositor that the drag destination successfully - * finished the drag-and-drop operation. - * - * Upon receiving this request, the compositor will emit - * wl_data_source.dnd_finished on the drag source client. - * - * It is a client error to perform other requests than - * wl_data_offer.destroy after this one. It is also an error to perform - * this request after a NULL mime type has been set in - * wl_data_offer.accept or no action was received through - * wl_data_offer.action. - */ -static inline void -wl_data_offer_finish(struct wl_data_offer *wl_data_offer) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer, - WL_DATA_OFFER_FINISH, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0); -} - -/** - * @ingroup iface_wl_data_offer - * - * Sets the actions that the destination side client supports for - * this operation. This request may trigger the emission of - * wl_data_source.action and wl_data_offer.action events if the compositor - * needs to change the selected action. - * - * This request can be called multiple times throughout the - * drag-and-drop operation, typically in response to wl_data_device.enter - * or wl_data_device.motion events. - * - * This request determines the final result of the drag-and-drop - * operation. If the end result is that no action is accepted, - * the drag source will receive wl_drag_source.cancelled. - * - * The dnd_actions argument must contain only values expressed in the - * wl_data_device_manager.dnd_actions enum, and the preferred_action - * argument must only contain one of those values set, otherwise it - * will result in a protocol error. - * - * While managing an "ask" action, the destination drag-and-drop client - * may perform further wl_data_offer.receive requests, and is expected - * to perform one last wl_data_offer.set_actions request with a preferred - * action other than "ask" (and optionally wl_data_offer.accept) before - * requesting wl_data_offer.finish, in order to convey the action selected - * by the user. If the preferred action is not in the - * wl_data_offer.source_actions mask, an error will be raised. - * - * If the "ask" action is dismissed (e.g. user cancellation), the client - * is expected to perform wl_data_offer.destroy right away. - * - * This request can only be made on drag-and-drop offers, a protocol error - * will be raised otherwise. - */ -static inline void -wl_data_offer_set_actions(struct wl_data_offer *wl_data_offer, uint32_t dnd_actions, uint32_t preferred_action) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer, - WL_DATA_OFFER_SET_ACTIONS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, dnd_actions, preferred_action); -} - -#ifndef WL_DATA_SOURCE_ERROR_ENUM -#define WL_DATA_SOURCE_ERROR_ENUM -enum wl_data_source_error { - /** - * action mask contains invalid values - */ - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0, - /** - * source doesn't accept this request - */ - WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1, -}; -#endif /* WL_DATA_SOURCE_ERROR_ENUM */ - -/** - * @ingroup iface_wl_data_source - * @struct wl_data_source_listener - */ -struct wl_data_source_listener { - /** - * a target accepts an offered mime type - * - * Sent when a target accepts pointer_focus or motion events. If - * a target does not accept any of the offered types, type is NULL. - * - * Used for feedback during drag-and-drop. - * @param mime_type mime type accepted by the target - */ - void (*target)(void *data, - struct wl_data_source *wl_data_source, - const char *mime_type); - /** - * send the data - * - * Request for data from the client. Send the data as the - * specified mime type over the passed file descriptor, then close - * it. - * @param mime_type mime type for the data - * @param fd file descriptor for the data - */ - void (*send)(void *data, - struct wl_data_source *wl_data_source, - const char *mime_type, - int32_t fd); - /** - * selection was cancelled - * - * This data source is no longer valid. There are several reasons - * why this could happen: - * - * - The data source has been replaced by another data source. - - * The drag-and-drop operation was performed, but the drop - * destination did not accept any of the mime types offered through - * wl_data_source.target. - The drag-and-drop operation was - * performed, but the drop destination did not select any of the - * actions present in the mask offered through - * wl_data_source.action. - The drag-and-drop operation was - * performed but didn't happen over a surface. - The compositor - * cancelled the drag-and-drop operation (e.g. compositor dependent - * timeouts to avoid stale drag-and-drop transfers). - * - * The client should clean up and destroy this data source. - * - * For objects of version 2 or older, wl_data_source.cancelled will - * only be emitted if the data source was replaced by another data - * source. - */ - void (*cancelled)(void *data, - struct wl_data_source *wl_data_source); - /** - * the drag-and-drop operation physically finished - * - * The user performed the drop action. This event does not - * indicate acceptance, wl_data_source.cancelled may still be - * emitted afterwards if the drop destination does not accept any - * mime type. - * - * However, this event might however not be received if the - * compositor cancelled the drag-and-drop operation before this - * event could happen. - * - * Note that the data_source may still be used in the future and - * should not be destroyed here. - * @since 3 - */ - void (*dnd_drop_performed)(void *data, - struct wl_data_source *wl_data_source); - /** - * the drag-and-drop operation concluded - * - * The drop destination finished interoperating with this data - * source, so the client is now free to destroy this data source - * and free all associated data. - * - * If the action used to perform the operation was "move", the - * source can now delete the transferred data. - * @since 3 - */ - void (*dnd_finished)(void *data, - struct wl_data_source *wl_data_source); - /** - * notify the selected action - * - * This event indicates the action selected by the compositor - * after matching the source/destination side actions. Only one - * action (or none) will be offered here. - * - * This event can be emitted multiple times during the - * drag-and-drop operation, mainly in response to destination side - * changes through wl_data_offer.set_actions, and as the data - * device enters/leaves surfaces. - * - * It is only possible to receive this event after - * wl_data_source.dnd_drop_performed if the drag-and-drop operation - * ended in an "ask" action, in which case the final - * wl_data_source.action event will happen immediately before - * wl_data_source.dnd_finished. - * - * Compositors may also change the selected action on the fly, - * mainly in response to keyboard modifier changes during the - * drag-and-drop operation. - * - * The most recent action received is always the valid one. The - * chosen action may change alongside negotiation (e.g. an "ask" - * action can turn into a "move" operation), so the effects of the - * final action must always be applied in - * wl_data_offer.dnd_finished. - * - * Clients can trigger cursor surface changes from this point, so - * they reflect the current action. - * @param dnd_action action selected by the compositor - * @since 3 - */ - void (*action)(void *data, - struct wl_data_source *wl_data_source, - uint32_t dnd_action); -}; - -/** - * @ingroup iface_wl_data_source - */ -static inline int -wl_data_source_add_listener(struct wl_data_source *wl_data_source, - const struct wl_data_source_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_data_source, - (void (**)(void)) listener, data); -} - -#define WL_DATA_SOURCE_OFFER 0 -#define WL_DATA_SOURCE_DESTROY 1 -#define WL_DATA_SOURCE_SET_ACTIONS 2 - -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_TARGET_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_SEND_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_CANCELLED_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_ACTION_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_OFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION 3 - -/** @ingroup iface_wl_data_source */ -static inline void -wl_data_source_set_user_data(struct wl_data_source *wl_data_source, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_data_source, user_data); -} - -/** @ingroup iface_wl_data_source */ -static inline void * -wl_data_source_get_user_data(struct wl_data_source *wl_data_source) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_data_source); -} - -static inline uint32_t -wl_data_source_get_version(struct wl_data_source *wl_data_source) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_data_source); -} - -/** - * @ingroup iface_wl_data_source - * - * This request adds a mime type to the set of mime types - * advertised to targets. Can be called several times to offer - * multiple types. - */ -static inline void -wl_data_source_offer(struct wl_data_source *wl_data_source, const char *mime_type) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source, - WL_DATA_SOURCE_OFFER, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), 0, mime_type); -} - -/** - * @ingroup iface_wl_data_source - * - * Destroy the data source. - */ -static inline void -wl_data_source_destroy(struct wl_data_source *wl_data_source) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source, - WL_DATA_SOURCE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_data_source - * - * Sets the actions that the source side client supports for this - * operation. This request may trigger wl_data_source.action and - * wl_data_offer.action events if the compositor needs to change the - * selected action. - * - * The dnd_actions argument must contain only values expressed in the - * wl_data_device_manager.dnd_actions enum, otherwise it will result - * in a protocol error. - * - * This request must be made once only, and can only be made on sources - * used in drag-and-drop, so it must be performed before - * wl_data_device.start_drag. Attempting to use the source other than - * for drag-and-drop will raise a protocol error. - */ -static inline void -wl_data_source_set_actions(struct wl_data_source *wl_data_source, uint32_t dnd_actions) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source, - WL_DATA_SOURCE_SET_ACTIONS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), 0, dnd_actions); -} - -#ifndef WL_DATA_DEVICE_ERROR_ENUM -#define WL_DATA_DEVICE_ERROR_ENUM -enum wl_data_device_error { - /** - * given wl_surface has another role - */ - WL_DATA_DEVICE_ERROR_ROLE = 0, -}; -#endif /* WL_DATA_DEVICE_ERROR_ENUM */ - -/** - * @ingroup iface_wl_data_device - * @struct wl_data_device_listener - */ -struct wl_data_device_listener { - /** - * introduce a new wl_data_offer - * - * The data_offer event introduces a new wl_data_offer object, - * which will subsequently be used in either the data_device.enter - * event (for drag-and-drop) or the data_device.selection event - * (for selections). Immediately following the - * data_device.data_offer event, the new data_offer object will - * send out data_offer.offer events to describe the mime types it - * offers. - * @param id the new data_offer object - */ - void (*data_offer)(void *data, - struct wl_data_device *wl_data_device, - struct wl_data_offer *id); - /** - * initiate drag-and-drop session - * - * This event is sent when an active drag-and-drop pointer enters - * a surface owned by the client. The position of the pointer at - * enter time is provided by the x and y arguments, in - * surface-local coordinates. - * @param serial serial number of the enter event - * @param surface client surface entered - * @param x surface-local x coordinate - * @param y surface-local y coordinate - * @param id source data_offer object - */ - void (*enter)(void *data, - struct wl_data_device *wl_data_device, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t x, - wl_fixed_t y, - struct wl_data_offer *id); - /** - * end drag-and-drop session - * - * This event is sent when the drag-and-drop pointer leaves the - * surface and the session ends. The client must destroy the - * wl_data_offer introduced at enter time at this point. - */ - void (*leave)(void *data, - struct wl_data_device *wl_data_device); - /** - * drag-and-drop session motion - * - * This event is sent when the drag-and-drop pointer moves within - * the currently focused surface. The new position of the pointer - * is provided by the x and y arguments, in surface-local - * coordinates. - * @param time timestamp with millisecond granularity - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ - void (*motion)(void *data, - struct wl_data_device *wl_data_device, - uint32_t time, - wl_fixed_t x, - wl_fixed_t y); - /** - * end drag-and-drop session successfully - * - * The event is sent when a drag-and-drop operation is ended - * because the implicit grab is removed. - * - * The drag-and-drop destination is expected to honor the last - * action received through wl_data_offer.action, if the resulting - * action is "copy" or "move", the destination can still perform - * wl_data_offer.receive requests, and is expected to end all - * transfers with a wl_data_offer.finish request. - * - * If the resulting action is "ask", the action will not be - * considered final. The drag-and-drop destination is expected to - * perform one last wl_data_offer.set_actions request, or - * wl_data_offer.destroy in order to cancel the operation. - */ - void (*drop)(void *data, - struct wl_data_device *wl_data_device); - /** - * advertise new selection - * - * The selection event is sent out to notify the client of a new - * wl_data_offer for the selection for this device. The - * data_device.data_offer and the data_offer.offer events are sent - * out immediately before this event to introduce the data offer - * object. The selection event is sent to a client immediately - * before receiving keyboard focus and when a new selection is set - * while the client has keyboard focus. The data_offer is valid - * until a new data_offer or NULL is received or until the client - * loses keyboard focus. The client must destroy the previous - * selection data_offer, if any, upon receiving this event. - * @param id selection data_offer object - */ - void (*selection)(void *data, - struct wl_data_device *wl_data_device, - struct wl_data_offer *id); -}; - -/** - * @ingroup iface_wl_data_device - */ -static inline int -wl_data_device_add_listener(struct wl_data_device *wl_data_device, - const struct wl_data_device_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_data_device, - (void (**)(void)) listener, data); -} - -#define WL_DATA_DEVICE_START_DRAG 0 -#define WL_DATA_DEVICE_SET_SELECTION 1 -#define WL_DATA_DEVICE_RELEASE 2 - -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_DATA_OFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_LEAVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_MOTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_DROP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_SELECTION_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_START_DRAG_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_SET_SELECTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_RELEASE_SINCE_VERSION 2 - -/** @ingroup iface_wl_data_device */ -static inline void -wl_data_device_set_user_data(struct wl_data_device *wl_data_device, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_data_device, user_data); -} - -/** @ingroup iface_wl_data_device */ -static inline void * -wl_data_device_get_user_data(struct wl_data_device *wl_data_device) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_data_device); -} - -static inline uint32_t -wl_data_device_get_version(struct wl_data_device *wl_data_device) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_data_device); -} - -/** @ingroup iface_wl_data_device */ -static inline void -wl_data_device_destroy(struct wl_data_device *wl_data_device) -{ - wl_proxy_destroy((struct wl_proxy *) wl_data_device); -} - -/** - * @ingroup iface_wl_data_device - * - * This request asks the compositor to start a drag-and-drop - * operation on behalf of the client. - * - * The source argument is the data source that provides the data - * for the eventual data transfer. If source is NULL, enter, leave - * and motion events are sent only to the client that initiated the - * drag and the client is expected to handle the data passing - * internally. - * - * The origin surface is the surface where the drag originates and - * the client must have an active implicit grab that matches the - * serial. - * - * The icon surface is an optional (can be NULL) surface that - * provides an icon to be moved around with the cursor. Initially, - * the top-left corner of the icon surface is placed at the cursor - * hotspot, but subsequent wl_surface.attach request can move the - * relative position. Attach requests must be confirmed with - * wl_surface.commit as usual. The icon surface is given the role of - * a drag-and-drop icon. If the icon surface already has another role, - * it raises a protocol error. - * - * The current and pending input regions of the icon wl_surface are - * cleared, and wl_surface.set_input_region is ignored until the - * wl_surface is no longer used as the icon surface. When the use - * as an icon ends, the current and pending input regions become - * undefined, and the wl_surface is unmapped. - */ -static inline void -wl_data_device_start_drag(struct wl_data_device *wl_data_device, struct wl_data_source *source, struct wl_surface *origin, struct wl_surface *icon, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device, - WL_DATA_DEVICE_START_DRAG, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), 0, source, origin, icon, serial); -} - -/** - * @ingroup iface_wl_data_device - * - * This request asks the compositor to set the selection - * to the data from the source on behalf of the client. - * - * To unset the selection, set the source to NULL. - */ -static inline void -wl_data_device_set_selection(struct wl_data_device *wl_data_device, struct wl_data_source *source, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device, - WL_DATA_DEVICE_SET_SELECTION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), 0, source, serial); -} - -/** - * @ingroup iface_wl_data_device - * - * This request destroys the data device. - */ -static inline void -wl_data_device_release(struct wl_data_device *wl_data_device) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device, - WL_DATA_DEVICE_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), WL_MARSHAL_FLAG_DESTROY); -} - -#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM -#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM -/** - * @ingroup iface_wl_data_device_manager - * drag and drop actions - * - * This is a bitmask of the available/preferred actions in a - * drag-and-drop operation. - * - * In the compositor, the selected action is a result of matching the - * actions offered by the source and destination sides. "action" events - * with a "none" action will be sent to both source and destination if - * there is no match. All further checks will effectively happen on - * (source actions ∩ destination actions). - * - * In addition, compositors may also pick different actions in - * reaction to key modifiers being pressed. One common design that - * is used in major toolkits (and the behavior recommended for - * compositors) is: - * - * - If no modifiers are pressed, the first match (in bit order) - * will be used. - * - Pressing Shift selects "move", if enabled in the mask. - * - Pressing Control selects "copy", if enabled in the mask. - * - * Behavior beyond that is considered implementation-dependent. - * Compositors may for example bind other modifiers (like Alt/Meta) - * or drags initiated with other buttons than BTN_LEFT to specific - * actions (e.g. "ask"). - */ -enum wl_data_device_manager_dnd_action { - /** - * no action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0, - /** - * copy action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1, - /** - * move action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2, - /** - * ask action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4, -}; -#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */ - -#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE 0 -#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE 1 - - -/** - * @ingroup iface_wl_data_device_manager - */ -#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device_manager - */ -#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1 - -/** @ingroup iface_wl_data_device_manager */ -static inline void -wl_data_device_manager_set_user_data(struct wl_data_device_manager *wl_data_device_manager, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_data_device_manager, user_data); -} - -/** @ingroup iface_wl_data_device_manager */ -static inline void * -wl_data_device_manager_get_user_data(struct wl_data_device_manager *wl_data_device_manager) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_data_device_manager); -} - -static inline uint32_t -wl_data_device_manager_get_version(struct wl_data_device_manager *wl_data_device_manager) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager); -} - -/** @ingroup iface_wl_data_device_manager */ -static inline void -wl_data_device_manager_destroy(struct wl_data_device_manager *wl_data_device_manager) -{ - wl_proxy_destroy((struct wl_proxy *) wl_data_device_manager); -} - -/** - * @ingroup iface_wl_data_device_manager - * - * Create a new data source. - */ -static inline struct wl_data_source * -wl_data_device_manager_create_data_source(struct wl_data_device_manager *wl_data_device_manager) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager, - WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE, &wl_data_source_interface, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), 0, NULL); - - return (struct wl_data_source *) id; -} - -/** - * @ingroup iface_wl_data_device_manager - * - * Create a new data device for a given seat. - */ -static inline struct wl_data_device * -wl_data_device_manager_get_data_device(struct wl_data_device_manager *wl_data_device_manager, struct wl_seat *seat) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager, - WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE, &wl_data_device_interface, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), 0, NULL, seat); - - return (struct wl_data_device *) id; -} - -#ifndef WL_SHELL_ERROR_ENUM -#define WL_SHELL_ERROR_ENUM -enum wl_shell_error { - /** - * given wl_surface has another role - */ - WL_SHELL_ERROR_ROLE = 0, -}; -#endif /* WL_SHELL_ERROR_ENUM */ - -#define WL_SHELL_GET_SHELL_SURFACE 0 - - -/** - * @ingroup iface_wl_shell - */ -#define WL_SHELL_GET_SHELL_SURFACE_SINCE_VERSION 1 - -/** @ingroup iface_wl_shell */ -static inline void -wl_shell_set_user_data(struct wl_shell *wl_shell, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_shell, user_data); -} - -/** @ingroup iface_wl_shell */ -static inline void * -wl_shell_get_user_data(struct wl_shell *wl_shell) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_shell); -} - -static inline uint32_t -wl_shell_get_version(struct wl_shell *wl_shell) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_shell); -} - -/** @ingroup iface_wl_shell */ -static inline void -wl_shell_destroy(struct wl_shell *wl_shell) -{ - wl_proxy_destroy((struct wl_proxy *) wl_shell); -} - -/** - * @ingroup iface_wl_shell - * - * Create a shell surface for an existing surface. This gives - * the wl_surface the role of a shell surface. If the wl_surface - * already has another role, it raises a protocol error. - * - * Only one shell surface can be associated with a given surface. - */ -static inline struct wl_shell_surface * -wl_shell_get_shell_surface(struct wl_shell *wl_shell, struct wl_surface *surface) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shell, - WL_SHELL_GET_SHELL_SURFACE, &wl_shell_surface_interface, wl_proxy_get_version((struct wl_proxy *) wl_shell), 0, NULL, surface); - - return (struct wl_shell_surface *) id; -} - -#ifndef WL_SHELL_SURFACE_RESIZE_ENUM -#define WL_SHELL_SURFACE_RESIZE_ENUM -/** - * @ingroup iface_wl_shell_surface - * edge values for resizing - * - * These values are used to indicate which edge of a surface - * is being dragged in a resize operation. The server may - * use this information to adapt its behavior, e.g. choose - * an appropriate cursor image. - */ -enum wl_shell_surface_resize { - /** - * no edge - */ - WL_SHELL_SURFACE_RESIZE_NONE = 0, - /** - * top edge - */ - WL_SHELL_SURFACE_RESIZE_TOP = 1, - /** - * bottom edge - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM = 2, - /** - * left edge - */ - WL_SHELL_SURFACE_RESIZE_LEFT = 4, - /** - * top and left edges - */ - WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5, - /** - * bottom and left edges - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6, - /** - * right edge - */ - WL_SHELL_SURFACE_RESIZE_RIGHT = 8, - /** - * top and right edges - */ - WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9, - /** - * bottom and right edges - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10, -}; -#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */ - -#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM -#define WL_SHELL_SURFACE_TRANSIENT_ENUM -/** - * @ingroup iface_wl_shell_surface - * details of transient behaviour - * - * These flags specify details of the expected behaviour - * of transient surfaces. Used in the set_transient request. - */ -enum wl_shell_surface_transient { - /** - * do not set keyboard focus - */ - WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1, -}; -#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */ - -#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM -#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM -/** - * @ingroup iface_wl_shell_surface - * different method to set the surface fullscreen - * - * Hints to indicate to the compositor how to deal with a conflict - * between the dimensions of the surface and the dimensions of the - * output. The compositor is free to ignore this parameter. - */ -enum wl_shell_surface_fullscreen_method { - /** - * no preference, apply default policy - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0, - /** - * scale, preserve the surface's aspect ratio and center on output - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1, - /** - * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2, - /** - * no upscaling, center on output and add black borders to compensate size mismatch - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3, -}; -#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */ - -/** - * @ingroup iface_wl_shell_surface - * @struct wl_shell_surface_listener - */ -struct wl_shell_surface_listener { - /** - * ping client - * - * Ping a client to check if it is receiving events and sending - * requests. A client is expected to reply with a pong request. - * @param serial serial number of the ping - */ - void (*ping)(void *data, - struct wl_shell_surface *wl_shell_surface, - uint32_t serial); - /** - * suggest resize - * - * The configure event asks the client to resize its surface. - * - * The size is a hint, in the sense that the client is free to - * ignore it if it doesn't resize, pick a smaller size (to satisfy - * aspect ratio or resize in steps of NxM pixels). - * - * The edges parameter provides a hint about how the surface was - * resized. The client may use this information to decide how to - * adjust its content to the new size (e.g. a scrolling area might - * adjust its content position to leave the viewable content - * unmoved). - * - * The client is free to dismiss all but the last configure event - * it received. - * - * The width and height arguments specify the size of the window in - * surface-local coordinates. - * @param edges how the surface was resized - * @param width new width of the surface - * @param height new height of the surface - */ - void (*configure)(void *data, - struct wl_shell_surface *wl_shell_surface, - uint32_t edges, - int32_t width, - int32_t height); - /** - * popup interaction is done - * - * The popup_done event is sent out when a popup grab is broken, - * that is, when the user clicks a surface that doesn't belong to - * the client owning the popup surface. - */ - void (*popup_done)(void *data, - struct wl_shell_surface *wl_shell_surface); -}; - -/** - * @ingroup iface_wl_shell_surface - */ -static inline int -wl_shell_surface_add_listener(struct wl_shell_surface *wl_shell_surface, - const struct wl_shell_surface_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_shell_surface, - (void (**)(void)) listener, data); -} - -#define WL_SHELL_SURFACE_PONG 0 -#define WL_SHELL_SURFACE_MOVE 1 -#define WL_SHELL_SURFACE_RESIZE 2 -#define WL_SHELL_SURFACE_SET_TOPLEVEL 3 -#define WL_SHELL_SURFACE_SET_TRANSIENT 4 -#define WL_SHELL_SURFACE_SET_FULLSCREEN 5 -#define WL_SHELL_SURFACE_SET_POPUP 6 -#define WL_SHELL_SURFACE_SET_MAXIMIZED 7 -#define WL_SHELL_SURFACE_SET_TITLE 8 -#define WL_SHELL_SURFACE_SET_CLASS 9 - -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_PING_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_CONFIGURE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_POPUP_DONE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_PONG_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_MOVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_RESIZE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_TOPLEVEL_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_TRANSIENT_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_FULLSCREEN_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_POPUP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_MAXIMIZED_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_TITLE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_CLASS_SINCE_VERSION 1 - -/** @ingroup iface_wl_shell_surface */ -static inline void -wl_shell_surface_set_user_data(struct wl_shell_surface *wl_shell_surface, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_shell_surface, user_data); -} - -/** @ingroup iface_wl_shell_surface */ -static inline void * -wl_shell_surface_get_user_data(struct wl_shell_surface *wl_shell_surface) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_shell_surface); -} - -static inline uint32_t -wl_shell_surface_get_version(struct wl_shell_surface *wl_shell_surface) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_shell_surface); -} - -/** @ingroup iface_wl_shell_surface */ -static inline void -wl_shell_surface_destroy(struct wl_shell_surface *wl_shell_surface) -{ - wl_proxy_destroy((struct wl_proxy *) wl_shell_surface); -} - -/** - * @ingroup iface_wl_shell_surface - * - * A client must respond to a ping event with a pong request or - * the client may be deemed unresponsive. - */ -static inline void -wl_shell_surface_pong(struct wl_shell_surface *wl_shell_surface, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, serial); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Start a pointer-driven move of the surface. - * - * This request must be used in response to a button press event. - * The server may ignore move requests depending on the state of - * the surface (e.g. fullscreen or maximized). - */ -static inline void -wl_shell_surface_move(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Start a pointer-driven resizing of the surface. - * - * This request must be used in response to a button press event. - * The server may ignore resize requests depending on the state of - * the surface (e.g. fullscreen or maximized). - */ -static inline void -wl_shell_surface_resize(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial, uint32_t edges) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial, edges); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Map the surface as a toplevel surface. - * - * A toplevel surface is not fullscreen, maximized or transient. - */ -static inline void -wl_shell_surface_set_toplevel(struct wl_shell_surface *wl_shell_surface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_TOPLEVEL, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Map the surface relative to an existing surface. - * - * The x and y arguments specify the location of the upper left - * corner of the surface relative to the upper left corner of the - * parent surface, in surface-local coordinates. - * - * The flags argument controls details of the transient behaviour. - */ -static inline void -wl_shell_surface_set_transient(struct wl_shell_surface *wl_shell_surface, struct wl_surface *parent, int32_t x, int32_t y, uint32_t flags) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_TRANSIENT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, parent, x, y, flags); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Map the surface as a fullscreen surface. - * - * If an output parameter is given then the surface will be made - * fullscreen on that output. If the client does not specify the - * output then the compositor will apply its policy - usually - * choosing the output on which the surface has the biggest surface - * area. - * - * The client may specify a method to resolve a size conflict - * between the output size and the surface size - this is provided - * through the method parameter. - * - * The framerate parameter is used only when the method is set - * to "driver", to indicate the preferred framerate. A value of 0 - * indicates that the client does not care about framerate. The - * framerate is specified in mHz, that is framerate of 60000 is 60Hz. - * - * A method of "scale" or "driver" implies a scaling operation of - * the surface, either via a direct scaling operation or a change of - * the output mode. This will override any kind of output scaling, so - * that mapping a surface with a buffer size equal to the mode can - * fill the screen independent of buffer_scale. - * - * A method of "fill" means we don't scale up the buffer, however - * any output scale is applied. This means that you may run into - * an edge case where the application maps a buffer with the same - * size of the output mode but buffer_scale 1 (thus making a - * surface larger than the output). In this case it is allowed to - * downscale the results to fit the screen. - * - * The compositor must reply to this request with a configure event - * with the dimensions for the output on which the surface will - * be made fullscreen. - */ -static inline void -wl_shell_surface_set_fullscreen(struct wl_shell_surface *wl_shell_surface, uint32_t method, uint32_t framerate, struct wl_output *output) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, method, framerate, output); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Map the surface as a popup. - * - * A popup surface is a transient surface with an added pointer - * grab. - * - * An existing implicit grab will be changed to owner-events mode, - * and the popup grab will continue after the implicit grab ends - * (i.e. releasing the mouse button does not cause the popup to - * be unmapped). - * - * The popup grab continues until the window is destroyed or a - * mouse button is pressed in any other client's window. A click - * in any of the client's surfaces is reported as normal, however, - * clicks in other clients' surfaces will be discarded and trigger - * the callback. - * - * The x and y arguments specify the location of the upper left - * corner of the surface relative to the upper left corner of the - * parent surface, in surface-local coordinates. - */ -static inline void -wl_shell_surface_set_popup(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial, struct wl_surface *parent, int32_t x, int32_t y, uint32_t flags) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_POPUP, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial, parent, x, y, flags); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Map the surface as a maximized surface. - * - * If an output parameter is given then the surface will be - * maximized on that output. If the client does not specify the - * output then the compositor will apply its policy - usually - * choosing the output on which the surface has the biggest surface - * area. - * - * The compositor will reply with a configure event telling - * the expected new surface size. The operation is completed - * on the next buffer attach to this surface. - * - * A maximized surface typically fills the entire output it is - * bound to, except for desktop elements such as panels. This is - * the main difference between a maximized shell surface and a - * fullscreen shell surface. - * - * The details depend on the compositor implementation. - */ -static inline void -wl_shell_surface_set_maximized(struct wl_shell_surface *wl_shell_surface, struct wl_output *output) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, output); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Set a short title for the surface. - * - * This string may be used to identify the surface in a task bar, - * window list, or other user interface elements provided by the - * compositor. - * - * The string must be encoded in UTF-8. - */ -static inline void -wl_shell_surface_set_title(struct wl_shell_surface *wl_shell_surface, const char *title) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, title); -} - -/** - * @ingroup iface_wl_shell_surface - * - * Set a class for the surface. - * - * The surface class identifies the general class of applications - * to which the surface belongs. A common convention is to use the - * file name (or the full path if it is a non-standard location) of - * the application's .desktop file as the class. - */ -static inline void -wl_shell_surface_set_class(struct wl_shell_surface *wl_shell_surface, const char *class_) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface, - WL_SHELL_SURFACE_SET_CLASS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, class_); -} - -#ifndef WL_SURFACE_ERROR_ENUM -#define WL_SURFACE_ERROR_ENUM -/** - * @ingroup iface_wl_surface - * wl_surface error values - * - * These errors can be emitted in response to wl_surface requests. - */ -enum wl_surface_error { - /** - * buffer scale value is invalid - */ - WL_SURFACE_ERROR_INVALID_SCALE = 0, - /** - * buffer transform value is invalid - */ - WL_SURFACE_ERROR_INVALID_TRANSFORM = 1, -}; -#endif /* WL_SURFACE_ERROR_ENUM */ - -/** - * @ingroup iface_wl_surface - * @struct wl_surface_listener - */ -struct wl_surface_listener { - /** - * surface enters an output - * - * This is emitted whenever a surface's creation, movement, or - * resizing results in some part of it being within the scanout - * region of an output. - * - * Note that a surface may be overlapping with zero or more - * outputs. - * @param output output entered by the surface - */ - void (*enter)(void *data, - struct wl_surface *wl_surface, - struct wl_output *output); - /** - * surface leaves an output - * - * This is emitted whenever a surface's creation, movement, or - * resizing results in it no longer having any part of it within - * the scanout region of an output. - * @param output output left by the surface - */ - void (*leave)(void *data, - struct wl_surface *wl_surface, - struct wl_output *output); -}; - -/** - * @ingroup iface_wl_surface - */ -static inline int -wl_surface_add_listener(struct wl_surface *wl_surface, - const struct wl_surface_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_surface, - (void (**)(void)) listener, data); -} - -#define WL_SURFACE_DESTROY 0 -#define WL_SURFACE_ATTACH 1 -#define WL_SURFACE_DAMAGE 2 -#define WL_SURFACE_FRAME 3 -#define WL_SURFACE_SET_OPAQUE_REGION 4 -#define WL_SURFACE_SET_INPUT_REGION 5 -#define WL_SURFACE_COMMIT 6 -#define WL_SURFACE_SET_BUFFER_TRANSFORM 7 -#define WL_SURFACE_SET_BUFFER_SCALE 8 -#define WL_SURFACE_DAMAGE_BUFFER 9 - -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_LEAVE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_ATTACH_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_DAMAGE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_FRAME_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_OPAQUE_REGION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_INPUT_REGION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_COMMIT_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_BUFFER_TRANSFORM_SINCE_VERSION 2 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION 3 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION 4 - -/** @ingroup iface_wl_surface */ -static inline void -wl_surface_set_user_data(struct wl_surface *wl_surface, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_surface, user_data); -} - -/** @ingroup iface_wl_surface */ -static inline void * -wl_surface_get_user_data(struct wl_surface *wl_surface) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_surface); -} - -static inline uint32_t -wl_surface_get_version(struct wl_surface *wl_surface) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_surface); -} - -/** - * @ingroup iface_wl_surface - * - * Deletes the surface and invalidates its object ID. - */ -static inline void -wl_surface_destroy(struct wl_surface *wl_surface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_surface - * - * Set a buffer as the content of this surface. - * - * The new size of the surface is calculated based on the buffer - * size transformed by the inverse buffer_transform and the - * inverse buffer_scale. This means that the supplied buffer - * must be an integer multiple of the buffer_scale. - * - * The x and y arguments specify the location of the new pending - * buffer's upper left corner, relative to the current buffer's upper - * left corner, in surface-local coordinates. In other words, the - * x and y, combined with the new surface size define in which - * directions the surface's size changes. - * - * Surface contents are double-buffered state, see wl_surface.commit. - * - * The initial surface contents are void; there is no content. - * wl_surface.attach assigns the given wl_buffer as the pending - * wl_buffer. wl_surface.commit makes the pending wl_buffer the new - * surface contents, and the size of the surface becomes the size - * calculated from the wl_buffer, as described above. After commit, - * there is no pending buffer until the next attach. - * - * Committing a pending wl_buffer allows the compositor to read the - * pixels in the wl_buffer. The compositor may access the pixels at - * any time after the wl_surface.commit request. When the compositor - * will not access the pixels anymore, it will send the - * wl_buffer.release event. Only after receiving wl_buffer.release, - * the client may reuse the wl_buffer. A wl_buffer that has been - * attached and then replaced by another attach instead of committed - * will not receive a release event, and is not used by the - * compositor. - * - * Destroying the wl_buffer after wl_buffer.release does not change - * the surface contents. However, if the client destroys the - * wl_buffer before receiving the wl_buffer.release event, the surface - * contents become undefined immediately. - * - * If wl_surface.attach is sent with a NULL wl_buffer, the - * following wl_surface.commit will remove the surface content. - */ -static inline void -wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_ATTACH, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, buffer, x, y); -} - -/** - * @ingroup iface_wl_surface - * - * This request is used to describe the regions where the pending - * buffer is different from the current surface contents, and where - * the surface therefore needs to be repainted. The compositor - * ignores the parts of the damage that fall outside of the surface. - * - * Damage is double-buffered state, see wl_surface.commit. - * - * The damage rectangle is specified in surface-local coordinates, - * where x and y specify the upper left corner of the damage rectangle. - * - * The initial value for pending damage is empty: no damage. - * wl_surface.damage adds pending damage: the new pending damage - * is the union of old pending damage and the given rectangle. - * - * wl_surface.commit assigns pending damage as the current damage, - * and clears pending damage. The server will clear the current - * damage as it repaints the surface. - * - * Alternatively, damage can be posted with wl_surface.damage_buffer - * which uses buffer coordinates instead of surface coordinates, - * and is probably the preferred and intuitive way of doing this. - */ -static inline void -wl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_DAMAGE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y, width, height); -} - -/** - * @ingroup iface_wl_surface - * - * Request a notification when it is a good time to start drawing a new - * frame, by creating a frame callback. This is useful for throttling - * redrawing operations, and driving animations. - * - * When a client is animating on a wl_surface, it can use the 'frame' - * request to get notified when it is a good time to draw and commit the - * next frame of animation. If the client commits an update earlier than - * that, it is likely that some updates will not make it to the display, - * and the client is wasting resources by drawing too often. - * - * The frame request will take effect on the next wl_surface.commit. - * The notification will only be posted for one frame unless - * requested again. For a wl_surface, the notifications are posted in - * the order the frame requests were committed. - * - * The server must send the notifications so that a client - * will not send excessive updates, while still allowing - * the highest possible update rate for clients that wait for the reply - * before drawing again. The server should give some time for the client - * to draw and commit after sending the frame callback events to let it - * hit the next output refresh. - * - * A server should avoid signaling the frame callbacks if the - * surface is not visible in any way, e.g. the surface is off-screen, - * or completely obscured by other opaque surfaces. - * - * The object returned by this request will be destroyed by the - * compositor after the callback is fired and as such the client must not - * attempt to use it after that point. - * - * The callback_data passed in the callback is the current time, in - * milliseconds, with an undefined base. - */ -static inline struct wl_callback * -wl_surface_frame(struct wl_surface *wl_surface) -{ - struct wl_proxy *callback; - - callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_FRAME, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, NULL); - - return (struct wl_callback *) callback; -} - -/** - * @ingroup iface_wl_surface - * - * This request sets the region of the surface that contains - * opaque content. - * - * The opaque region is an optimization hint for the compositor - * that lets it optimize the redrawing of content behind opaque - * regions. Setting an opaque region is not required for correct - * behaviour, but marking transparent content as opaque will result - * in repaint artifacts. - * - * The opaque region is specified in surface-local coordinates. - * - * The compositor ignores the parts of the opaque region that fall - * outside of the surface. - * - * Opaque region is double-buffered state, see wl_surface.commit. - * - * wl_surface.set_opaque_region changes the pending opaque region. - * wl_surface.commit copies the pending region to the current region. - * Otherwise, the pending and current regions are never changed. - * - * The initial value for an opaque region is empty. Setting the pending - * opaque region has copy semantics, and the wl_region object can be - * destroyed immediately. A NULL wl_region causes the pending opaque - * region to be set to empty. - */ -static inline void -wl_surface_set_opaque_region(struct wl_surface *wl_surface, struct wl_region *region) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_SET_OPAQUE_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, region); -} - -/** - * @ingroup iface_wl_surface - * - * This request sets the region of the surface that can receive - * pointer and touch events. - * - * Input events happening outside of this region will try the next - * surface in the server surface stack. The compositor ignores the - * parts of the input region that fall outside of the surface. - * - * The input region is specified in surface-local coordinates. - * - * Input region is double-buffered state, see wl_surface.commit. - * - * wl_surface.set_input_region changes the pending input region. - * wl_surface.commit copies the pending region to the current region. - * Otherwise the pending and current regions are never changed, - * except cursor and icon surfaces are special cases, see - * wl_pointer.set_cursor and wl_data_device.start_drag. - * - * The initial value for an input region is infinite. That means the - * whole surface will accept input. Setting the pending input region - * has copy semantics, and the wl_region object can be destroyed - * immediately. A NULL wl_region causes the input region to be set - * to infinite. - */ -static inline void -wl_surface_set_input_region(struct wl_surface *wl_surface, struct wl_region *region) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_SET_INPUT_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, region); -} - -/** - * @ingroup iface_wl_surface - * - * Surface state (input, opaque, and damage regions, attached buffers, - * etc.) is double-buffered. Protocol requests modify the pending state, - * as opposed to the current state in use by the compositor. A commit - * request atomically applies all pending state, replacing the current - * state. After commit, the new pending state is as documented for each - * related request. - * - * On commit, a pending wl_buffer is applied first, and all other state - * second. This means that all coordinates in double-buffered state are - * relative to the new wl_buffer coming into use, except for - * wl_surface.attach itself. If there is no pending wl_buffer, the - * coordinates are relative to the current surface contents. - * - * All requests that need a commit to become effective are documented - * to affect double-buffered state. - * - * Other interfaces may add further double-buffered surface state. - */ -static inline void -wl_surface_commit(struct wl_surface *wl_surface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_COMMIT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0); -} - -/** - * @ingroup iface_wl_surface - * - * This request sets an optional transformation on how the compositor - * interprets the contents of the buffer attached to the surface. The - * accepted values for the transform parameter are the values for - * wl_output.transform. - * - * Buffer transform is double-buffered state, see wl_surface.commit. - * - * A newly created surface has its buffer transformation set to normal. - * - * wl_surface.set_buffer_transform changes the pending buffer - * transformation. wl_surface.commit copies the pending buffer - * transformation to the current one. Otherwise, the pending and current - * values are never changed. - * - * The purpose of this request is to allow clients to render content - * according to the output transform, thus permitting the compositor to - * use certain optimizations even if the display is rotated. Using - * hardware overlays and scanning out a client buffer for fullscreen - * surfaces are examples of such optimizations. Those optimizations are - * highly dependent on the compositor implementation, so the use of this - * request should be considered on a case-by-case basis. - * - * Note that if the transform value includes 90 or 270 degree rotation, - * the width of the buffer will become the surface height and the height - * of the buffer will become the surface width. - * - * If transform is not one of the values from the - * wl_output.transform enum the invalid_transform protocol error - * is raised. - */ -static inline void -wl_surface_set_buffer_transform(struct wl_surface *wl_surface, int32_t transform) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_SET_BUFFER_TRANSFORM, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, transform); -} - -/** - * @ingroup iface_wl_surface - * - * This request sets an optional scaling factor on how the compositor - * interprets the contents of the buffer attached to the window. - * - * Buffer scale is double-buffered state, see wl_surface.commit. - * - * A newly created surface has its buffer scale set to 1. - * - * wl_surface.set_buffer_scale changes the pending buffer scale. - * wl_surface.commit copies the pending buffer scale to the current one. - * Otherwise, the pending and current values are never changed. - * - * The purpose of this request is to allow clients to supply higher - * resolution buffer data for use on high resolution outputs. It is - * intended that you pick the same buffer scale as the scale of the - * output that the surface is displayed on. This means the compositor - * can avoid scaling when rendering the surface on that output. - * - * Note that if the scale is larger than 1, then you have to attach - * a buffer that is larger (by a factor of scale in each dimension) - * than the desired surface size. - * - * If scale is not positive the invalid_scale protocol error is - * raised. - */ -static inline void -wl_surface_set_buffer_scale(struct wl_surface *wl_surface, int32_t scale) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_SET_BUFFER_SCALE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, scale); -} - -/** - * @ingroup iface_wl_surface - * - * This request is used to describe the regions where the pending - * buffer is different from the current surface contents, and where - * the surface therefore needs to be repainted. The compositor - * ignores the parts of the damage that fall outside of the surface. - * - * Damage is double-buffered state, see wl_surface.commit. - * - * The damage rectangle is specified in buffer coordinates, - * where x and y specify the upper left corner of the damage rectangle. - * - * The initial value for pending damage is empty: no damage. - * wl_surface.damage_buffer adds pending damage: the new pending - * damage is the union of old pending damage and the given rectangle. - * - * wl_surface.commit assigns pending damage as the current damage, - * and clears pending damage. The server will clear the current - * damage as it repaints the surface. - * - * This request differs from wl_surface.damage in only one way - it - * takes damage in buffer coordinates instead of surface-local - * coordinates. While this generally is more intuitive than surface - * coordinates, it is especially desirable when using wp_viewport - * or when a drawing library (like EGL) is unaware of buffer scale - * and buffer transform. - * - * Note: Because buffer transformation changes and damage requests may - * be interleaved in the protocol stream, it is impossible to determine - * the actual mapping between surface and buffer damage until - * wl_surface.commit time. Therefore, compositors wishing to take both - * kinds of damage into account will have to accumulate damage from the - * two requests separately and only transform from one to the other - * after receiving the wl_surface.commit. - */ -static inline void -wl_surface_damage_buffer(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_surface, - WL_SURFACE_DAMAGE_BUFFER, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y, width, height); -} - -#ifndef WL_SEAT_CAPABILITY_ENUM -#define WL_SEAT_CAPABILITY_ENUM -/** - * @ingroup iface_wl_seat - * seat capability bitmask - * - * This is a bitmask of capabilities this seat has; if a member is - * set, then it is present on the seat. - */ -enum wl_seat_capability { - /** - * the seat has pointer devices - */ - WL_SEAT_CAPABILITY_POINTER = 1, - /** - * the seat has one or more keyboards - */ - WL_SEAT_CAPABILITY_KEYBOARD = 2, - /** - * the seat has touch devices - */ - WL_SEAT_CAPABILITY_TOUCH = 4, -}; -#endif /* WL_SEAT_CAPABILITY_ENUM */ - -/** - * @ingroup iface_wl_seat - * @struct wl_seat_listener - */ -struct wl_seat_listener { - /** - * seat capabilities changed - * - * This is emitted whenever a seat gains or loses the pointer, - * keyboard or touch capabilities. The argument is a capability - * enum containing the complete set of capabilities this seat has. - * - * When the pointer capability is added, a client may create a - * wl_pointer object using the wl_seat.get_pointer request. This - * object will receive pointer events until the capability is - * removed in the future. - * - * When the pointer capability is removed, a client should destroy - * the wl_pointer objects associated with the seat where the - * capability was removed, using the wl_pointer.release request. No - * further pointer events will be received on these objects. - * - * In some compositors, if a seat regains the pointer capability - * and a client has a previously obtained wl_pointer object of - * version 4 or less, that object may start sending pointer events - * again. This behavior is considered a misinterpretation of the - * intended behavior and must not be relied upon by the client. - * wl_pointer objects of version 5 or later must not send events if - * created before the most recent event notifying the client of an - * added pointer capability. - * - * The above behavior also applies to wl_keyboard and wl_touch with - * the keyboard and touch capabilities, respectively. - * @param capabilities capabilities of the seat - */ - void (*capabilities)(void *data, - struct wl_seat *wl_seat, - uint32_t capabilities); - /** - * unique identifier for this seat - * - * In a multiseat configuration this can be used by the client to - * help identify which physical devices the seat represents. Based - * on the seat configuration used by the compositor. - * @param name seat identifier - * @since 2 - */ - void (*name)(void *data, - struct wl_seat *wl_seat, - const char *name); -}; - -/** - * @ingroup iface_wl_seat - */ -static inline int -wl_seat_add_listener(struct wl_seat *wl_seat, - const struct wl_seat_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_seat, - (void (**)(void)) listener, data); -} - -#define WL_SEAT_GET_POINTER 0 -#define WL_SEAT_GET_KEYBOARD 1 -#define WL_SEAT_GET_TOUCH 2 -#define WL_SEAT_RELEASE 3 - -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_CAPABILITIES_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_NAME_SINCE_VERSION 2 - -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_GET_POINTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_GET_KEYBOARD_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_GET_TOUCH_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_RELEASE_SINCE_VERSION 5 - -/** @ingroup iface_wl_seat */ -static inline void -wl_seat_set_user_data(struct wl_seat *wl_seat, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_seat, user_data); -} - -/** @ingroup iface_wl_seat */ -static inline void * -wl_seat_get_user_data(struct wl_seat *wl_seat) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_seat); -} - -static inline uint32_t -wl_seat_get_version(struct wl_seat *wl_seat) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_seat); -} - -/** @ingroup iface_wl_seat */ -static inline void -wl_seat_destroy(struct wl_seat *wl_seat) -{ - wl_proxy_destroy((struct wl_proxy *) wl_seat); -} - -/** - * @ingroup iface_wl_seat - * - * The ID provided will be initialized to the wl_pointer interface - * for this seat. - * - * This request only takes effect if the seat has the pointer - * capability, or has had the pointer capability in the past. - * It is a protocol violation to issue this request on a seat that has - * never had the pointer capability. - */ -static inline struct wl_pointer * -wl_seat_get_pointer(struct wl_seat *wl_seat) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat, - WL_SEAT_GET_POINTER, &wl_pointer_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL); - - return (struct wl_pointer *) id; -} - -/** - * @ingroup iface_wl_seat - * - * The ID provided will be initialized to the wl_keyboard interface - * for this seat. - * - * This request only takes effect if the seat has the keyboard - * capability, or has had the keyboard capability in the past. - * It is a protocol violation to issue this request on a seat that has - * never had the keyboard capability. - */ -static inline struct wl_keyboard * -wl_seat_get_keyboard(struct wl_seat *wl_seat) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat, - WL_SEAT_GET_KEYBOARD, &wl_keyboard_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL); - - return (struct wl_keyboard *) id; -} - -/** - * @ingroup iface_wl_seat - * - * The ID provided will be initialized to the wl_touch interface - * for this seat. - * - * This request only takes effect if the seat has the touch - * capability, or has had the touch capability in the past. - * It is a protocol violation to issue this request on a seat that has - * never had the touch capability. - */ -static inline struct wl_touch * -wl_seat_get_touch(struct wl_seat *wl_seat) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat, - WL_SEAT_GET_TOUCH, &wl_touch_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL); - - return (struct wl_touch *) id; -} - -/** - * @ingroup iface_wl_seat - * - * Using this request a client can tell the server that it is not going to - * use the seat object anymore. - */ -static inline void -wl_seat_release(struct wl_seat *wl_seat) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_seat, - WL_SEAT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_seat), WL_MARSHAL_FLAG_DESTROY); -} - -#ifndef WL_POINTER_ERROR_ENUM -#define WL_POINTER_ERROR_ENUM -enum wl_pointer_error { - /** - * given wl_surface has another role - */ - WL_POINTER_ERROR_ROLE = 0, -}; -#endif /* WL_POINTER_ERROR_ENUM */ - -#ifndef WL_POINTER_BUTTON_STATE_ENUM -#define WL_POINTER_BUTTON_STATE_ENUM -/** - * @ingroup iface_wl_pointer - * physical button state - * - * Describes the physical state of a button that produced the button - * event. - */ -enum wl_pointer_button_state { - /** - * the button is not pressed - */ - WL_POINTER_BUTTON_STATE_RELEASED = 0, - /** - * the button is pressed - */ - WL_POINTER_BUTTON_STATE_PRESSED = 1, -}; -#endif /* WL_POINTER_BUTTON_STATE_ENUM */ - -#ifndef WL_POINTER_AXIS_ENUM -#define WL_POINTER_AXIS_ENUM -/** - * @ingroup iface_wl_pointer - * axis types - * - * Describes the axis types of scroll events. - */ -enum wl_pointer_axis { - /** - * vertical axis - */ - WL_POINTER_AXIS_VERTICAL_SCROLL = 0, - /** - * horizontal axis - */ - WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1, -}; -#endif /* WL_POINTER_AXIS_ENUM */ - -#ifndef WL_POINTER_AXIS_SOURCE_ENUM -#define WL_POINTER_AXIS_SOURCE_ENUM -/** - * @ingroup iface_wl_pointer - * axis source types - * - * Describes the source types for axis events. This indicates to the - * client how an axis event was physically generated; a client may - * adjust the user interface accordingly. For example, scroll events - * from a "finger" source may be in a smooth coordinate space with - * kinetic scrolling whereas a "wheel" source may be in discrete steps - * of a number of lines. - */ -enum wl_pointer_axis_source { - /** - * a physical wheel rotation - */ - WL_POINTER_AXIS_SOURCE_WHEEL = 0, - /** - * finger on a touch surface - */ - WL_POINTER_AXIS_SOURCE_FINGER = 1, - /** - * continuous coordinate space - * - * A device generating events in a continuous coordinate space, - * but using something other than a finger. One example for this - * source is button-based scrolling where the vertical motion of a - * device is converted to scroll events while a button is held - * down. - */ - WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2, - /** - * a physical wheel tilt - * - * Indicates that the actual device is a wheel but the scroll - * event is not caused by a rotation but a (usually sideways) tilt - * of the wheel. - * @since 6 - */ - WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3, -}; -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6 -#endif /* WL_POINTER_AXIS_SOURCE_ENUM */ - -/** - * @ingroup iface_wl_pointer - * @struct wl_pointer_listener - */ -struct wl_pointer_listener { - /** - * enter event - * - * Notification that this seat's pointer is focused on a certain - * surface. - * - * When a seat's focus enters a surface, the pointer image is - * undefined and a client should respond to this event by setting - * an appropriate pointer image with the set_cursor request. - * @param serial serial number of the enter event - * @param surface surface entered by the pointer - * @param surface_x surface-local x coordinate - * @param surface_y surface-local y coordinate - */ - void (*enter)(void *data, - struct wl_pointer *wl_pointer, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t surface_x, - wl_fixed_t surface_y); - /** - * leave event - * - * Notification that this seat's pointer is no longer focused on - * a certain surface. - * - * The leave notification is sent before the enter notification for - * the new focus. - * @param serial serial number of the leave event - * @param surface surface left by the pointer - */ - void (*leave)(void *data, - struct wl_pointer *wl_pointer, - uint32_t serial, - struct wl_surface *surface); - /** - * pointer motion event - * - * Notification of pointer location change. The arguments - * surface_x and surface_y are the location relative to the focused - * surface. - * @param time timestamp with millisecond granularity - * @param surface_x surface-local x coordinate - * @param surface_y surface-local y coordinate - */ - void (*motion)(void *data, - struct wl_pointer *wl_pointer, - uint32_t time, - wl_fixed_t surface_x, - wl_fixed_t surface_y); - /** - * pointer button event - * - * Mouse button click and release notifications. - * - * The location of the click is given by the last motion or enter - * event. The time argument is a timestamp with millisecond - * granularity, with an undefined base. - * - * The button is a button code as defined in the Linux kernel's - * linux/input-event-codes.h header file, e.g. BTN_LEFT. - * - * Any 16-bit button code value is reserved for future additions to - * the kernel's event code list. All other button codes above - * 0xFFFF are currently undefined but may be used in future - * versions of this protocol. - * @param serial serial number of the button event - * @param time timestamp with millisecond granularity - * @param button button that produced the event - * @param state physical state of the button - */ - void (*button)(void *data, - struct wl_pointer *wl_pointer, - uint32_t serial, - uint32_t time, - uint32_t button, - uint32_t state); - /** - * axis event - * - * Scroll and other axis notifications. - * - * For scroll events (vertical and horizontal scroll axes), the - * value parameter is the length of a vector along the specified - * axis in a coordinate space identical to those of motion events, - * representing a relative movement along the specified axis. - * - * For devices that support movements non-parallel to axes multiple - * axis events will be emitted. - * - * When applicable, for example for touch pads, the server can - * choose to emit scroll events where the motion vector is - * equivalent to a motion event vector. - * - * When applicable, a client can transform its content relative to - * the scroll distance. - * @param time timestamp with millisecond granularity - * @param axis axis type - * @param value length of vector in surface-local coordinate space - */ - void (*axis)(void *data, - struct wl_pointer *wl_pointer, - uint32_t time, - uint32_t axis, - wl_fixed_t value); - /** - * end of a pointer event sequence - * - * Indicates the end of a set of events that logically belong - * together. A client is expected to accumulate the data in all - * events within the frame before proceeding. - * - * All wl_pointer events before a wl_pointer.frame event belong - * logically together. For example, in a diagonal scroll motion the - * compositor will send an optional wl_pointer.axis_source event, - * two wl_pointer.axis events (horizontal and vertical) and finally - * a wl_pointer.frame event. The client may use this information to - * calculate a diagonal vector for scrolling. - * - * When multiple wl_pointer.axis events occur within the same - * frame, the motion vector is the combined motion of all events. - * When a wl_pointer.axis and a wl_pointer.axis_stop event occur - * within the same frame, this indicates that axis movement in one - * axis has stopped but continues in the other axis. When multiple - * wl_pointer.axis_stop events occur within the same frame, this - * indicates that these axes stopped in the same instance. - * - * A wl_pointer.frame event is sent for every logical event group, - * even if the group only contains a single wl_pointer event. - * Specifically, a client may get a sequence: motion, frame, - * button, frame, axis, frame, axis_stop, frame. - * - * The wl_pointer.enter and wl_pointer.leave events are logical - * events generated by the compositor and not the hardware. These - * events are also grouped by a wl_pointer.frame. When a pointer - * moves from one surface to another, a compositor should group the - * wl_pointer.leave event within the same wl_pointer.frame. - * However, a client must not rely on wl_pointer.leave and - * wl_pointer.enter being in the same wl_pointer.frame. - * Compositor-specific policies may require the wl_pointer.leave - * and wl_pointer.enter event being split across multiple - * wl_pointer.frame groups. - * @since 5 - */ - void (*frame)(void *data, - struct wl_pointer *wl_pointer); - /** - * axis source event - * - * Source information for scroll and other axes. - * - * This event does not occur on its own. It is sent before a - * wl_pointer.frame event and carries the source information for - * all events within that frame. - * - * The source specifies how this event was generated. If the source - * is wl_pointer.axis_source.finger, a wl_pointer.axis_stop event - * will be sent when the user lifts the finger off the device. - * - * If the source is wl_pointer.axis_source.wheel, - * wl_pointer.axis_source.wheel_tilt or - * wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event - * may or may not be sent. Whether a compositor sends an axis_stop - * event for these sources is hardware-specific and - * implementation-dependent; clients must not rely on receiving an - * axis_stop event for these scroll sources and should treat scroll - * sequences from these scroll sources as unterminated by default. - * - * This event is optional. If the source is unknown for a - * particular axis event sequence, no event is sent. Only one - * wl_pointer.axis_source event is permitted per frame. - * - * The order of wl_pointer.axis_discrete and wl_pointer.axis_source - * is not guaranteed. - * @param axis_source source of the axis event - * @since 5 - */ - void (*axis_source)(void *data, - struct wl_pointer *wl_pointer, - uint32_t axis_source); - /** - * axis stop event - * - * Stop notification for scroll and other axes. - * - * For some wl_pointer.axis_source types, a wl_pointer.axis_stop - * event is sent to notify a client that the axis sequence has - * terminated. This enables the client to implement kinetic - * scrolling. See the wl_pointer.axis_source documentation for - * information on when this event may be generated. - * - * Any wl_pointer.axis events with the same axis_source after this - * event should be considered as the start of a new axis motion. - * - * The timestamp is to be interpreted identical to the timestamp in - * the wl_pointer.axis event. The timestamp value may be the same - * as a preceding wl_pointer.axis event. - * @param time timestamp with millisecond granularity - * @param axis the axis stopped with this event - * @since 5 - */ - void (*axis_stop)(void *data, - struct wl_pointer *wl_pointer, - uint32_t time, - uint32_t axis); - /** - * axis click event - * - * Discrete step information for scroll and other axes. - * - * This event carries the axis value of the wl_pointer.axis event - * in discrete steps (e.g. mouse wheel clicks). - * - * This event does not occur on its own, it is coupled with a - * wl_pointer.axis event that represents this axis value on a - * continuous scale. The protocol guarantees that each - * axis_discrete event is always followed by exactly one axis event - * with the same axis number within the same wl_pointer.frame. Note - * that the protocol allows for other events to occur between the - * axis_discrete and its coupled axis event, including other - * axis_discrete or axis events. - * - * This event is optional; continuous scrolling devices like - * two-finger scrolling on touchpads do not have discrete steps and - * do not generate this event. - * - * The discrete value carries the directional information. e.g. a - * value of -2 is two steps towards the negative direction of this - * axis. - * - * The axis number is identical to the axis number in the - * associated axis event. - * - * The order of wl_pointer.axis_discrete and wl_pointer.axis_source - * is not guaranteed. - * @param axis axis type - * @param discrete number of steps - * @since 5 - */ - void (*axis_discrete)(void *data, - struct wl_pointer *wl_pointer, - uint32_t axis, - int32_t discrete); -}; - -/** - * @ingroup iface_wl_pointer - */ -static inline int -wl_pointer_add_listener(struct wl_pointer *wl_pointer, - const struct wl_pointer_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_pointer, - (void (**)(void)) listener, data); -} - -#define WL_POINTER_SET_CURSOR 0 -#define WL_POINTER_RELEASE 1 - -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_LEAVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_MOTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_BUTTON_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_FRAME_SINCE_VERSION 5 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SOURCE_SINCE_VERSION 5 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_STOP_SINCE_VERSION 5 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_DISCRETE_SINCE_VERSION 5 - -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_SET_CURSOR_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_RELEASE_SINCE_VERSION 3 - -/** @ingroup iface_wl_pointer */ -static inline void -wl_pointer_set_user_data(struct wl_pointer *wl_pointer, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_pointer, user_data); -} - -/** @ingroup iface_wl_pointer */ -static inline void * -wl_pointer_get_user_data(struct wl_pointer *wl_pointer) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_pointer); -} - -static inline uint32_t -wl_pointer_get_version(struct wl_pointer *wl_pointer) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_pointer); -} - -/** @ingroup iface_wl_pointer */ -static inline void -wl_pointer_destroy(struct wl_pointer *wl_pointer) -{ - wl_proxy_destroy((struct wl_proxy *) wl_pointer); -} - -/** - * @ingroup iface_wl_pointer - * - * Set the pointer surface, i.e., the surface that contains the - * pointer image (cursor). This request gives the surface the role - * of a cursor. If the surface already has another role, it raises - * a protocol error. - * - * The cursor actually changes only if the pointer - * focus for this device is one of the requesting client's surfaces - * or the surface parameter is the current pointer surface. If - * there was a previous surface set with this request it is - * replaced. If surface is NULL, the pointer image is hidden. - * - * The parameters hotspot_x and hotspot_y define the position of - * the pointer surface relative to the pointer location. Its - * top-left corner is always at (x, y) - (hotspot_x, hotspot_y), - * where (x, y) are the coordinates of the pointer location, in - * surface-local coordinates. - * - * On surface.attach requests to the pointer surface, hotspot_x - * and hotspot_y are decremented by the x and y parameters - * passed to the request. Attach must be confirmed by - * wl_surface.commit as usual. - * - * The hotspot can also be updated by passing the currently set - * pointer surface to this request with new values for hotspot_x - * and hotspot_y. - * - * The current and pending input regions of the wl_surface are - * cleared, and wl_surface.set_input_region is ignored until the - * wl_surface is no longer used as the cursor. When the use as a - * cursor ends, the current and pending input regions become - * undefined, and the wl_surface is unmapped. - */ -static inline void -wl_pointer_set_cursor(struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_pointer, - WL_POINTER_SET_CURSOR, NULL, wl_proxy_get_version((struct wl_proxy *) wl_pointer), 0, serial, surface, hotspot_x, hotspot_y); -} - -/** - * @ingroup iface_wl_pointer - * - * Using this request a client can tell the server that it is not going to - * use the pointer object anymore. - * - * This request destroys the pointer proxy object, so clients must not call - * wl_pointer_destroy() after using this request. - */ -static inline void -wl_pointer_release(struct wl_pointer *wl_pointer) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_pointer, - WL_POINTER_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_pointer), WL_MARSHAL_FLAG_DESTROY); -} - -#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM -#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM -/** - * @ingroup iface_wl_keyboard - * keyboard mapping format - * - * This specifies the format of the keymap provided to the - * client with the wl_keyboard.keymap event. - */ -enum wl_keyboard_keymap_format { - /** - * no keymap; client must understand how to interpret the raw keycode - */ - WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0, - /** - * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode - */ - WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1, -}; -#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */ - -#ifndef WL_KEYBOARD_KEY_STATE_ENUM -#define WL_KEYBOARD_KEY_STATE_ENUM -/** - * @ingroup iface_wl_keyboard - * physical key state - * - * Describes the physical state of a key that produced the key event. - */ -enum wl_keyboard_key_state { - /** - * key is not pressed - */ - WL_KEYBOARD_KEY_STATE_RELEASED = 0, - /** - * key is pressed - */ - WL_KEYBOARD_KEY_STATE_PRESSED = 1, -}; -#endif /* WL_KEYBOARD_KEY_STATE_ENUM */ - -/** - * @ingroup iface_wl_keyboard - * @struct wl_keyboard_listener - */ -struct wl_keyboard_listener { - /** - * keyboard mapping - * - * This event provides a file descriptor to the client which can - * be memory-mapped to provide a keyboard mapping description. - * @param format keymap format - * @param fd keymap file descriptor - * @param size keymap size, in bytes - */ - void (*keymap)(void *data, - struct wl_keyboard *wl_keyboard, - uint32_t format, - int32_t fd, - uint32_t size); - /** - * enter event - * - * Notification that this seat's keyboard focus is on a certain - * surface. - * @param serial serial number of the enter event - * @param surface surface gaining keyboard focus - * @param keys the currently pressed keys - */ - void (*enter)(void *data, - struct wl_keyboard *wl_keyboard, - uint32_t serial, - struct wl_surface *surface, - struct wl_array *keys); - /** - * leave event - * - * Notification that this seat's keyboard focus is no longer on a - * certain surface. - * - * The leave notification is sent before the enter notification for - * the new focus. - * @param serial serial number of the leave event - * @param surface surface that lost keyboard focus - */ - void (*leave)(void *data, - struct wl_keyboard *wl_keyboard, - uint32_t serial, - struct wl_surface *surface); - /** - * key event - * - * A key was pressed or released. The time argument is a - * timestamp with millisecond granularity, with an undefined base. - * @param serial serial number of the key event - * @param time timestamp with millisecond granularity - * @param key key that produced the event - * @param state physical state of the key - */ - void (*key)(void *data, - struct wl_keyboard *wl_keyboard, - uint32_t serial, - uint32_t time, - uint32_t key, - uint32_t state); - /** - * modifier and group state - * - * Notifies clients that the modifier and/or group state has - * changed, and it should update its local state. - * @param serial serial number of the modifiers event - * @param mods_depressed depressed modifiers - * @param mods_latched latched modifiers - * @param mods_locked locked modifiers - * @param group keyboard layout - */ - void (*modifiers)(void *data, - struct wl_keyboard *wl_keyboard, - uint32_t serial, - uint32_t mods_depressed, - uint32_t mods_latched, - uint32_t mods_locked, - uint32_t group); - /** - * repeat rate and delay - * - * Informs the client about the keyboard's repeat rate and delay. - * - * This event is sent as soon as the wl_keyboard object has been - * created, and is guaranteed to be received by the client before - * any key press event. - * - * Negative values for either rate or delay are illegal. A rate of - * zero will disable any repeating (regardless of the value of - * delay). - * - * This event can be sent later on as well with a new value if - * necessary, so clients should continue listening for the event - * past the creation of wl_keyboard. - * @param rate the rate of repeating keys in characters per second - * @param delay delay in milliseconds since key down until repeating starts - * @since 4 - */ - void (*repeat_info)(void *data, - struct wl_keyboard *wl_keyboard, - int32_t rate, - int32_t delay); -}; - -/** - * @ingroup iface_wl_keyboard - */ -static inline int -wl_keyboard_add_listener(struct wl_keyboard *wl_keyboard, - const struct wl_keyboard_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_keyboard, - (void (**)(void)) listener, data); -} - -#define WL_KEYBOARD_RELEASE 0 - -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_KEYMAP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_LEAVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_KEY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_MODIFIERS_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION 4 - -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_RELEASE_SINCE_VERSION 3 - -/** @ingroup iface_wl_keyboard */ -static inline void -wl_keyboard_set_user_data(struct wl_keyboard *wl_keyboard, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_keyboard, user_data); -} - -/** @ingroup iface_wl_keyboard */ -static inline void * -wl_keyboard_get_user_data(struct wl_keyboard *wl_keyboard) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_keyboard); -} - -static inline uint32_t -wl_keyboard_get_version(struct wl_keyboard *wl_keyboard) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_keyboard); -} - -/** @ingroup iface_wl_keyboard */ -static inline void -wl_keyboard_destroy(struct wl_keyboard *wl_keyboard) -{ - wl_proxy_destroy((struct wl_proxy *) wl_keyboard); -} - -/** - * @ingroup iface_wl_keyboard - */ -static inline void -wl_keyboard_release(struct wl_keyboard *wl_keyboard) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_keyboard, - WL_KEYBOARD_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_keyboard), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_touch - * @struct wl_touch_listener - */ -struct wl_touch_listener { - /** - * touch down event and beginning of a touch sequence - * - * A new touch point has appeared on the surface. This touch - * point is assigned a unique ID. Future events from this touch - * point reference this ID. The ID ceases to be valid after a touch - * up event and may be reused in the future. - * @param serial serial number of the touch down event - * @param time timestamp with millisecond granularity - * @param surface surface touched - * @param id the unique ID of this touch point - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ - void (*down)(void *data, - struct wl_touch *wl_touch, - uint32_t serial, - uint32_t time, - struct wl_surface *surface, - int32_t id, - wl_fixed_t x, - wl_fixed_t y); - /** - * end of a touch event sequence - * - * The touch point has disappeared. No further events will be - * sent for this touch point and the touch point's ID is released - * and may be reused in a future touch down event. - * @param serial serial number of the touch up event - * @param time timestamp with millisecond granularity - * @param id the unique ID of this touch point - */ - void (*up)(void *data, - struct wl_touch *wl_touch, - uint32_t serial, - uint32_t time, - int32_t id); - /** - * update of touch point coordinates - * - * A touch point has changed coordinates. - * @param time timestamp with millisecond granularity - * @param id the unique ID of this touch point - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ - void (*motion)(void *data, - struct wl_touch *wl_touch, - uint32_t time, - int32_t id, - wl_fixed_t x, - wl_fixed_t y); - /** - * end of touch frame event - * - * Indicates the end of a set of events that logically belong - * together. A client is expected to accumulate the data in all - * events within the frame before proceeding. - * - * A wl_touch.frame terminates at least one event but otherwise no - * guarantee is provided about the set of events within a frame. A - * client must assume that any state not updated in a frame is - * unchanged from the previously known state. - */ - void (*frame)(void *data, - struct wl_touch *wl_touch); - /** - * touch session cancelled - * - * Sent if the compositor decides the touch stream is a global - * gesture. No further events are sent to the clients from that - * particular gesture. Touch cancellation applies to all touch - * points currently active on this client's surface. The client is - * responsible for finalizing the touch points, future touch points - * on this surface may reuse the touch point ID. - */ - void (*cancel)(void *data, - struct wl_touch *wl_touch); - /** - * update shape of touch point - * - * Sent when a touchpoint has changed its shape. - * - * This event does not occur on its own. It is sent before a - * wl_touch.frame event and carries the new shape information for - * any previously reported, or new touch points of that frame. - * - * Other events describing the touch point such as wl_touch.down, - * wl_touch.motion or wl_touch.orientation may be sent within the - * same wl_touch.frame. A client should treat these events as a - * single logical touch point update. The order of wl_touch.shape, - * wl_touch.orientation and wl_touch.motion is not guaranteed. A - * wl_touch.down event is guaranteed to occur before the first - * wl_touch.shape event for this touch ID but both events may occur - * within the same wl_touch.frame. - * - * A touchpoint shape is approximated by an ellipse through the - * major and minor axis length. The major axis length describes the - * longer diameter of the ellipse, while the minor axis length - * describes the shorter diameter. Major and minor are orthogonal - * and both are specified in surface-local coordinates. The center - * of the ellipse is always at the touchpoint location as reported - * by wl_touch.down or wl_touch.move. - * - * This event is only sent by the compositor if the touch device - * supports shape reports. The client has to make reasonable - * assumptions about the shape if it did not receive this event. - * @param id the unique ID of this touch point - * @param major length of the major axis in surface-local coordinates - * @param minor length of the minor axis in surface-local coordinates - * @since 6 - */ - void (*shape)(void *data, - struct wl_touch *wl_touch, - int32_t id, - wl_fixed_t major, - wl_fixed_t minor); - /** - * update orientation of touch point - * - * Sent when a touchpoint has changed its orientation. - * - * This event does not occur on its own. It is sent before a - * wl_touch.frame event and carries the new shape information for - * any previously reported, or new touch points of that frame. - * - * Other events describing the touch point such as wl_touch.down, - * wl_touch.motion or wl_touch.shape may be sent within the same - * wl_touch.frame. A client should treat these events as a single - * logical touch point update. The order of wl_touch.shape, - * wl_touch.orientation and wl_touch.motion is not guaranteed. A - * wl_touch.down event is guaranteed to occur before the first - * wl_touch.orientation event for this touch ID but both events may - * occur within the same wl_touch.frame. - * - * The orientation describes the clockwise angle of a touchpoint's - * major axis to the positive surface y-axis and is normalized to - * the -180 to +180 degree range. The granularity of orientation - * depends on the touch device, some devices only support binary - * rotation values between 0 and 90 degrees. - * - * This event is only sent by the compositor if the touch device - * supports orientation reports. - * @param id the unique ID of this touch point - * @param orientation angle between major axis and positive surface y-axis in degrees - * @since 6 - */ - void (*orientation)(void *data, - struct wl_touch *wl_touch, - int32_t id, - wl_fixed_t orientation); -}; - -/** - * @ingroup iface_wl_touch - */ -static inline int -wl_touch_add_listener(struct wl_touch *wl_touch, - const struct wl_touch_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_touch, - (void (**)(void)) listener, data); -} - -#define WL_TOUCH_RELEASE 0 - -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_DOWN_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_UP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_MOTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_FRAME_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_CANCEL_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_SHAPE_SINCE_VERSION 6 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_ORIENTATION_SINCE_VERSION 6 - -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_RELEASE_SINCE_VERSION 3 - -/** @ingroup iface_wl_touch */ -static inline void -wl_touch_set_user_data(struct wl_touch *wl_touch, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_touch, user_data); -} - -/** @ingroup iface_wl_touch */ -static inline void * -wl_touch_get_user_data(struct wl_touch *wl_touch) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_touch); -} - -static inline uint32_t -wl_touch_get_version(struct wl_touch *wl_touch) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_touch); -} - -/** @ingroup iface_wl_touch */ -static inline void -wl_touch_destroy(struct wl_touch *wl_touch) -{ - wl_proxy_destroy((struct wl_proxy *) wl_touch); -} - -/** - * @ingroup iface_wl_touch - */ -static inline void -wl_touch_release(struct wl_touch *wl_touch) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_touch, - WL_TOUCH_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_touch), WL_MARSHAL_FLAG_DESTROY); -} - -#ifndef WL_OUTPUT_SUBPIXEL_ENUM -#define WL_OUTPUT_SUBPIXEL_ENUM -/** - * @ingroup iface_wl_output - * subpixel geometry information - * - * This enumeration describes how the physical - * pixels on an output are laid out. - */ -enum wl_output_subpixel { - /** - * unknown geometry - */ - WL_OUTPUT_SUBPIXEL_UNKNOWN = 0, - /** - * no geometry - */ - WL_OUTPUT_SUBPIXEL_NONE = 1, - /** - * horizontal RGB - */ - WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2, - /** - * horizontal BGR - */ - WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3, - /** - * vertical RGB - */ - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4, - /** - * vertical BGR - */ - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5, -}; -#endif /* WL_OUTPUT_SUBPIXEL_ENUM */ - -#ifndef WL_OUTPUT_TRANSFORM_ENUM -#define WL_OUTPUT_TRANSFORM_ENUM -/** - * @ingroup iface_wl_output - * transform from framebuffer to output - * - * This describes the transform that a compositor will apply to a - * surface to compensate for the rotation or mirroring of an - * output device. - * - * The flipped values correspond to an initial flip around a - * vertical axis followed by rotation. - * - * The purpose is mainly to allow clients to render accordingly and - * tell the compositor, so that for fullscreen surfaces, the - * compositor will still be able to scan out directly from client - * surfaces. - */ -enum wl_output_transform { - /** - * no transform - */ - WL_OUTPUT_TRANSFORM_NORMAL = 0, - /** - * 90 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_90 = 1, - /** - * 180 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_180 = 2, - /** - * 270 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_270 = 3, - /** - * 180 degree flip around a vertical axis - */ - WL_OUTPUT_TRANSFORM_FLIPPED = 4, - /** - * flip and rotate 90 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5, - /** - * flip and rotate 180 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6, - /** - * flip and rotate 270 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7, -}; -#endif /* WL_OUTPUT_TRANSFORM_ENUM */ - -#ifndef WL_OUTPUT_MODE_ENUM -#define WL_OUTPUT_MODE_ENUM -/** - * @ingroup iface_wl_output - * mode information - * - * These flags describe properties of an output mode. - * They are used in the flags bitfield of the mode event. - */ -enum wl_output_mode { - /** - * indicates this is the current mode - */ - WL_OUTPUT_MODE_CURRENT = 0x1, - /** - * indicates this is the preferred mode - */ - WL_OUTPUT_MODE_PREFERRED = 0x2, -}; -#endif /* WL_OUTPUT_MODE_ENUM */ - -/** - * @ingroup iface_wl_output - * @struct wl_output_listener - */ -struct wl_output_listener { - /** - * properties of the output - * - * The geometry event describes geometric properties of the - * output. The event is sent when binding to the output object and - * whenever any of the properties change. - * @param x x position within the global compositor space - * @param y y position within the global compositor space - * @param physical_width width in millimeters of the output - * @param physical_height height in millimeters of the output - * @param subpixel subpixel orientation of the output - * @param make textual description of the manufacturer - * @param model textual description of the model - * @param transform transform that maps framebuffer to output - */ - void (*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 transform); - /** - * advertise available modes for the output - * - * The mode event describes an available mode for the output. - * - * The event is sent when binding to the output object and there - * will always be one mode, the current mode. The event is sent - * again if an output changes mode, for the mode that is now - * current. In other words, the current mode is always the last - * mode that was received with the current flag set. - * - * The size of a mode is given in physical hardware units of the - * output device. This is not necessarily the same as the output - * size in the global compositor space. For instance, the output - * may be scaled, as described in wl_output.scale, or transformed, - * as described in wl_output.transform. - * @param flags bitfield of mode flags - * @param width width of the mode in hardware units - * @param height height of the mode in hardware units - * @param refresh vertical refresh rate in mHz - */ - void (*mode)(void *data, - struct wl_output *wl_output, - uint32_t flags, - int32_t width, - int32_t height, - int32_t refresh); - /** - * sent all information about output - * - * This event is sent after all other properties have been sent - * after binding to the output object and after any other property - * changes done after that. This allows changes to the output - * properties to be seen as atomic, even if they happen via - * multiple events. - * @since 2 - */ - void (*done)(void *data, - struct wl_output *wl_output); - /** - * output scaling properties - * - * This event contains scaling geometry information that is not - * in the geometry event. It may be sent after binding the output - * object or if the output scale changes later. If it is not sent, - * the client should assume a scale of 1. - * - * A scale larger than 1 means that the compositor will - * automatically scale surface buffers by this amount when - * rendering. This is used for very high resolution displays where - * applications rendering at the native resolution would be too - * small to be legible. - * - * It is intended that scaling aware clients track the current - * output of a surface, and if it is on a scaled output it should - * use wl_surface.set_buffer_scale with the scale of the output. - * That way the compositor can avoid scaling the surface, and the - * client can supply a higher detail image. - * @param factor scaling factor of output - * @since 2 - */ - void (*scale)(void *data, - struct wl_output *wl_output, - int32_t factor); -}; - -/** - * @ingroup iface_wl_output - */ -static inline int -wl_output_add_listener(struct wl_output *wl_output, - const struct wl_output_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) wl_output, - (void (**)(void)) listener, data); -} - -#define WL_OUTPUT_RELEASE 0 - -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_GEOMETRY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_MODE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_DONE_SINCE_VERSION 2 -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_SCALE_SINCE_VERSION 2 - -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_RELEASE_SINCE_VERSION 3 - -/** @ingroup iface_wl_output */ -static inline void -wl_output_set_user_data(struct wl_output *wl_output, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_output, user_data); -} - -/** @ingroup iface_wl_output */ -static inline void * -wl_output_get_user_data(struct wl_output *wl_output) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_output); -} - -static inline uint32_t -wl_output_get_version(struct wl_output *wl_output) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_output); -} - -/** @ingroup iface_wl_output */ -static inline void -wl_output_destroy(struct wl_output *wl_output) -{ - wl_proxy_destroy((struct wl_proxy *) wl_output); -} - -/** - * @ingroup iface_wl_output - * - * Using this request a client can tell the server that it is not going to - * use the output object anymore. - */ -static inline void -wl_output_release(struct wl_output *wl_output) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_output, - WL_OUTPUT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_output), WL_MARSHAL_FLAG_DESTROY); -} - -#define WL_REGION_DESTROY 0 -#define WL_REGION_ADD 1 -#define WL_REGION_SUBTRACT 2 - - -/** - * @ingroup iface_wl_region - */ -#define WL_REGION_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_region - */ -#define WL_REGION_ADD_SINCE_VERSION 1 -/** - * @ingroup iface_wl_region - */ -#define WL_REGION_SUBTRACT_SINCE_VERSION 1 - -/** @ingroup iface_wl_region */ -static inline void -wl_region_set_user_data(struct wl_region *wl_region, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_region, user_data); -} - -/** @ingroup iface_wl_region */ -static inline void * -wl_region_get_user_data(struct wl_region *wl_region) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_region); -} - -static inline uint32_t -wl_region_get_version(struct wl_region *wl_region) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_region); -} - -/** - * @ingroup iface_wl_region - * - * Destroy the region. This will invalidate the object ID. - */ -static inline void -wl_region_destroy(struct wl_region *wl_region) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_region, - WL_REGION_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_region - * - * Add the specified rectangle to the region. - */ -static inline void -wl_region_add(struct wl_region *wl_region, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_region, - WL_REGION_ADD, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), 0, x, y, width, height); -} - -/** - * @ingroup iface_wl_region - * - * Subtract the specified rectangle from the region. - */ -static inline void -wl_region_subtract(struct wl_region *wl_region, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_region, - WL_REGION_SUBTRACT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), 0, x, y, width, height); -} - -#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM -#define WL_SUBCOMPOSITOR_ERROR_ENUM -enum wl_subcompositor_error { - /** - * the to-be sub-surface is invalid - */ - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0, -}; -#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */ - -#define WL_SUBCOMPOSITOR_DESTROY 0 -#define WL_SUBCOMPOSITOR_GET_SUBSURFACE 1 - - -/** - * @ingroup iface_wl_subcompositor - */ -#define WL_SUBCOMPOSITOR_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subcompositor - */ -#define WL_SUBCOMPOSITOR_GET_SUBSURFACE_SINCE_VERSION 1 - -/** @ingroup iface_wl_subcompositor */ -static inline void -wl_subcompositor_set_user_data(struct wl_subcompositor *wl_subcompositor, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_subcompositor, user_data); -} - -/** @ingroup iface_wl_subcompositor */ -static inline void * -wl_subcompositor_get_user_data(struct wl_subcompositor *wl_subcompositor) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_subcompositor); -} - -static inline uint32_t -wl_subcompositor_get_version(struct wl_subcompositor *wl_subcompositor) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_subcompositor); -} - -/** - * @ingroup iface_wl_subcompositor - * - * Informs the server that the client will not be using this - * protocol object anymore. This does not affect any other - * objects, wl_subsurface objects included. - */ -static inline void -wl_subcompositor_destroy(struct wl_subcompositor *wl_subcompositor) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subcompositor, - WL_SUBCOMPOSITOR_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subcompositor), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_subcompositor - * - * Create a sub-surface interface for the given surface, and - * associate it with the given parent surface. This turns a - * plain wl_surface into a sub-surface. - * - * The to-be sub-surface must not already have another role, and it - * must not have an existing wl_subsurface object. Otherwise a protocol - * error is raised. - */ -static inline struct wl_subsurface * -wl_subcompositor_get_subsurface(struct wl_subcompositor *wl_subcompositor, struct wl_surface *surface, struct wl_surface *parent) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) wl_subcompositor, - WL_SUBCOMPOSITOR_GET_SUBSURFACE, &wl_subsurface_interface, wl_proxy_get_version((struct wl_proxy *) wl_subcompositor), 0, NULL, surface, parent); - - return (struct wl_subsurface *) id; -} - -#ifndef WL_SUBSURFACE_ERROR_ENUM -#define WL_SUBSURFACE_ERROR_ENUM -enum wl_subsurface_error { - /** - * wl_surface is not a sibling or the parent - */ - WL_SUBSURFACE_ERROR_BAD_SURFACE = 0, -}; -#endif /* WL_SUBSURFACE_ERROR_ENUM */ - -#define WL_SUBSURFACE_DESTROY 0 -#define WL_SUBSURFACE_SET_POSITION 1 -#define WL_SUBSURFACE_PLACE_ABOVE 2 -#define WL_SUBSURFACE_PLACE_BELOW 3 -#define WL_SUBSURFACE_SET_SYNC 4 -#define WL_SUBSURFACE_SET_DESYNC 5 - - -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_SET_POSITION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_PLACE_ABOVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_SET_SYNC_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION 1 - -/** @ingroup iface_wl_subsurface */ -static inline void -wl_subsurface_set_user_data(struct wl_subsurface *wl_subsurface, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wl_subsurface, user_data); -} - -/** @ingroup iface_wl_subsurface */ -static inline void * -wl_subsurface_get_user_data(struct wl_subsurface *wl_subsurface) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wl_subsurface); -} - -static inline uint32_t -wl_subsurface_get_version(struct wl_subsurface *wl_subsurface) -{ - return wl_proxy_get_version((struct wl_proxy *) wl_subsurface); -} - -/** - * @ingroup iface_wl_subsurface - * - * The sub-surface interface is removed from the wl_surface object - * that was turned into a sub-surface with a - * wl_subcompositor.get_subsurface request. The wl_surface's association - * to the parent is deleted, and the wl_surface loses its role as - * a sub-surface. The wl_surface is unmapped. - */ -static inline void -wl_subsurface_destroy(struct wl_subsurface *wl_subsurface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface, - WL_SUBSURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wl_subsurface - * - * This schedules a sub-surface position change. - * The sub-surface will be moved so that its origin (top left - * corner pixel) will be at the location x, y of the parent surface - * coordinate system. The coordinates are not restricted to the parent - * surface area. Negative values are allowed. - * - * The scheduled coordinates will take effect whenever the state of the - * parent surface is applied. When this happens depends on whether the - * parent surface is in synchronized mode or not. See - * wl_subsurface.set_sync and wl_subsurface.set_desync for details. - * - * If more than one set_position request is invoked by the client before - * the commit of the parent surface, the position of a new request always - * replaces the scheduled position from any previous request. - * - * The initial position is 0, 0. - */ -static inline void -wl_subsurface_set_position(struct wl_subsurface *wl_subsurface, int32_t x, int32_t y) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface, - WL_SUBSURFACE_SET_POSITION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, x, y); -} - -/** - * @ingroup iface_wl_subsurface - * - * This sub-surface is taken from the stack, and put back just - * above the reference surface, changing the z-order of the sub-surfaces. - * The reference surface must be one of the sibling surfaces, or the - * parent surface. Using any other surface, including this sub-surface, - * will cause a protocol error. - * - * The z-order is double-buffered. Requests are handled in order and - * applied immediately to a pending state. The final pending state is - * copied to the active state the next time the state of the parent - * surface is applied. When this happens depends on whether the parent - * surface is in synchronized mode or not. See wl_subsurface.set_sync and - * wl_subsurface.set_desync for details. - * - * A new sub-surface is initially added as the top-most in the stack - * of its siblings and parent. - */ -static inline void -wl_subsurface_place_above(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface, - WL_SUBSURFACE_PLACE_ABOVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, sibling); -} - -/** - * @ingroup iface_wl_subsurface - * - * The sub-surface is placed just below the reference surface. - * See wl_subsurface.place_above. - */ -static inline void -wl_subsurface_place_below(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface, - WL_SUBSURFACE_PLACE_BELOW, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, sibling); -} - -/** - * @ingroup iface_wl_subsurface - * - * Change the commit behaviour of the sub-surface to synchronized - * mode, also described as the parent dependent mode. - * - * In synchronized mode, wl_surface.commit on a sub-surface will - * accumulate the committed state in a cache, but the state will - * not be applied and hence will not change the compositor output. - * The cached state is applied to the sub-surface immediately after - * the parent surface's state is applied. This ensures atomic - * updates of the parent and all its synchronized sub-surfaces. - * Applying the cached state will invalidate the cache, so further - * parent surface commits do not (re-)apply old state. - * - * See wl_subsurface for the recursive effect of this mode. - */ -static inline void -wl_subsurface_set_sync(struct wl_subsurface *wl_subsurface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface, - WL_SUBSURFACE_SET_SYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0); -} - -/** - * @ingroup iface_wl_subsurface - * - * Change the commit behaviour of the sub-surface to desynchronized - * mode, also described as independent or freely running mode. - * - * In desynchronized mode, wl_surface.commit on a sub-surface will - * apply the pending state directly, without caching, as happens - * normally with a wl_surface. Calling wl_surface.commit on the - * parent surface has no effect on the sub-surface's wl_surface - * state. This mode allows a sub-surface to be updated on its own. - * - * If cached state exists when wl_surface.commit is called in - * desynchronized mode, the pending state is added to the cached - * state, and applied as a whole. This invalidates the cache. - * - * Note: even if a sub-surface is set to desynchronized, a parent - * sub-surface may override it to behave as synchronized. For details, - * see wl_subsurface. - * - * If a surface's parent surface behaves as desynchronized, then - * the cached state is applied on set_desync. - */ -static inline void -wl_subsurface_set_desync(struct wl_subsurface *wl_subsurface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface, - WL_SUBSURFACE_SET_DESYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/example-code.c b/tests/data/example-code.c deleted file mode 100644 index 37feed78..00000000 --- a/tests/data/example-code.c +++ /dev/null @@ -1,508 +0,0 @@ -/* SCANNER TEST */ - -/* - * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2010-2011 Intel Corporation - * Copyright © 2012-2013 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 -#include -#include -#include "wayland-util.h" - -extern const struct wl_interface wl_buffer_interface; -extern const struct wl_interface wl_callback_interface; -extern const struct wl_interface wl_data_device_interface; -extern const struct wl_interface wl_data_offer_interface; -extern const struct wl_interface wl_data_source_interface; -extern const struct wl_interface wl_keyboard_interface; -extern const struct wl_interface wl_output_interface; -extern const struct wl_interface wl_pointer_interface; -extern const struct wl_interface wl_region_interface; -extern const struct wl_interface wl_registry_interface; -extern const struct wl_interface wl_seat_interface; -extern const struct wl_interface wl_shell_surface_interface; -extern const struct wl_interface wl_shm_pool_interface; -extern const struct wl_interface wl_subsurface_interface; -extern const struct wl_interface wl_surface_interface; -extern const struct wl_interface wl_touch_interface; - -static const struct wl_interface *wayland_types[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - &wl_callback_interface, - &wl_registry_interface, - &wl_surface_interface, - &wl_region_interface, - &wl_buffer_interface, - NULL, - NULL, - NULL, - NULL, - NULL, - &wl_shm_pool_interface, - NULL, - NULL, - &wl_data_source_interface, - &wl_surface_interface, - &wl_surface_interface, - NULL, - &wl_data_source_interface, - NULL, - &wl_data_offer_interface, - NULL, - &wl_surface_interface, - NULL, - NULL, - &wl_data_offer_interface, - &wl_data_offer_interface, - &wl_data_source_interface, - &wl_data_device_interface, - &wl_seat_interface, - &wl_shell_surface_interface, - &wl_surface_interface, - &wl_seat_interface, - NULL, - &wl_seat_interface, - NULL, - NULL, - &wl_surface_interface, - NULL, - NULL, - NULL, - NULL, - NULL, - &wl_output_interface, - &wl_seat_interface, - NULL, - &wl_surface_interface, - NULL, - NULL, - NULL, - &wl_output_interface, - &wl_buffer_interface, - NULL, - NULL, - &wl_callback_interface, - &wl_region_interface, - &wl_region_interface, - &wl_output_interface, - &wl_output_interface, - &wl_pointer_interface, - &wl_keyboard_interface, - &wl_touch_interface, - NULL, - &wl_surface_interface, - NULL, - NULL, - NULL, - &wl_surface_interface, - NULL, - NULL, - NULL, - &wl_surface_interface, - NULL, - &wl_surface_interface, - NULL, - NULL, - &wl_surface_interface, - NULL, - NULL, - &wl_surface_interface, - NULL, - NULL, - NULL, - &wl_subsurface_interface, - &wl_surface_interface, - &wl_surface_interface, - &wl_surface_interface, - &wl_surface_interface, -}; - -static const struct wl_message wl_display_requests[] = { - { "sync", "n", wayland_types + 8 }, - { "get_registry", "n", wayland_types + 9 }, -}; - -static const struct wl_message wl_display_events[] = { - { "error", "ous", wayland_types + 0 }, - { "delete_id", "u", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_display_interface = { - "wl_display", 1, - 2, wl_display_requests, - 2, wl_display_events, -}; - -static const struct wl_message wl_registry_requests[] = { - { "bind", "usun", wayland_types + 0 }, -}; - -static const struct wl_message wl_registry_events[] = { - { "global", "usu", wayland_types + 0 }, - { "global_remove", "u", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_registry_interface = { - "wl_registry", 1, - 1, wl_registry_requests, - 2, wl_registry_events, -}; - -static const struct wl_message wl_callback_events[] = { - { "done", "u", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_callback_interface = { - "wl_callback", 1, - 0, NULL, - 1, wl_callback_events, -}; - -static const struct wl_message wl_compositor_requests[] = { - { "create_surface", "n", wayland_types + 10 }, - { "create_region", "n", wayland_types + 11 }, -}; - -WL_EXPORT const struct wl_interface wl_compositor_interface = { - "wl_compositor", 4, - 2, wl_compositor_requests, - 0, NULL, -}; - -static const struct wl_message wl_shm_pool_requests[] = { - { "create_buffer", "niiiiu", wayland_types + 12 }, - { "destroy", "", wayland_types + 0 }, - { "resize", "i", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_shm_pool_interface = { - "wl_shm_pool", 1, - 3, wl_shm_pool_requests, - 0, NULL, -}; - -static const struct wl_message wl_shm_requests[] = { - { "create_pool", "nhi", wayland_types + 18 }, -}; - -static const struct wl_message wl_shm_events[] = { - { "format", "u", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_shm_interface = { - "wl_shm", 1, - 1, wl_shm_requests, - 1, wl_shm_events, -}; - -static const struct wl_message wl_buffer_requests[] = { - { "destroy", "", wayland_types + 0 }, -}; - -static const struct wl_message wl_buffer_events[] = { - { "release", "", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_buffer_interface = { - "wl_buffer", 1, - 1, wl_buffer_requests, - 1, wl_buffer_events, -}; - -static const struct wl_message wl_data_offer_requests[] = { - { "accept", "u?s", wayland_types + 0 }, - { "receive", "sh", wayland_types + 0 }, - { "destroy", "", wayland_types + 0 }, - { "finish", "3", wayland_types + 0 }, - { "set_actions", "3uu", wayland_types + 0 }, -}; - -static const struct wl_message wl_data_offer_events[] = { - { "offer", "s", wayland_types + 0 }, - { "source_actions", "3u", wayland_types + 0 }, - { "action", "3u", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_data_offer_interface = { - "wl_data_offer", 3, - 5, wl_data_offer_requests, - 3, wl_data_offer_events, -}; - -static const struct wl_message wl_data_source_requests[] = { - { "offer", "s", wayland_types + 0 }, - { "destroy", "", wayland_types + 0 }, - { "set_actions", "3u", wayland_types + 0 }, -}; - -static const struct wl_message wl_data_source_events[] = { - { "target", "?s", wayland_types + 0 }, - { "send", "sh", wayland_types + 0 }, - { "cancelled", "", wayland_types + 0 }, - { "dnd_drop_performed", "3", wayland_types + 0 }, - { "dnd_finished", "3", wayland_types + 0 }, - { "action", "3u", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_data_source_interface = { - "wl_data_source", 3, - 3, wl_data_source_requests, - 6, wl_data_source_events, -}; - -static const struct wl_message wl_data_device_requests[] = { - { "start_drag", "?oo?ou", wayland_types + 21 }, - { "set_selection", "?ou", wayland_types + 25 }, - { "release", "2", wayland_types + 0 }, -}; - -static const struct wl_message wl_data_device_events[] = { - { "data_offer", "n", wayland_types + 27 }, - { "enter", "uoff?o", wayland_types + 28 }, - { "leave", "", wayland_types + 0 }, - { "motion", "uff", wayland_types + 0 }, - { "drop", "", wayland_types + 0 }, - { "selection", "?o", wayland_types + 33 }, -}; - -WL_EXPORT const struct wl_interface wl_data_device_interface = { - "wl_data_device", 3, - 3, wl_data_device_requests, - 6, wl_data_device_events, -}; - -static const struct wl_message wl_data_device_manager_requests[] = { - { "create_data_source", "n", wayland_types + 34 }, - { "get_data_device", "no", wayland_types + 35 }, -}; - -WL_EXPORT const struct wl_interface wl_data_device_manager_interface = { - "wl_data_device_manager", 3, - 2, wl_data_device_manager_requests, - 0, NULL, -}; - -static const struct wl_message wl_shell_requests[] = { - { "get_shell_surface", "no", wayland_types + 37 }, -}; - -WL_EXPORT const struct wl_interface wl_shell_interface = { - "wl_shell", 1, - 1, wl_shell_requests, - 0, NULL, -}; - -static const struct wl_message wl_shell_surface_requests[] = { - { "pong", "u", wayland_types + 0 }, - { "move", "ou", wayland_types + 39 }, - { "resize", "ouu", wayland_types + 41 }, - { "set_toplevel", "", wayland_types + 0 }, - { "set_transient", "oiiu", wayland_types + 44 }, - { "set_fullscreen", "uu?o", wayland_types + 48 }, - { "set_popup", "ouoiiu", wayland_types + 51 }, - { "set_maximized", "?o", wayland_types + 57 }, - { "set_title", "s", wayland_types + 0 }, - { "set_class", "s", wayland_types + 0 }, -}; - -static const struct wl_message wl_shell_surface_events[] = { - { "ping", "u", wayland_types + 0 }, - { "configure", "uii", wayland_types + 0 }, - { "popup_done", "", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_shell_surface_interface = { - "wl_shell_surface", 1, - 10, wl_shell_surface_requests, - 3, wl_shell_surface_events, -}; - -static const struct wl_message wl_surface_requests[] = { - { "destroy", "", wayland_types + 0 }, - { "attach", "?oii", wayland_types + 58 }, - { "damage", "iiii", wayland_types + 0 }, - { "frame", "n", wayland_types + 61 }, - { "set_opaque_region", "?o", wayland_types + 62 }, - { "set_input_region", "?o", wayland_types + 63 }, - { "commit", "", wayland_types + 0 }, - { "set_buffer_transform", "2i", wayland_types + 0 }, - { "set_buffer_scale", "3i", wayland_types + 0 }, - { "damage_buffer", "4iiii", wayland_types + 0 }, -}; - -static const struct wl_message wl_surface_events[] = { - { "enter", "o", wayland_types + 64 }, - { "leave", "o", wayland_types + 65 }, -}; - -WL_EXPORT const struct wl_interface wl_surface_interface = { - "wl_surface", 4, - 10, wl_surface_requests, - 2, wl_surface_events, -}; - -static const struct wl_message wl_seat_requests[] = { - { "get_pointer", "n", wayland_types + 66 }, - { "get_keyboard", "n", wayland_types + 67 }, - { "get_touch", "n", wayland_types + 68 }, - { "release", "5", wayland_types + 0 }, -}; - -static const struct wl_message wl_seat_events[] = { - { "capabilities", "u", wayland_types + 0 }, - { "name", "2s", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_seat_interface = { - "wl_seat", 6, - 4, wl_seat_requests, - 2, wl_seat_events, -}; - -static const struct wl_message wl_pointer_requests[] = { - { "set_cursor", "u?oii", wayland_types + 69 }, - { "release", "3", wayland_types + 0 }, -}; - -static const struct wl_message wl_pointer_events[] = { - { "enter", "uoff", wayland_types + 73 }, - { "leave", "uo", wayland_types + 77 }, - { "motion", "uff", wayland_types + 0 }, - { "button", "uuuu", wayland_types + 0 }, - { "axis", "uuf", wayland_types + 0 }, - { "frame", "5", wayland_types + 0 }, - { "axis_source", "5u", wayland_types + 0 }, - { "axis_stop", "5uu", wayland_types + 0 }, - { "axis_discrete", "5ui", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_pointer_interface = { - "wl_pointer", 6, - 2, wl_pointer_requests, - 9, wl_pointer_events, -}; - -static const struct wl_message wl_keyboard_requests[] = { - { "release", "3", wayland_types + 0 }, -}; - -static const struct wl_message wl_keyboard_events[] = { - { "keymap", "uhu", wayland_types + 0 }, - { "enter", "uoa", wayland_types + 79 }, - { "leave", "uo", wayland_types + 82 }, - { "key", "uuuu", wayland_types + 0 }, - { "modifiers", "uuuuu", wayland_types + 0 }, - { "repeat_info", "4ii", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_keyboard_interface = { - "wl_keyboard", 6, - 1, wl_keyboard_requests, - 6, wl_keyboard_events, -}; - -static const struct wl_message wl_touch_requests[] = { - { "release", "3", wayland_types + 0 }, -}; - -static const struct wl_message wl_touch_events[] = { - { "down", "uuoiff", wayland_types + 84 }, - { "up", "uui", wayland_types + 0 }, - { "motion", "uiff", wayland_types + 0 }, - { "frame", "", wayland_types + 0 }, - { "cancel", "", wayland_types + 0 }, - { "shape", "6iff", wayland_types + 0 }, - { "orientation", "6if", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_touch_interface = { - "wl_touch", 6, - 1, wl_touch_requests, - 7, wl_touch_events, -}; - -static const struct wl_message wl_output_requests[] = { - { "release", "3", wayland_types + 0 }, -}; - -static const struct wl_message wl_output_events[] = { - { "geometry", "iiiiissi", wayland_types + 0 }, - { "mode", "uiii", wayland_types + 0 }, - { "done", "2", wayland_types + 0 }, - { "scale", "2i", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_output_interface = { - "wl_output", 3, - 1, wl_output_requests, - 4, wl_output_events, -}; - -static const struct wl_message wl_region_requests[] = { - { "destroy", "", wayland_types + 0 }, - { "add", "iiii", wayland_types + 0 }, - { "subtract", "iiii", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_region_interface = { - "wl_region", 1, - 3, wl_region_requests, - 0, NULL, -}; - -static const struct wl_message wl_subcompositor_requests[] = { - { "destroy", "", wayland_types + 0 }, - { "get_subsurface", "noo", wayland_types + 90 }, -}; - -WL_EXPORT const struct wl_interface wl_subcompositor_interface = { - "wl_subcompositor", 1, - 2, wl_subcompositor_requests, - 0, NULL, -}; - -static const struct wl_message wl_subsurface_requests[] = { - { "destroy", "", wayland_types + 0 }, - { "set_position", "ii", wayland_types + 0 }, - { "place_above", "o", wayland_types + 93 }, - { "place_below", "o", wayland_types + 94 }, - { "set_sync", "", wayland_types + 0 }, - { "set_desync", "", wayland_types + 0 }, -}; - -WL_EXPORT const struct wl_interface wl_subsurface_interface = { - "wl_subsurface", 1, - 6, wl_subsurface_requests, - 0, NULL, -}; - diff --git a/tests/data/example-enum.h b/tests/data/example-enum.h deleted file mode 100644 index 9aec4035..00000000 --- a/tests/data/example-enum.h +++ /dev/null @@ -1,836 +0,0 @@ -/* SCANNER TEST */ - -#ifndef WAYLAND_ENUM_PROTOCOL_H -#define WAYLAND_ENUM_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef WL_DISPLAY_ERROR_ENUM -#define WL_DISPLAY_ERROR_ENUM -/** - * @ingroup iface_wl_display - * global error values - * - * These errors are global and can be emitted in response to any - * server request. - */ -enum wl_display_error { - /** - * server couldn't find object - */ - WL_DISPLAY_ERROR_INVALID_OBJECT = 0, - /** - * method doesn't exist on the specified interface - */ - WL_DISPLAY_ERROR_INVALID_METHOD = 1, - /** - * server is out of memory - */ - WL_DISPLAY_ERROR_NO_MEMORY = 2, -}; -#endif /* WL_DISPLAY_ERROR_ENUM */ - -#ifndef WL_SHM_ERROR_ENUM -#define WL_SHM_ERROR_ENUM -/** - * @ingroup iface_wl_shm - * wl_shm error values - * - * These errors can be emitted in response to wl_shm requests. - */ -enum wl_shm_error { - /** - * buffer format is not known - */ - WL_SHM_ERROR_INVALID_FORMAT = 0, - /** - * invalid size or stride during pool or buffer creation - */ - WL_SHM_ERROR_INVALID_STRIDE = 1, - /** - * mmapping the file descriptor failed - */ - WL_SHM_ERROR_INVALID_FD = 2, -}; -#endif /* WL_SHM_ERROR_ENUM */ - -#ifndef WL_SHM_FORMAT_ENUM -#define WL_SHM_FORMAT_ENUM -/** - * @ingroup iface_wl_shm - * pixel formats - * - * This describes the memory layout of an individual pixel. - * - * All renderers should support argb8888 and xrgb8888 but any other - * formats are optional and may not be supported by the particular - * renderer in use. - * - * The drm format codes match the macros defined in drm_fourcc.h. - * The formats actually supported by the compositor will be - * reported by the format event. - */ -enum wl_shm_format { - /** - * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian - */ - WL_SHM_FORMAT_ARGB8888 = 0, - /** - * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian - */ - WL_SHM_FORMAT_XRGB8888 = 1, - /** - * 8-bit color index format, [7:0] C - */ - WL_SHM_FORMAT_C8 = 0x20203843, - /** - * 8-bit RGB format, [7:0] R:G:B 3:3:2 - */ - WL_SHM_FORMAT_RGB332 = 0x38424752, - /** - * 8-bit BGR format, [7:0] B:G:R 2:3:3 - */ - WL_SHM_FORMAT_BGR233 = 0x38524742, - /** - * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian - */ - WL_SHM_FORMAT_XRGB4444 = 0x32315258, - /** - * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian - */ - WL_SHM_FORMAT_XBGR4444 = 0x32314258, - /** - * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian - */ - WL_SHM_FORMAT_RGBX4444 = 0x32315852, - /** - * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian - */ - WL_SHM_FORMAT_BGRX4444 = 0x32315842, - /** - * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian - */ - WL_SHM_FORMAT_ARGB4444 = 0x32315241, - /** - * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian - */ - WL_SHM_FORMAT_ABGR4444 = 0x32314241, - /** - * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian - */ - WL_SHM_FORMAT_RGBA4444 = 0x32314152, - /** - * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian - */ - WL_SHM_FORMAT_BGRA4444 = 0x32314142, - /** - * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian - */ - WL_SHM_FORMAT_XRGB1555 = 0x35315258, - /** - * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian - */ - WL_SHM_FORMAT_XBGR1555 = 0x35314258, - /** - * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian - */ - WL_SHM_FORMAT_RGBX5551 = 0x35315852, - /** - * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian - */ - WL_SHM_FORMAT_BGRX5551 = 0x35315842, - /** - * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian - */ - WL_SHM_FORMAT_ARGB1555 = 0x35315241, - /** - * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian - */ - WL_SHM_FORMAT_ABGR1555 = 0x35314241, - /** - * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian - */ - WL_SHM_FORMAT_RGBA5551 = 0x35314152, - /** - * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian - */ - WL_SHM_FORMAT_BGRA5551 = 0x35314142, - /** - * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian - */ - WL_SHM_FORMAT_RGB565 = 0x36314752, - /** - * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian - */ - WL_SHM_FORMAT_BGR565 = 0x36314742, - /** - * 24-bit RGB format, [23:0] R:G:B little endian - */ - WL_SHM_FORMAT_RGB888 = 0x34324752, - /** - * 24-bit BGR format, [23:0] B:G:R little endian - */ - WL_SHM_FORMAT_BGR888 = 0x34324742, - /** - * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian - */ - WL_SHM_FORMAT_XBGR8888 = 0x34324258, - /** - * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian - */ - WL_SHM_FORMAT_RGBX8888 = 0x34325852, - /** - * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian - */ - WL_SHM_FORMAT_BGRX8888 = 0x34325842, - /** - * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian - */ - WL_SHM_FORMAT_ABGR8888 = 0x34324241, - /** - * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian - */ - WL_SHM_FORMAT_RGBA8888 = 0x34324152, - /** - * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian - */ - WL_SHM_FORMAT_BGRA8888 = 0x34324142, - /** - * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian - */ - WL_SHM_FORMAT_XRGB2101010 = 0x30335258, - /** - * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian - */ - WL_SHM_FORMAT_XBGR2101010 = 0x30334258, - /** - * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian - */ - WL_SHM_FORMAT_RGBX1010102 = 0x30335852, - /** - * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian - */ - WL_SHM_FORMAT_BGRX1010102 = 0x30335842, - /** - * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian - */ - WL_SHM_FORMAT_ARGB2101010 = 0x30335241, - /** - * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian - */ - WL_SHM_FORMAT_ABGR2101010 = 0x30334241, - /** - * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian - */ - WL_SHM_FORMAT_RGBA1010102 = 0x30334152, - /** - * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian - */ - WL_SHM_FORMAT_BGRA1010102 = 0x30334142, - /** - * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_YUYV = 0x56595559, - /** - * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_YVYU = 0x55595659, - /** - * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_UYVY = 0x59565955, - /** - * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_VYUY = 0x59555956, - /** - * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian - */ - WL_SHM_FORMAT_AYUV = 0x56555941, - /** - * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane - */ - WL_SHM_FORMAT_NV12 = 0x3231564e, - /** - * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane - */ - WL_SHM_FORMAT_NV21 = 0x3132564e, - /** - * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane - */ - WL_SHM_FORMAT_NV16 = 0x3631564e, - /** - * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane - */ - WL_SHM_FORMAT_NV61 = 0x3136564e, - /** - * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV410 = 0x39565559, - /** - * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU410 = 0x39555659, - /** - * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV411 = 0x31315559, - /** - * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU411 = 0x31315659, - /** - * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV420 = 0x32315559, - /** - * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU420 = 0x32315659, - /** - * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV422 = 0x36315559, - /** - * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU422 = 0x36315659, - /** - * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV444 = 0x34325559, - /** - * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU444 = 0x34325659, -}; -#endif /* WL_SHM_FORMAT_ENUM */ - -#ifndef WL_DATA_OFFER_ERROR_ENUM -#define WL_DATA_OFFER_ERROR_ENUM -enum wl_data_offer_error { - /** - * finish request was called untimely - */ - WL_DATA_OFFER_ERROR_INVALID_FINISH = 0, - /** - * action mask contains invalid values - */ - WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1, - /** - * action argument has an invalid value - */ - WL_DATA_OFFER_ERROR_INVALID_ACTION = 2, - /** - * offer doesn't accept this request - */ - WL_DATA_OFFER_ERROR_INVALID_OFFER = 3, -}; -#endif /* WL_DATA_OFFER_ERROR_ENUM */ - -#ifndef WL_DATA_SOURCE_ERROR_ENUM -#define WL_DATA_SOURCE_ERROR_ENUM -enum wl_data_source_error { - /** - * action mask contains invalid values - */ - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0, - /** - * source doesn't accept this request - */ - WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1, -}; -#endif /* WL_DATA_SOURCE_ERROR_ENUM */ - -#ifndef WL_DATA_DEVICE_ERROR_ENUM -#define WL_DATA_DEVICE_ERROR_ENUM -enum wl_data_device_error { - /** - * given wl_surface has another role - */ - WL_DATA_DEVICE_ERROR_ROLE = 0, -}; -#endif /* WL_DATA_DEVICE_ERROR_ENUM */ - -#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM -#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM -/** - * @ingroup iface_wl_data_device_manager - * drag and drop actions - * - * This is a bitmask of the available/preferred actions in a - * drag-and-drop operation. - * - * In the compositor, the selected action is a result of matching the - * actions offered by the source and destination sides. "action" events - * with a "none" action will be sent to both source and destination if - * there is no match. All further checks will effectively happen on - * (source actions ∩ destination actions). - * - * In addition, compositors may also pick different actions in - * reaction to key modifiers being pressed. One common design that - * is used in major toolkits (and the behavior recommended for - * compositors) is: - * - * - If no modifiers are pressed, the first match (in bit order) - * will be used. - * - Pressing Shift selects "move", if enabled in the mask. - * - Pressing Control selects "copy", if enabled in the mask. - * - * Behavior beyond that is considered implementation-dependent. - * Compositors may for example bind other modifiers (like Alt/Meta) - * or drags initiated with other buttons than BTN_LEFT to specific - * actions (e.g. "ask"). - */ -enum wl_data_device_manager_dnd_action { - /** - * no action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0, - /** - * copy action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1, - /** - * move action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2, - /** - * ask action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4, -}; -#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */ - -#ifndef WL_SHELL_ERROR_ENUM -#define WL_SHELL_ERROR_ENUM -enum wl_shell_error { - /** - * given wl_surface has another role - */ - WL_SHELL_ERROR_ROLE = 0, -}; -#endif /* WL_SHELL_ERROR_ENUM */ - -#ifndef WL_SHELL_SURFACE_RESIZE_ENUM -#define WL_SHELL_SURFACE_RESIZE_ENUM -/** - * @ingroup iface_wl_shell_surface - * edge values for resizing - * - * These values are used to indicate which edge of a surface - * is being dragged in a resize operation. The server may - * use this information to adapt its behavior, e.g. choose - * an appropriate cursor image. - */ -enum wl_shell_surface_resize { - /** - * no edge - */ - WL_SHELL_SURFACE_RESIZE_NONE = 0, - /** - * top edge - */ - WL_SHELL_SURFACE_RESIZE_TOP = 1, - /** - * bottom edge - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM = 2, - /** - * left edge - */ - WL_SHELL_SURFACE_RESIZE_LEFT = 4, - /** - * top and left edges - */ - WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5, - /** - * bottom and left edges - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6, - /** - * right edge - */ - WL_SHELL_SURFACE_RESIZE_RIGHT = 8, - /** - * top and right edges - */ - WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9, - /** - * bottom and right edges - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10, -}; -#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */ - -#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM -#define WL_SHELL_SURFACE_TRANSIENT_ENUM -/** - * @ingroup iface_wl_shell_surface - * details of transient behaviour - * - * These flags specify details of the expected behaviour - * of transient surfaces. Used in the set_transient request. - */ -enum wl_shell_surface_transient { - /** - * do not set keyboard focus - */ - WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1, -}; -#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */ - -#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM -#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM -/** - * @ingroup iface_wl_shell_surface - * different method to set the surface fullscreen - * - * Hints to indicate to the compositor how to deal with a conflict - * between the dimensions of the surface and the dimensions of the - * output. The compositor is free to ignore this parameter. - */ -enum wl_shell_surface_fullscreen_method { - /** - * no preference, apply default policy - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0, - /** - * scale, preserve the surface's aspect ratio and center on output - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1, - /** - * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2, - /** - * no upscaling, center on output and add black borders to compensate size mismatch - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3, -}; -#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */ - -#ifndef WL_SURFACE_ERROR_ENUM -#define WL_SURFACE_ERROR_ENUM -/** - * @ingroup iface_wl_surface - * wl_surface error values - * - * These errors can be emitted in response to wl_surface requests. - */ -enum wl_surface_error { - /** - * buffer scale value is invalid - */ - WL_SURFACE_ERROR_INVALID_SCALE = 0, - /** - * buffer transform value is invalid - */ - WL_SURFACE_ERROR_INVALID_TRANSFORM = 1, -}; -#endif /* WL_SURFACE_ERROR_ENUM */ - -#ifndef WL_SEAT_CAPABILITY_ENUM -#define WL_SEAT_CAPABILITY_ENUM -/** - * @ingroup iface_wl_seat - * seat capability bitmask - * - * This is a bitmask of capabilities this seat has; if a member is - * set, then it is present on the seat. - */ -enum wl_seat_capability { - /** - * the seat has pointer devices - */ - WL_SEAT_CAPABILITY_POINTER = 1, - /** - * the seat has one or more keyboards - */ - WL_SEAT_CAPABILITY_KEYBOARD = 2, - /** - * the seat has touch devices - */ - WL_SEAT_CAPABILITY_TOUCH = 4, -}; -#endif /* WL_SEAT_CAPABILITY_ENUM */ - -#ifndef WL_POINTER_ERROR_ENUM -#define WL_POINTER_ERROR_ENUM -enum wl_pointer_error { - /** - * given wl_surface has another role - */ - WL_POINTER_ERROR_ROLE = 0, -}; -#endif /* WL_POINTER_ERROR_ENUM */ - -#ifndef WL_POINTER_BUTTON_STATE_ENUM -#define WL_POINTER_BUTTON_STATE_ENUM -/** - * @ingroup iface_wl_pointer - * physical button state - * - * Describes the physical state of a button that produced the button - * event. - */ -enum wl_pointer_button_state { - /** - * the button is not pressed - */ - WL_POINTER_BUTTON_STATE_RELEASED = 0, - /** - * the button is pressed - */ - WL_POINTER_BUTTON_STATE_PRESSED = 1, -}; -#endif /* WL_POINTER_BUTTON_STATE_ENUM */ - -#ifndef WL_POINTER_AXIS_ENUM -#define WL_POINTER_AXIS_ENUM -/** - * @ingroup iface_wl_pointer - * axis types - * - * Describes the axis types of scroll events. - */ -enum wl_pointer_axis { - /** - * vertical axis - */ - WL_POINTER_AXIS_VERTICAL_SCROLL = 0, - /** - * horizontal axis - */ - WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1, -}; -#endif /* WL_POINTER_AXIS_ENUM */ - -#ifndef WL_POINTER_AXIS_SOURCE_ENUM -#define WL_POINTER_AXIS_SOURCE_ENUM -/** - * @ingroup iface_wl_pointer - * axis source types - * - * Describes the source types for axis events. This indicates to the - * client how an axis event was physically generated; a client may - * adjust the user interface accordingly. For example, scroll events - * from a "finger" source may be in a smooth coordinate space with - * kinetic scrolling whereas a "wheel" source may be in discrete steps - * of a number of lines. - */ -enum wl_pointer_axis_source { - /** - * a physical wheel rotation - */ - WL_POINTER_AXIS_SOURCE_WHEEL = 0, - /** - * finger on a touch surface - */ - WL_POINTER_AXIS_SOURCE_FINGER = 1, - /** - * continuous coordinate space - * - * A device generating events in a continuous coordinate space, - * but using something other than a finger. One example for this - * source is button-based scrolling where the vertical motion of a - * device is converted to scroll events while a button is held - * down. - */ - WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2, - /** - * a physical wheel tilt - * - * Indicates that the actual device is a wheel but the scroll - * event is not caused by a rotation but a (usually sideways) tilt - * of the wheel. - * @since 6 - */ - WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3, -}; -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6 -#endif /* WL_POINTER_AXIS_SOURCE_ENUM */ - -#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM -#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM -/** - * @ingroup iface_wl_keyboard - * keyboard mapping format - * - * This specifies the format of the keymap provided to the - * client with the wl_keyboard.keymap event. - */ -enum wl_keyboard_keymap_format { - /** - * no keymap; client must understand how to interpret the raw keycode - */ - WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0, - /** - * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode - */ - WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1, -}; -#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */ - -#ifndef WL_KEYBOARD_KEY_STATE_ENUM -#define WL_KEYBOARD_KEY_STATE_ENUM -/** - * @ingroup iface_wl_keyboard - * physical key state - * - * Describes the physical state of a key that produced the key event. - */ -enum wl_keyboard_key_state { - /** - * key is not pressed - */ - WL_KEYBOARD_KEY_STATE_RELEASED = 0, - /** - * key is pressed - */ - WL_KEYBOARD_KEY_STATE_PRESSED = 1, -}; -#endif /* WL_KEYBOARD_KEY_STATE_ENUM */ - -#ifndef WL_OUTPUT_SUBPIXEL_ENUM -#define WL_OUTPUT_SUBPIXEL_ENUM -/** - * @ingroup iface_wl_output - * subpixel geometry information - * - * This enumeration describes how the physical - * pixels on an output are laid out. - */ -enum wl_output_subpixel { - /** - * unknown geometry - */ - WL_OUTPUT_SUBPIXEL_UNKNOWN = 0, - /** - * no geometry - */ - WL_OUTPUT_SUBPIXEL_NONE = 1, - /** - * horizontal RGB - */ - WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2, - /** - * horizontal BGR - */ - WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3, - /** - * vertical RGB - */ - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4, - /** - * vertical BGR - */ - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5, -}; -#endif /* WL_OUTPUT_SUBPIXEL_ENUM */ - -#ifndef WL_OUTPUT_TRANSFORM_ENUM -#define WL_OUTPUT_TRANSFORM_ENUM -/** - * @ingroup iface_wl_output - * transform from framebuffer to output - * - * This describes the transform that a compositor will apply to a - * surface to compensate for the rotation or mirroring of an - * output device. - * - * The flipped values correspond to an initial flip around a - * vertical axis followed by rotation. - * - * The purpose is mainly to allow clients to render accordingly and - * tell the compositor, so that for fullscreen surfaces, the - * compositor will still be able to scan out directly from client - * surfaces. - */ -enum wl_output_transform { - /** - * no transform - */ - WL_OUTPUT_TRANSFORM_NORMAL = 0, - /** - * 90 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_90 = 1, - /** - * 180 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_180 = 2, - /** - * 270 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_270 = 3, - /** - * 180 degree flip around a vertical axis - */ - WL_OUTPUT_TRANSFORM_FLIPPED = 4, - /** - * flip and rotate 90 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5, - /** - * flip and rotate 180 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6, - /** - * flip and rotate 270 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7, -}; -#endif /* WL_OUTPUT_TRANSFORM_ENUM */ - -#ifndef WL_OUTPUT_MODE_ENUM -#define WL_OUTPUT_MODE_ENUM -/** - * @ingroup iface_wl_output - * mode information - * - * These flags describe properties of an output mode. - * They are used in the flags bitfield of the mode event. - */ -enum wl_output_mode { - /** - * indicates this is the current mode - */ - WL_OUTPUT_MODE_CURRENT = 0x1, - /** - * indicates this is the preferred mode - */ - WL_OUTPUT_MODE_PREFERRED = 0x2, -}; -#endif /* WL_OUTPUT_MODE_ENUM */ - -#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM -#define WL_SUBCOMPOSITOR_ERROR_ENUM -enum wl_subcompositor_error { - /** - * the to-be sub-surface is invalid - */ - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0, -}; -#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */ - -#ifndef WL_SUBSURFACE_ERROR_ENUM -#define WL_SUBSURFACE_ERROR_ENUM -enum wl_subsurface_error { - /** - * wl_surface is not a sibling or the parent - */ - WL_SUBSURFACE_ERROR_BAD_SURFACE = 0, -}; -#endif /* WL_SUBSURFACE_ERROR_ENUM */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/example-server.h b/tests/data/example-server.h deleted file mode 100644 index 0ddc73db..00000000 --- a/tests/data/example-server.h +++ /dev/null @@ -1,5075 +0,0 @@ -/* SCANNER TEST */ - -#ifndef WAYLAND_SERVER_PROTOCOL_H -#define WAYLAND_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_wayland The wayland protocol - * @section page_ifaces_wayland Interfaces - * - @subpage page_iface_wl_display - core global object - * - @subpage page_iface_wl_registry - global registry object - * - @subpage page_iface_wl_callback - callback object - * - @subpage page_iface_wl_compositor - the compositor singleton - * - @subpage page_iface_wl_shm_pool - a shared memory pool - * - @subpage page_iface_wl_shm - shared memory support - * - @subpage page_iface_wl_buffer - content for a wl_surface - * - @subpage page_iface_wl_data_offer - offer to transfer data - * - @subpage page_iface_wl_data_source - offer to transfer data - * - @subpage page_iface_wl_data_device - data transfer device - * - @subpage page_iface_wl_data_device_manager - data transfer interface - * - @subpage page_iface_wl_shell - create desktop-style surfaces - * - @subpage page_iface_wl_shell_surface - desktop-style metadata interface - * - @subpage page_iface_wl_surface - an onscreen surface - * - @subpage page_iface_wl_seat - group of input devices - * - @subpage page_iface_wl_pointer - pointer input device - * - @subpage page_iface_wl_keyboard - keyboard input device - * - @subpage page_iface_wl_touch - touchscreen input device - * - @subpage page_iface_wl_output - compositor output region - * - @subpage page_iface_wl_region - region interface - * - @subpage page_iface_wl_subcompositor - sub-surface compositing - * - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface - * @section page_copyright_wayland Copyright - *
- *
- * Copyright © 2008-2011 Kristian Høgsberg
- * Copyright © 2010-2011 Intel Corporation
- * Copyright © 2012-2013 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.
- * 
- */ -struct wl_buffer; -struct wl_callback; -struct wl_compositor; -struct wl_data_device; -struct wl_data_device_manager; -struct wl_data_offer; -struct wl_data_source; -struct wl_display; -struct wl_keyboard; -struct wl_output; -struct wl_pointer; -struct wl_region; -struct wl_registry; -struct wl_seat; -struct wl_shell; -struct wl_shell_surface; -struct wl_shm; -struct wl_shm_pool; -struct wl_subcompositor; -struct wl_subsurface; -struct wl_surface; -struct wl_touch; - -#ifndef WL_DISPLAY_INTERFACE -#define WL_DISPLAY_INTERFACE -/** - * @page page_iface_wl_display wl_display - * @section page_iface_wl_display_desc Description - * - * The core global object. This is a special singleton object. It - * is used for internal Wayland protocol features. - * @section page_iface_wl_display_api API - * See @ref iface_wl_display. - */ -/** - * @defgroup iface_wl_display The wl_display interface - * - * The core global object. This is a special singleton object. It - * is used for internal Wayland protocol features. - */ -extern const struct wl_interface wl_display_interface; -#endif -#ifndef WL_REGISTRY_INTERFACE -#define WL_REGISTRY_INTERFACE -/** - * @page page_iface_wl_registry wl_registry - * @section page_iface_wl_registry_desc Description - * - * The singleton global registry object. The server has a number of - * global objects that are available to all clients. These objects - * typically represent an actual object in the server (for example, - * an input device) or they are singleton objects that provide - * extension functionality. - * - * When a client creates a registry object, the registry object - * will emit a global event for each global currently in the - * registry. Globals come and go as a result of device or - * monitor hotplugs, reconfiguration or other events, and the - * registry will send out global and global_remove events to - * keep the client up to date with the changes. To mark the end - * of the initial burst of events, the client can use the - * wl_display.sync request immediately after calling - * wl_display.get_registry. - * - * A client can bind to a global object by using the bind - * request. This creates a client-side handle that lets the object - * emit events to the client and lets the client invoke requests on - * the object. - * @section page_iface_wl_registry_api API - * See @ref iface_wl_registry. - */ -/** - * @defgroup iface_wl_registry The wl_registry interface - * - * The singleton global registry object. The server has a number of - * global objects that are available to all clients. These objects - * typically represent an actual object in the server (for example, - * an input device) or they are singleton objects that provide - * extension functionality. - * - * When a client creates a registry object, the registry object - * will emit a global event for each global currently in the - * registry. Globals come and go as a result of device or - * monitor hotplugs, reconfiguration or other events, and the - * registry will send out global and global_remove events to - * keep the client up to date with the changes. To mark the end - * of the initial burst of events, the client can use the - * wl_display.sync request immediately after calling - * wl_display.get_registry. - * - * A client can bind to a global object by using the bind - * request. This creates a client-side handle that lets the object - * emit events to the client and lets the client invoke requests on - * the object. - */ -extern const struct wl_interface wl_registry_interface; -#endif -#ifndef WL_CALLBACK_INTERFACE -#define WL_CALLBACK_INTERFACE -/** - * @page page_iface_wl_callback wl_callback - * @section page_iface_wl_callback_desc Description - * - * Clients can handle the 'done' event to get notified when - * the related request is done. - * @section page_iface_wl_callback_api API - * See @ref iface_wl_callback. - */ -/** - * @defgroup iface_wl_callback The wl_callback interface - * - * Clients can handle the 'done' event to get notified when - * the related request is done. - */ -extern const struct wl_interface wl_callback_interface; -#endif -#ifndef WL_COMPOSITOR_INTERFACE -#define WL_COMPOSITOR_INTERFACE -/** - * @page page_iface_wl_compositor wl_compositor - * @section page_iface_wl_compositor_desc Description - * - * A compositor. This object is a singleton global. The - * compositor is in charge of combining the contents of multiple - * surfaces into one displayable output. - * @section page_iface_wl_compositor_api API - * See @ref iface_wl_compositor. - */ -/** - * @defgroup iface_wl_compositor The wl_compositor interface - * - * A compositor. This object is a singleton global. The - * compositor is in charge of combining the contents of multiple - * surfaces into one displayable output. - */ -extern const struct wl_interface wl_compositor_interface; -#endif -#ifndef WL_SHM_POOL_INTERFACE -#define WL_SHM_POOL_INTERFACE -/** - * @page page_iface_wl_shm_pool wl_shm_pool - * @section page_iface_wl_shm_pool_desc Description - * - * The wl_shm_pool object encapsulates a piece of memory shared - * between the compositor and client. Through the wl_shm_pool - * object, the client can allocate shared memory wl_buffer objects. - * All objects created through the same pool share the same - * underlying mapped memory. Reusing the mapped memory avoids the - * setup/teardown overhead and is useful when interactively resizing - * a surface or for many small buffers. - * @section page_iface_wl_shm_pool_api API - * See @ref iface_wl_shm_pool. - */ -/** - * @defgroup iface_wl_shm_pool The wl_shm_pool interface - * - * The wl_shm_pool object encapsulates a piece of memory shared - * between the compositor and client. Through the wl_shm_pool - * object, the client can allocate shared memory wl_buffer objects. - * All objects created through the same pool share the same - * underlying mapped memory. Reusing the mapped memory avoids the - * setup/teardown overhead and is useful when interactively resizing - * a surface or for many small buffers. - */ -extern const struct wl_interface wl_shm_pool_interface; -#endif -#ifndef WL_SHM_INTERFACE -#define WL_SHM_INTERFACE -/** - * @page page_iface_wl_shm wl_shm - * @section page_iface_wl_shm_desc Description - * - * A singleton global object that provides support for shared - * memory. - * - * Clients can create wl_shm_pool objects using the create_pool - * request. - * - * At connection setup time, the wl_shm object emits one or more - * format events to inform clients about the valid pixel formats - * that can be used for buffers. - * @section page_iface_wl_shm_api API - * See @ref iface_wl_shm. - */ -/** - * @defgroup iface_wl_shm The wl_shm interface - * - * A singleton global object that provides support for shared - * memory. - * - * Clients can create wl_shm_pool objects using the create_pool - * request. - * - * At connection setup time, the wl_shm object emits one or more - * format events to inform clients about the valid pixel formats - * that can be used for buffers. - */ -extern const struct wl_interface wl_shm_interface; -#endif -#ifndef WL_BUFFER_INTERFACE -#define WL_BUFFER_INTERFACE -/** - * @page page_iface_wl_buffer wl_buffer - * @section page_iface_wl_buffer_desc Description - * - * A buffer provides the content for a wl_surface. Buffers are - * created through factory interfaces such as wl_drm, wl_shm or - * similar. It has a width and a height and can be attached to a - * wl_surface, but the mechanism by which a client provides and - * updates the contents is defined by the buffer factory interface. - * @section page_iface_wl_buffer_api API - * See @ref iface_wl_buffer. - */ -/** - * @defgroup iface_wl_buffer The wl_buffer interface - * - * A buffer provides the content for a wl_surface. Buffers are - * created through factory interfaces such as wl_drm, wl_shm or - * similar. It has a width and a height and can be attached to a - * wl_surface, but the mechanism by which a client provides and - * updates the contents is defined by the buffer factory interface. - */ -extern const struct wl_interface wl_buffer_interface; -#endif -#ifndef WL_DATA_OFFER_INTERFACE -#define WL_DATA_OFFER_INTERFACE -/** - * @page page_iface_wl_data_offer wl_data_offer - * @section page_iface_wl_data_offer_desc Description - * - * A wl_data_offer represents a piece of data offered for transfer - * by another client (the source client). It is used by the - * copy-and-paste and drag-and-drop mechanisms. The offer - * describes the different mime types that the data can be - * converted to and provides the mechanism for transferring the - * data directly from the source client. - * @section page_iface_wl_data_offer_api API - * See @ref iface_wl_data_offer. - */ -/** - * @defgroup iface_wl_data_offer The wl_data_offer interface - * - * A wl_data_offer represents a piece of data offered for transfer - * by another client (the source client). It is used by the - * copy-and-paste and drag-and-drop mechanisms. The offer - * describes the different mime types that the data can be - * converted to and provides the mechanism for transferring the - * data directly from the source client. - */ -extern const struct wl_interface wl_data_offer_interface; -#endif -#ifndef WL_DATA_SOURCE_INTERFACE -#define WL_DATA_SOURCE_INTERFACE -/** - * @page page_iface_wl_data_source wl_data_source - * @section page_iface_wl_data_source_desc Description - * - * The wl_data_source object is the source side of a wl_data_offer. - * It is created by the source client in a data transfer and - * provides a way to describe the offered data and a way to respond - * to requests to transfer the data. - * @section page_iface_wl_data_source_api API - * See @ref iface_wl_data_source. - */ -/** - * @defgroup iface_wl_data_source The wl_data_source interface - * - * The wl_data_source object is the source side of a wl_data_offer. - * It is created by the source client in a data transfer and - * provides a way to describe the offered data and a way to respond - * to requests to transfer the data. - */ -extern const struct wl_interface wl_data_source_interface; -#endif -#ifndef WL_DATA_DEVICE_INTERFACE -#define WL_DATA_DEVICE_INTERFACE -/** - * @page page_iface_wl_data_device wl_data_device - * @section page_iface_wl_data_device_desc Description - * - * There is one wl_data_device per seat which can be obtained - * from the global wl_data_device_manager singleton. - * - * A wl_data_device provides access to inter-client data transfer - * mechanisms such as copy-and-paste and drag-and-drop. - * @section page_iface_wl_data_device_api API - * See @ref iface_wl_data_device. - */ -/** - * @defgroup iface_wl_data_device The wl_data_device interface - * - * There is one wl_data_device per seat which can be obtained - * from the global wl_data_device_manager singleton. - * - * A wl_data_device provides access to inter-client data transfer - * mechanisms such as copy-and-paste and drag-and-drop. - */ -extern const struct wl_interface wl_data_device_interface; -#endif -#ifndef WL_DATA_DEVICE_MANAGER_INTERFACE -#define WL_DATA_DEVICE_MANAGER_INTERFACE -/** - * @page page_iface_wl_data_device_manager wl_data_device_manager - * @section page_iface_wl_data_device_manager_desc Description - * - * The wl_data_device_manager is a singleton global object that - * provides access to inter-client data transfer mechanisms such as - * copy-and-paste and drag-and-drop. These mechanisms are tied to - * a wl_seat and this interface lets a client get a wl_data_device - * corresponding to a wl_seat. - * - * Depending on the version bound, the objects created from the bound - * wl_data_device_manager object will have different requirements for - * functioning properly. See wl_data_source.set_actions, - * wl_data_offer.accept and wl_data_offer.finish for details. - * @section page_iface_wl_data_device_manager_api API - * See @ref iface_wl_data_device_manager. - */ -/** - * @defgroup iface_wl_data_device_manager The wl_data_device_manager interface - * - * The wl_data_device_manager is a singleton global object that - * provides access to inter-client data transfer mechanisms such as - * copy-and-paste and drag-and-drop. These mechanisms are tied to - * a wl_seat and this interface lets a client get a wl_data_device - * corresponding to a wl_seat. - * - * Depending on the version bound, the objects created from the bound - * wl_data_device_manager object will have different requirements for - * functioning properly. See wl_data_source.set_actions, - * wl_data_offer.accept and wl_data_offer.finish for details. - */ -extern const struct wl_interface wl_data_device_manager_interface; -#endif -#ifndef WL_SHELL_INTERFACE -#define WL_SHELL_INTERFACE -/** - * @page page_iface_wl_shell wl_shell - * @section page_iface_wl_shell_desc Description - * - * This interface is implemented by servers that provide - * desktop-style user interfaces. - * - * It allows clients to associate a wl_shell_surface with - * a basic surface. - * @section page_iface_wl_shell_api API - * See @ref iface_wl_shell. - */ -/** - * @defgroup iface_wl_shell The wl_shell interface - * - * This interface is implemented by servers that provide - * desktop-style user interfaces. - * - * It allows clients to associate a wl_shell_surface with - * a basic surface. - */ -extern const struct wl_interface wl_shell_interface; -#endif -#ifndef WL_SHELL_SURFACE_INTERFACE -#define WL_SHELL_SURFACE_INTERFACE -/** - * @page page_iface_wl_shell_surface wl_shell_surface - * @section page_iface_wl_shell_surface_desc Description - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides requests to treat surfaces like toplevel, fullscreen - * or popup windows, move, resize or maximize them, associate - * metadata like title and class, etc. - * - * On the server side the object is automatically destroyed when - * the related wl_surface is destroyed. On the client side, - * wl_shell_surface_destroy() must be called before destroying - * the wl_surface object. - * @section page_iface_wl_shell_surface_api API - * See @ref iface_wl_shell_surface. - */ -/** - * @defgroup iface_wl_shell_surface The wl_shell_surface interface - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides requests to treat surfaces like toplevel, fullscreen - * or popup windows, move, resize or maximize them, associate - * metadata like title and class, etc. - * - * On the server side the object is automatically destroyed when - * the related wl_surface is destroyed. On the client side, - * wl_shell_surface_destroy() must be called before destroying - * the wl_surface object. - */ -extern const struct wl_interface wl_shell_surface_interface; -#endif -#ifndef WL_SURFACE_INTERFACE -#define WL_SURFACE_INTERFACE -/** - * @page page_iface_wl_surface wl_surface - * @section page_iface_wl_surface_desc Description - * - * A surface is a rectangular area that is displayed on the screen. - * It has a location, size and pixel contents. - * - * The size of a surface (and relative positions on it) is described - * in surface-local coordinates, which may differ from the buffer - * coordinates of the pixel content, in case a buffer_transform - * or a buffer_scale is used. - * - * A surface without a "role" is fairly useless: a compositor does - * not know where, when or how to present it. The role is the - * purpose of a wl_surface. Examples of roles are a cursor for a - * pointer (as set by wl_pointer.set_cursor), a drag icon - * (wl_data_device.start_drag), a sub-surface - * (wl_subcompositor.get_subsurface), and a window as defined by a - * shell protocol (e.g. wl_shell.get_shell_surface). - * - * A surface can have only one role at a time. Initially a - * wl_surface does not have a role. Once a wl_surface is given a - * role, it is set permanently for the whole lifetime of the - * wl_surface object. Giving the current role again is allowed, - * unless explicitly forbidden by the relevant interface - * specification. - * - * Surface roles are given by requests in other interfaces such as - * wl_pointer.set_cursor. The request should explicitly mention - * that this request gives a role to a wl_surface. Often, this - * request also creates a new protocol object that represents the - * role and adds additional functionality to wl_surface. When a - * client wants to destroy a wl_surface, they must destroy this 'role - * object' before the wl_surface. - * - * Destroying the role object does not remove the role from the - * wl_surface, but it may stop the wl_surface from "playing the role". - * For instance, if a wl_subsurface object is destroyed, the wl_surface - * it was created for will be unmapped and forget its position and - * z-order. It is allowed to create a wl_subsurface for the same - * wl_surface again, but it is not allowed to use the wl_surface as - * a cursor (cursor is a different role than sub-surface, and role - * switching is not allowed). - * @section page_iface_wl_surface_api API - * See @ref iface_wl_surface. - */ -/** - * @defgroup iface_wl_surface The wl_surface interface - * - * A surface is a rectangular area that is displayed on the screen. - * It has a location, size and pixel contents. - * - * The size of a surface (and relative positions on it) is described - * in surface-local coordinates, which may differ from the buffer - * coordinates of the pixel content, in case a buffer_transform - * or a buffer_scale is used. - * - * A surface without a "role" is fairly useless: a compositor does - * not know where, when or how to present it. The role is the - * purpose of a wl_surface. Examples of roles are a cursor for a - * pointer (as set by wl_pointer.set_cursor), a drag icon - * (wl_data_device.start_drag), a sub-surface - * (wl_subcompositor.get_subsurface), and a window as defined by a - * shell protocol (e.g. wl_shell.get_shell_surface). - * - * A surface can have only one role at a time. Initially a - * wl_surface does not have a role. Once a wl_surface is given a - * role, it is set permanently for the whole lifetime of the - * wl_surface object. Giving the current role again is allowed, - * unless explicitly forbidden by the relevant interface - * specification. - * - * Surface roles are given by requests in other interfaces such as - * wl_pointer.set_cursor. The request should explicitly mention - * that this request gives a role to a wl_surface. Often, this - * request also creates a new protocol object that represents the - * role and adds additional functionality to wl_surface. When a - * client wants to destroy a wl_surface, they must destroy this 'role - * object' before the wl_surface. - * - * Destroying the role object does not remove the role from the - * wl_surface, but it may stop the wl_surface from "playing the role". - * For instance, if a wl_subsurface object is destroyed, the wl_surface - * it was created for will be unmapped and forget its position and - * z-order. It is allowed to create a wl_subsurface for the same - * wl_surface again, but it is not allowed to use the wl_surface as - * a cursor (cursor is a different role than sub-surface, and role - * switching is not allowed). - */ -extern const struct wl_interface wl_surface_interface; -#endif -#ifndef WL_SEAT_INTERFACE -#define WL_SEAT_INTERFACE -/** - * @page page_iface_wl_seat wl_seat - * @section page_iface_wl_seat_desc Description - * - * A seat is a group of keyboards, pointer and touch devices. This - * object is published as a global during start up, or when such a - * device is hot plugged. A seat typically has a pointer and - * maintains a keyboard focus and a pointer focus. - * @section page_iface_wl_seat_api API - * See @ref iface_wl_seat. - */ -/** - * @defgroup iface_wl_seat The wl_seat interface - * - * A seat is a group of keyboards, pointer and touch devices. This - * object is published as a global during start up, or when such a - * device is hot plugged. A seat typically has a pointer and - * maintains a keyboard focus and a pointer focus. - */ -extern const struct wl_interface wl_seat_interface; -#endif -#ifndef WL_POINTER_INTERFACE -#define WL_POINTER_INTERFACE -/** - * @page page_iface_wl_pointer wl_pointer - * @section page_iface_wl_pointer_desc Description - * - * The wl_pointer interface represents one or more input devices, - * such as mice, which control the pointer location and pointer_focus - * of a seat. - * - * The wl_pointer interface generates motion, enter and leave - * events for the surfaces that the pointer is located over, - * and button and axis events for button presses, button releases - * and scrolling. - * @section page_iface_wl_pointer_api API - * See @ref iface_wl_pointer. - */ -/** - * @defgroup iface_wl_pointer The wl_pointer interface - * - * The wl_pointer interface represents one or more input devices, - * such as mice, which control the pointer location and pointer_focus - * of a seat. - * - * The wl_pointer interface generates motion, enter and leave - * events for the surfaces that the pointer is located over, - * and button and axis events for button presses, button releases - * and scrolling. - */ -extern const struct wl_interface wl_pointer_interface; -#endif -#ifndef WL_KEYBOARD_INTERFACE -#define WL_KEYBOARD_INTERFACE -/** - * @page page_iface_wl_keyboard wl_keyboard - * @section page_iface_wl_keyboard_desc Description - * - * The wl_keyboard interface represents one or more keyboards - * associated with a seat. - * @section page_iface_wl_keyboard_api API - * See @ref iface_wl_keyboard. - */ -/** - * @defgroup iface_wl_keyboard The wl_keyboard interface - * - * The wl_keyboard interface represents one or more keyboards - * associated with a seat. - */ -extern const struct wl_interface wl_keyboard_interface; -#endif -#ifndef WL_TOUCH_INTERFACE -#define WL_TOUCH_INTERFACE -/** - * @page page_iface_wl_touch wl_touch - * @section page_iface_wl_touch_desc Description - * - * The wl_touch interface represents a touchscreen - * associated with a seat. - * - * Touch interactions can consist of one or more contacts. - * For each contact, a series of events is generated, starting - * with a down event, followed by zero or more motion events, - * and ending with an up event. Events relating to the same - * contact point can be identified by the ID of the sequence. - * @section page_iface_wl_touch_api API - * See @ref iface_wl_touch. - */ -/** - * @defgroup iface_wl_touch The wl_touch interface - * - * The wl_touch interface represents a touchscreen - * associated with a seat. - * - * Touch interactions can consist of one or more contacts. - * For each contact, a series of events is generated, starting - * with a down event, followed by zero or more motion events, - * and ending with an up event. Events relating to the same - * contact point can be identified by the ID of the sequence. - */ -extern const struct wl_interface wl_touch_interface; -#endif -#ifndef WL_OUTPUT_INTERFACE -#define WL_OUTPUT_INTERFACE -/** - * @page page_iface_wl_output wl_output - * @section page_iface_wl_output_desc Description - * - * An output describes part of the compositor geometry. The - * compositor works in the 'compositor coordinate system' and an - * output corresponds to a rectangular area in that space that is - * actually visible. This typically corresponds to a monitor that - * displays part of the compositor space. This object is published - * as global during start up, or when a monitor is hotplugged. - * @section page_iface_wl_output_api API - * See @ref iface_wl_output. - */ -/** - * @defgroup iface_wl_output The wl_output interface - * - * An output describes part of the compositor geometry. The - * compositor works in the 'compositor coordinate system' and an - * output corresponds to a rectangular area in that space that is - * actually visible. This typically corresponds to a monitor that - * displays part of the compositor space. This object is published - * as global during start up, or when a monitor is hotplugged. - */ -extern const struct wl_interface wl_output_interface; -#endif -#ifndef WL_REGION_INTERFACE -#define WL_REGION_INTERFACE -/** - * @page page_iface_wl_region wl_region - * @section page_iface_wl_region_desc Description - * - * A region object describes an area. - * - * Region objects are used to describe the opaque and input - * regions of a surface. - * @section page_iface_wl_region_api API - * See @ref iface_wl_region. - */ -/** - * @defgroup iface_wl_region The wl_region interface - * - * A region object describes an area. - * - * Region objects are used to describe the opaque and input - * regions of a surface. - */ -extern const struct wl_interface wl_region_interface; -#endif -#ifndef WL_SUBCOMPOSITOR_INTERFACE -#define WL_SUBCOMPOSITOR_INTERFACE -/** - * @page page_iface_wl_subcompositor wl_subcompositor - * @section page_iface_wl_subcompositor_desc Description - * - * The global interface exposing sub-surface compositing capabilities. - * A wl_surface, that has sub-surfaces associated, is called the - * parent surface. Sub-surfaces can be arbitrarily nested and create - * a tree of sub-surfaces. - * - * The root surface in a tree of sub-surfaces is the main - * surface. The main surface cannot be a sub-surface, because - * sub-surfaces must always have a parent. - * - * A main surface with its sub-surfaces forms a (compound) window. - * For window management purposes, this set of wl_surface objects is - * to be considered as a single window, and it should also behave as - * such. - * - * The aim of sub-surfaces is to offload some of the compositing work - * within a window from clients to the compositor. A prime example is - * a video player with decorations and video in separate wl_surface - * objects. This should allow the compositor to pass YUV video buffer - * processing to dedicated overlay hardware when possible. - * @section page_iface_wl_subcompositor_api API - * See @ref iface_wl_subcompositor. - */ -/** - * @defgroup iface_wl_subcompositor The wl_subcompositor interface - * - * The global interface exposing sub-surface compositing capabilities. - * A wl_surface, that has sub-surfaces associated, is called the - * parent surface. Sub-surfaces can be arbitrarily nested and create - * a tree of sub-surfaces. - * - * The root surface in a tree of sub-surfaces is the main - * surface. The main surface cannot be a sub-surface, because - * sub-surfaces must always have a parent. - * - * A main surface with its sub-surfaces forms a (compound) window. - * For window management purposes, this set of wl_surface objects is - * to be considered as a single window, and it should also behave as - * such. - * - * The aim of sub-surfaces is to offload some of the compositing work - * within a window from clients to the compositor. A prime example is - * a video player with decorations and video in separate wl_surface - * objects. This should allow the compositor to pass YUV video buffer - * processing to dedicated overlay hardware when possible. - */ -extern const struct wl_interface wl_subcompositor_interface; -#endif -#ifndef WL_SUBSURFACE_INTERFACE -#define WL_SUBSURFACE_INTERFACE -/** - * @page page_iface_wl_subsurface wl_subsurface - * @section page_iface_wl_subsurface_desc Description - * - * An additional interface to a wl_surface object, which has been - * made a sub-surface. A sub-surface has one parent surface. A - * sub-surface's size and position are not limited to that of the parent. - * Particularly, a sub-surface is not automatically clipped to its - * parent's area. - * - * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied - * and the parent surface is mapped. The order of which one happens - * first is irrelevant. A sub-surface is hidden if the parent becomes - * hidden, or if a NULL wl_buffer is applied. These rules apply - * recursively through the tree of surfaces. - * - * The behaviour of a wl_surface.commit request on a sub-surface - * depends on the sub-surface's mode. The possible modes are - * synchronized and desynchronized, see methods - * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized - * mode caches the wl_surface state to be applied when the parent's - * state gets applied, and desynchronized mode applies the pending - * wl_surface state directly. A sub-surface is initially in the - * synchronized mode. - * - * Sub-surfaces have also other kind of state, which is managed by - * wl_subsurface requests, as opposed to wl_surface requests. This - * state includes the sub-surface position relative to the parent - * surface (wl_subsurface.set_position), and the stacking order of - * the parent and its sub-surfaces (wl_subsurface.place_above and - * .place_below). This state is applied when the parent surface's - * wl_surface state is applied, regardless of the sub-surface's mode. - * As the exception, set_sync and set_desync are effective immediately. - * - * The main surface can be thought to be always in desynchronized mode, - * since it does not have a parent in the sub-surfaces sense. - * - * Even if a sub-surface is in desynchronized mode, it will behave as - * in synchronized mode, if its parent surface behaves as in - * synchronized mode. This rule is applied recursively throughout the - * tree of surfaces. This means, that one can set a sub-surface into - * synchronized mode, and then assume that all its child and grand-child - * sub-surfaces are synchronized, too, without explicitly setting them. - * - * If the wl_surface associated with the wl_subsurface is destroyed, the - * wl_subsurface object becomes inert. Note, that destroying either object - * takes effect immediately. If you need to synchronize the removal - * of a sub-surface to the parent surface update, unmap the sub-surface - * first by attaching a NULL wl_buffer, update parent, and then destroy - * the sub-surface. - * - * If the parent wl_surface object is destroyed, the sub-surface is - * unmapped. - * @section page_iface_wl_subsurface_api API - * See @ref iface_wl_subsurface. - */ -/** - * @defgroup iface_wl_subsurface The wl_subsurface interface - * - * An additional interface to a wl_surface object, which has been - * made a sub-surface. A sub-surface has one parent surface. A - * sub-surface's size and position are not limited to that of the parent. - * Particularly, a sub-surface is not automatically clipped to its - * parent's area. - * - * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied - * and the parent surface is mapped. The order of which one happens - * first is irrelevant. A sub-surface is hidden if the parent becomes - * hidden, or if a NULL wl_buffer is applied. These rules apply - * recursively through the tree of surfaces. - * - * The behaviour of a wl_surface.commit request on a sub-surface - * depends on the sub-surface's mode. The possible modes are - * synchronized and desynchronized, see methods - * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized - * mode caches the wl_surface state to be applied when the parent's - * state gets applied, and desynchronized mode applies the pending - * wl_surface state directly. A sub-surface is initially in the - * synchronized mode. - * - * Sub-surfaces have also other kind of state, which is managed by - * wl_subsurface requests, as opposed to wl_surface requests. This - * state includes the sub-surface position relative to the parent - * surface (wl_subsurface.set_position), and the stacking order of - * the parent and its sub-surfaces (wl_subsurface.place_above and - * .place_below). This state is applied when the parent surface's - * wl_surface state is applied, regardless of the sub-surface's mode. - * As the exception, set_sync and set_desync are effective immediately. - * - * The main surface can be thought to be always in desynchronized mode, - * since it does not have a parent in the sub-surfaces sense. - * - * Even if a sub-surface is in desynchronized mode, it will behave as - * in synchronized mode, if its parent surface behaves as in - * synchronized mode. This rule is applied recursively throughout the - * tree of surfaces. This means, that one can set a sub-surface into - * synchronized mode, and then assume that all its child and grand-child - * sub-surfaces are synchronized, too, without explicitly setting them. - * - * If the wl_surface associated with the wl_subsurface is destroyed, the - * wl_subsurface object becomes inert. Note, that destroying either object - * takes effect immediately. If you need to synchronize the removal - * of a sub-surface to the parent surface update, unmap the sub-surface - * first by attaching a NULL wl_buffer, update parent, and then destroy - * the sub-surface. - * - * If the parent wl_surface object is destroyed, the sub-surface is - * unmapped. - */ -extern const struct wl_interface wl_subsurface_interface; -#endif - -#ifndef WL_DISPLAY_ERROR_ENUM -#define WL_DISPLAY_ERROR_ENUM -/** - * @ingroup iface_wl_display - * global error values - * - * These errors are global and can be emitted in response to any - * server request. - */ -enum wl_display_error { - /** - * server couldn't find object - */ - WL_DISPLAY_ERROR_INVALID_OBJECT = 0, - /** - * method doesn't exist on the specified interface - */ - WL_DISPLAY_ERROR_INVALID_METHOD = 1, - /** - * server is out of memory - */ - WL_DISPLAY_ERROR_NO_MEMORY = 2, -}; -#endif /* WL_DISPLAY_ERROR_ENUM */ - -#ifndef WL_DISPLAY_ERROR_ENUM_IS_VALID -#define WL_DISPLAY_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_display - * Validate a wl_display error value. - * - * @return true on success, false on error. - * @ref wl_display_error - */ -static inline bool -wl_display_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_DISPLAY_ERROR_INVALID_OBJECT: - return version >= 1; - case WL_DISPLAY_ERROR_INVALID_METHOD: - return version >= 1; - case WL_DISPLAY_ERROR_NO_MEMORY: - return version >= 1; - default: - return false; - } -} -#endif /* WL_DISPLAY_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_display - * @struct wl_display_interface - */ -struct wl_display_interface { - /** - * asynchronous roundtrip - * - * The sync request asks the server to emit the 'done' event on - * the returned wl_callback object. Since requests are handled - * in-order and events are delivered in-order, this can be used as - * a barrier to ensure all previous requests and the resulting - * events have been handled. - * - * The object returned by this request will be destroyed by the - * compositor after the callback is fired and as such the client - * must not attempt to use it after that point. - * - * The callback_data passed in the callback is the event serial. - * @param callback callback object for the sync request - */ - void (*sync)(struct wl_client *client, - struct wl_resource *resource, - uint32_t callback); - /** - * get global registry object - * - * This request creates a registry object that allows the client - * to list and bind the global objects available from the - * compositor. - * @param registry global registry object - */ - void (*get_registry)(struct wl_client *client, - struct wl_resource *resource, - uint32_t registry); -}; - -#define WL_DISPLAY_ERROR 0 -#define WL_DISPLAY_DELETE_ID 1 - -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_ERROR_SINCE_VERSION 1 -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_DELETE_ID_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_SYNC_SINCE_VERSION 1 -/** - * @ingroup iface_wl_display - */ -#define WL_DISPLAY_GET_REGISTRY_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_registry - * @struct wl_registry_interface - */ -struct wl_registry_interface { - /** - * bind an object to the display - * - * Binds a new, client-created object to the server using the - * specified name as the identifier. - * @param name unique numeric name of the object - * @param interface name of the objects interface - * @param version version of the objects interface - * @param id bounded object - */ - void (*bind)(struct wl_client *client, - struct wl_resource *resource, - uint32_t name, - const char *interface, uint32_t version, uint32_t id); -}; - -#define WL_REGISTRY_GLOBAL 0 -#define WL_REGISTRY_GLOBAL_REMOVE 1 - -/** - * @ingroup iface_wl_registry - */ -#define WL_REGISTRY_GLOBAL_SINCE_VERSION 1 -/** - * @ingroup iface_wl_registry - */ -#define WL_REGISTRY_GLOBAL_REMOVE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_registry - */ -#define WL_REGISTRY_BIND_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_registry - * Sends an global event to the client owning the resource. - * @param resource_ The client's resource - * @param name numeric name of the global object - * @param interface interface implemented by the object - * @param version interface version - */ -static inline void -wl_registry_send_global(struct wl_resource *resource_, uint32_t name, const char *interface, uint32_t version) -{ - wl_resource_post_event(resource_, WL_REGISTRY_GLOBAL, name, interface, version); -} - -/** - * @ingroup iface_wl_registry - * Sends an global_remove event to the client owning the resource. - * @param resource_ The client's resource - * @param name numeric name of the global object - */ -static inline void -wl_registry_send_global_remove(struct wl_resource *resource_, uint32_t name) -{ - wl_resource_post_event(resource_, WL_REGISTRY_GLOBAL_REMOVE, name); -} - -#define WL_CALLBACK_DONE 0 - -/** - * @ingroup iface_wl_callback - */ -#define WL_CALLBACK_DONE_SINCE_VERSION 1 - - -/** - * @ingroup iface_wl_callback - * Sends an done event to the client owning the resource. - * @param resource_ The client's resource - * @param callback_data request-specific data for the callback - */ -static inline void -wl_callback_send_done(struct wl_resource *resource_, uint32_t callback_data) -{ - wl_resource_post_event(resource_, WL_CALLBACK_DONE, callback_data); -} - -/** - * @ingroup iface_wl_compositor - * @struct wl_compositor_interface - */ -struct wl_compositor_interface { - /** - * create new surface - * - * Ask the compositor to create a new surface. - * @param id the new surface - */ - void (*create_surface)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * create new region - * - * Ask the compositor to create a new region. - * @param id the new region - */ - void (*create_region)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); -}; - - -/** - * @ingroup iface_wl_compositor - */ -#define WL_COMPOSITOR_CREATE_SURFACE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_compositor - */ -#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shm_pool - * @struct wl_shm_pool_interface - */ -struct wl_shm_pool_interface { - /** - * create a buffer from the pool - * - * Create a wl_buffer object from the pool. - * - * The buffer is created offset bytes into the pool and has width - * and height as specified. The stride argument specifies the - * number of bytes from the beginning of one row to the beginning - * of the next. The format is the pixel format of the buffer and - * must be one of those advertised through the wl_shm.format event. - * - * A buffer will keep a reference to the pool it was created from - * so it is valid to destroy the pool immediately after creating a - * buffer from it. - * @param id buffer to create - * @param offset buffer byte offset within the pool - * @param width buffer width, in pixels - * @param height buffer height, in pixels - * @param stride number of bytes from the beginning of one row to the beginning of the next row - * @param format buffer pixel format - */ - void (*create_buffer)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - int32_t offset, - int32_t width, - int32_t height, - int32_t stride, - uint32_t format); - /** - * destroy the pool - * - * Destroy the shared memory pool. - * - * The mmapped memory will be released when all buffers that have - * been created from this pool are gone. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * change the size of the pool mapping - * - * This request will cause the server to remap the backing memory - * for the pool from the file descriptor passed when the pool was - * created, but using the new size. This request can only be used - * to make the pool bigger. - * @param size new size of the pool, in bytes - */ - void (*resize)(struct wl_client *client, - struct wl_resource *resource, - int32_t size); -}; - - -/** - * @ingroup iface_wl_shm_pool - */ -#define WL_SHM_POOL_CREATE_BUFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shm_pool - */ -#define WL_SHM_POOL_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shm_pool - */ -#define WL_SHM_POOL_RESIZE_SINCE_VERSION 1 - -#ifndef WL_SHM_ERROR_ENUM -#define WL_SHM_ERROR_ENUM -/** - * @ingroup iface_wl_shm - * wl_shm error values - * - * These errors can be emitted in response to wl_shm requests. - */ -enum wl_shm_error { - /** - * buffer format is not known - */ - WL_SHM_ERROR_INVALID_FORMAT = 0, - /** - * invalid size or stride during pool or buffer creation - */ - WL_SHM_ERROR_INVALID_STRIDE = 1, - /** - * mmapping the file descriptor failed - */ - WL_SHM_ERROR_INVALID_FD = 2, -}; -#endif /* WL_SHM_ERROR_ENUM */ - -#ifndef WL_SHM_ERROR_ENUM_IS_VALID -#define WL_SHM_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_shm - * Validate a wl_shm error value. - * - * @return true on success, false on error. - * @ref wl_shm_error - */ -static inline bool -wl_shm_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SHM_ERROR_INVALID_FORMAT: - return version >= 1; - case WL_SHM_ERROR_INVALID_STRIDE: - return version >= 1; - case WL_SHM_ERROR_INVALID_FD: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SHM_ERROR_ENUM_IS_VALID */ - -#ifndef WL_SHM_FORMAT_ENUM -#define WL_SHM_FORMAT_ENUM -/** - * @ingroup iface_wl_shm - * pixel formats - * - * This describes the memory layout of an individual pixel. - * - * All renderers should support argb8888 and xrgb8888 but any other - * formats are optional and may not be supported by the particular - * renderer in use. - * - * The drm format codes match the macros defined in drm_fourcc.h. - * The formats actually supported by the compositor will be - * reported by the format event. - */ -enum wl_shm_format { - /** - * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian - */ - WL_SHM_FORMAT_ARGB8888 = 0, - /** - * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian - */ - WL_SHM_FORMAT_XRGB8888 = 1, - /** - * 8-bit color index format, [7:0] C - */ - WL_SHM_FORMAT_C8 = 0x20203843, - /** - * 8-bit RGB format, [7:0] R:G:B 3:3:2 - */ - WL_SHM_FORMAT_RGB332 = 0x38424752, - /** - * 8-bit BGR format, [7:0] B:G:R 2:3:3 - */ - WL_SHM_FORMAT_BGR233 = 0x38524742, - /** - * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian - */ - WL_SHM_FORMAT_XRGB4444 = 0x32315258, - /** - * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian - */ - WL_SHM_FORMAT_XBGR4444 = 0x32314258, - /** - * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian - */ - WL_SHM_FORMAT_RGBX4444 = 0x32315852, - /** - * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian - */ - WL_SHM_FORMAT_BGRX4444 = 0x32315842, - /** - * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian - */ - WL_SHM_FORMAT_ARGB4444 = 0x32315241, - /** - * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian - */ - WL_SHM_FORMAT_ABGR4444 = 0x32314241, - /** - * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian - */ - WL_SHM_FORMAT_RGBA4444 = 0x32314152, - /** - * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian - */ - WL_SHM_FORMAT_BGRA4444 = 0x32314142, - /** - * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian - */ - WL_SHM_FORMAT_XRGB1555 = 0x35315258, - /** - * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian - */ - WL_SHM_FORMAT_XBGR1555 = 0x35314258, - /** - * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian - */ - WL_SHM_FORMAT_RGBX5551 = 0x35315852, - /** - * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian - */ - WL_SHM_FORMAT_BGRX5551 = 0x35315842, - /** - * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian - */ - WL_SHM_FORMAT_ARGB1555 = 0x35315241, - /** - * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian - */ - WL_SHM_FORMAT_ABGR1555 = 0x35314241, - /** - * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian - */ - WL_SHM_FORMAT_RGBA5551 = 0x35314152, - /** - * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian - */ - WL_SHM_FORMAT_BGRA5551 = 0x35314142, - /** - * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian - */ - WL_SHM_FORMAT_RGB565 = 0x36314752, - /** - * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian - */ - WL_SHM_FORMAT_BGR565 = 0x36314742, - /** - * 24-bit RGB format, [23:0] R:G:B little endian - */ - WL_SHM_FORMAT_RGB888 = 0x34324752, - /** - * 24-bit BGR format, [23:0] B:G:R little endian - */ - WL_SHM_FORMAT_BGR888 = 0x34324742, - /** - * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian - */ - WL_SHM_FORMAT_XBGR8888 = 0x34324258, - /** - * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian - */ - WL_SHM_FORMAT_RGBX8888 = 0x34325852, - /** - * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian - */ - WL_SHM_FORMAT_BGRX8888 = 0x34325842, - /** - * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian - */ - WL_SHM_FORMAT_ABGR8888 = 0x34324241, - /** - * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian - */ - WL_SHM_FORMAT_RGBA8888 = 0x34324152, - /** - * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian - */ - WL_SHM_FORMAT_BGRA8888 = 0x34324142, - /** - * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian - */ - WL_SHM_FORMAT_XRGB2101010 = 0x30335258, - /** - * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian - */ - WL_SHM_FORMAT_XBGR2101010 = 0x30334258, - /** - * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian - */ - WL_SHM_FORMAT_RGBX1010102 = 0x30335852, - /** - * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian - */ - WL_SHM_FORMAT_BGRX1010102 = 0x30335842, - /** - * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian - */ - WL_SHM_FORMAT_ARGB2101010 = 0x30335241, - /** - * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian - */ - WL_SHM_FORMAT_ABGR2101010 = 0x30334241, - /** - * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian - */ - WL_SHM_FORMAT_RGBA1010102 = 0x30334152, - /** - * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian - */ - WL_SHM_FORMAT_BGRA1010102 = 0x30334142, - /** - * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_YUYV = 0x56595559, - /** - * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_YVYU = 0x55595659, - /** - * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_UYVY = 0x59565955, - /** - * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian - */ - WL_SHM_FORMAT_VYUY = 0x59555956, - /** - * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian - */ - WL_SHM_FORMAT_AYUV = 0x56555941, - /** - * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane - */ - WL_SHM_FORMAT_NV12 = 0x3231564e, - /** - * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane - */ - WL_SHM_FORMAT_NV21 = 0x3132564e, - /** - * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane - */ - WL_SHM_FORMAT_NV16 = 0x3631564e, - /** - * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane - */ - WL_SHM_FORMAT_NV61 = 0x3136564e, - /** - * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV410 = 0x39565559, - /** - * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU410 = 0x39555659, - /** - * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV411 = 0x31315559, - /** - * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU411 = 0x31315659, - /** - * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV420 = 0x32315559, - /** - * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU420 = 0x32315659, - /** - * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV422 = 0x36315559, - /** - * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU422 = 0x36315659, - /** - * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes - */ - WL_SHM_FORMAT_YUV444 = 0x34325559, - /** - * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes - */ - WL_SHM_FORMAT_YVU444 = 0x34325659, -}; -#endif /* WL_SHM_FORMAT_ENUM */ - -#ifndef WL_SHM_FORMAT_ENUM_IS_VALID -#define WL_SHM_FORMAT_ENUM_IS_VALID -/** - * @ingroup iface_wl_shm - * Validate a wl_shm format value. - * - * @return true on success, false on error. - * @ref wl_shm_format - */ -static inline bool -wl_shm_format_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SHM_FORMAT_ARGB8888: - return version >= 1; - case WL_SHM_FORMAT_XRGB8888: - return version >= 1; - case WL_SHM_FORMAT_C8: - return version >= 1; - case WL_SHM_FORMAT_RGB332: - return version >= 1; - case WL_SHM_FORMAT_BGR233: - return version >= 1; - case WL_SHM_FORMAT_XRGB4444: - return version >= 1; - case WL_SHM_FORMAT_XBGR4444: - return version >= 1; - case WL_SHM_FORMAT_RGBX4444: - return version >= 1; - case WL_SHM_FORMAT_BGRX4444: - return version >= 1; - case WL_SHM_FORMAT_ARGB4444: - return version >= 1; - case WL_SHM_FORMAT_ABGR4444: - return version >= 1; - case WL_SHM_FORMAT_RGBA4444: - return version >= 1; - case WL_SHM_FORMAT_BGRA4444: - return version >= 1; - case WL_SHM_FORMAT_XRGB1555: - return version >= 1; - case WL_SHM_FORMAT_XBGR1555: - return version >= 1; - case WL_SHM_FORMAT_RGBX5551: - return version >= 1; - case WL_SHM_FORMAT_BGRX5551: - return version >= 1; - case WL_SHM_FORMAT_ARGB1555: - return version >= 1; - case WL_SHM_FORMAT_ABGR1555: - return version >= 1; - case WL_SHM_FORMAT_RGBA5551: - return version >= 1; - case WL_SHM_FORMAT_BGRA5551: - return version >= 1; - case WL_SHM_FORMAT_RGB565: - return version >= 1; - case WL_SHM_FORMAT_BGR565: - return version >= 1; - case WL_SHM_FORMAT_RGB888: - return version >= 1; - case WL_SHM_FORMAT_BGR888: - return version >= 1; - case WL_SHM_FORMAT_XBGR8888: - return version >= 1; - case WL_SHM_FORMAT_RGBX8888: - return version >= 1; - case WL_SHM_FORMAT_BGRX8888: - return version >= 1; - case WL_SHM_FORMAT_ABGR8888: - return version >= 1; - case WL_SHM_FORMAT_RGBA8888: - return version >= 1; - case WL_SHM_FORMAT_BGRA8888: - return version >= 1; - case WL_SHM_FORMAT_XRGB2101010: - return version >= 1; - case WL_SHM_FORMAT_XBGR2101010: - return version >= 1; - case WL_SHM_FORMAT_RGBX1010102: - return version >= 1; - case WL_SHM_FORMAT_BGRX1010102: - return version >= 1; - case WL_SHM_FORMAT_ARGB2101010: - return version >= 1; - case WL_SHM_FORMAT_ABGR2101010: - return version >= 1; - case WL_SHM_FORMAT_RGBA1010102: - return version >= 1; - case WL_SHM_FORMAT_BGRA1010102: - return version >= 1; - case WL_SHM_FORMAT_YUYV: - return version >= 1; - case WL_SHM_FORMAT_YVYU: - return version >= 1; - case WL_SHM_FORMAT_UYVY: - return version >= 1; - case WL_SHM_FORMAT_VYUY: - return version >= 1; - case WL_SHM_FORMAT_AYUV: - return version >= 1; - case WL_SHM_FORMAT_NV12: - return version >= 1; - case WL_SHM_FORMAT_NV21: - return version >= 1; - case WL_SHM_FORMAT_NV16: - return version >= 1; - case WL_SHM_FORMAT_NV61: - return version >= 1; - case WL_SHM_FORMAT_YUV410: - return version >= 1; - case WL_SHM_FORMAT_YVU410: - return version >= 1; - case WL_SHM_FORMAT_YUV411: - return version >= 1; - case WL_SHM_FORMAT_YVU411: - return version >= 1; - case WL_SHM_FORMAT_YUV420: - return version >= 1; - case WL_SHM_FORMAT_YVU420: - return version >= 1; - case WL_SHM_FORMAT_YUV422: - return version >= 1; - case WL_SHM_FORMAT_YVU422: - return version >= 1; - case WL_SHM_FORMAT_YUV444: - return version >= 1; - case WL_SHM_FORMAT_YVU444: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SHM_FORMAT_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_shm - * @struct wl_shm_interface - */ -struct wl_shm_interface { - /** - * create a shm pool - * - * Create a new wl_shm_pool object. - * - * The pool can be used to create shared memory based buffer - * objects. The server will mmap size bytes of the passed file - * descriptor, to use as backing memory for the pool. - * @param id pool to create - * @param fd file descriptor for the pool - * @param size pool size, in bytes - */ - void (*create_pool)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - int32_t fd, - int32_t size); -}; - -#define WL_SHM_FORMAT 0 - -/** - * @ingroup iface_wl_shm - */ -#define WL_SHM_FORMAT_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shm - */ -#define WL_SHM_CREATE_POOL_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shm - * Sends an format event to the client owning the resource. - * @param resource_ The client's resource - * @param format buffer pixel format - */ -static inline void -wl_shm_send_format(struct wl_resource *resource_, uint32_t format) -{ - wl_resource_post_event(resource_, WL_SHM_FORMAT, format); -} - -/** - * @ingroup iface_wl_buffer - * @struct wl_buffer_interface - */ -struct wl_buffer_interface { - /** - * destroy a buffer - * - * Destroy a buffer. If and how you need to release the backing - * storage is defined by the buffer factory interface. - * - * For possible side-effects to a surface, see wl_surface.attach. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_BUFFER_RELEASE 0 - -/** - * @ingroup iface_wl_buffer - */ -#define WL_BUFFER_RELEASE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_buffer - */ -#define WL_BUFFER_DESTROY_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_buffer - * Sends an release event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_buffer_send_release(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_BUFFER_RELEASE); -} - -#ifndef WL_DATA_OFFER_ERROR_ENUM -#define WL_DATA_OFFER_ERROR_ENUM -enum wl_data_offer_error { - /** - * finish request was called untimely - */ - WL_DATA_OFFER_ERROR_INVALID_FINISH = 0, - /** - * action mask contains invalid values - */ - WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1, - /** - * action argument has an invalid value - */ - WL_DATA_OFFER_ERROR_INVALID_ACTION = 2, - /** - * offer doesn't accept this request - */ - WL_DATA_OFFER_ERROR_INVALID_OFFER = 3, -}; -#endif /* WL_DATA_OFFER_ERROR_ENUM */ - -#ifndef WL_DATA_OFFER_ERROR_ENUM_IS_VALID -#define WL_DATA_OFFER_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_data_offer - * Validate a wl_data_offer error value. - * - * @return true on success, false on error. - * @ref wl_data_offer_error - */ -static inline bool -wl_data_offer_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_DATA_OFFER_ERROR_INVALID_FINISH: - return version >= 1; - case WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK: - return version >= 1; - case WL_DATA_OFFER_ERROR_INVALID_ACTION: - return version >= 1; - case WL_DATA_OFFER_ERROR_INVALID_OFFER: - return version >= 1; - default: - return false; - } -} -#endif /* WL_DATA_OFFER_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_data_offer - * @struct wl_data_offer_interface - */ -struct wl_data_offer_interface { - /** - * accept one of the offered mime types - * - * Indicate that the client can accept the given mime type, or - * NULL for not accepted. - * - * For objects of version 2 or older, this request is used by the - * client to give feedback whether the client can receive the given - * mime type, or NULL if none is accepted; the feedback does not - * determine whether the drag-and-drop operation succeeds or not. - * - * For objects of version 3 or newer, this request determines the - * final result of the drag-and-drop operation. If the end result - * is that no mime types were accepted, the drag-and-drop operation - * will be cancelled and the corresponding drag source will receive - * wl_data_source.cancelled. Clients may still use this event in - * conjunction with wl_data_source.action for feedback. - * @param serial serial number of the accept request - * @param mime_type mime type accepted by the client - */ - void (*accept)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - const char *mime_type); - /** - * request that the data is transferred - * - * To transfer the offered data, the client issues this request - * and indicates the mime type it wants to receive. The transfer - * happens through the passed file descriptor (typically created - * with the pipe system call). The source client writes the data in - * the mime type representation requested and then closes the file - * descriptor. - * - * The receiving client reads from the read end of the pipe until - * EOF and then closes its end, at which point the transfer is - * complete. - * - * This request may happen multiple times for different mime types, - * both before and after wl_data_device.drop. Drag-and-drop - * destination clients may preemptively fetch data or examine it - * more closely to determine acceptance. - * @param mime_type mime type desired by receiver - * @param fd file descriptor for data transfer - */ - void (*receive)(struct wl_client *client, - struct wl_resource *resource, - const char *mime_type, - int32_t fd); - /** - * destroy data offer - * - * Destroy the data offer. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * the offer will no longer be used - * - * Notifies the compositor that the drag destination successfully - * finished the drag-and-drop operation. - * - * Upon receiving this request, the compositor will emit - * wl_data_source.dnd_finished on the drag source client. - * - * It is a client error to perform other requests than - * wl_data_offer.destroy after this one. It is also an error to - * perform this request after a NULL mime type has been set in - * wl_data_offer.accept or no action was received through - * wl_data_offer.action. - * @since 3 - */ - void (*finish)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the available/preferred drag-and-drop actions - * - * Sets the actions that the destination side client supports for - * this operation. This request may trigger the emission of - * wl_data_source.action and wl_data_offer.action events if the - * compositor needs to change the selected action. - * - * This request can be called multiple times throughout the - * drag-and-drop operation, typically in response to - * wl_data_device.enter or wl_data_device.motion events. - * - * This request determines the final result of the drag-and-drop - * operation. If the end result is that no action is accepted, the - * drag source will receive wl_drag_source.cancelled. - * - * The dnd_actions argument must contain only values expressed in - * the wl_data_device_manager.dnd_actions enum, and the - * preferred_action argument must only contain one of those values - * set, otherwise it will result in a protocol error. - * - * While managing an "ask" action, the destination drag-and-drop - * client may perform further wl_data_offer.receive requests, and - * is expected to perform one last wl_data_offer.set_actions - * request with a preferred action other than "ask" (and optionally - * wl_data_offer.accept) before requesting wl_data_offer.finish, in - * order to convey the action selected by the user. If the - * preferred action is not in the wl_data_offer.source_actions - * mask, an error will be raised. - * - * If the "ask" action is dismissed (e.g. user cancellation), the - * client is expected to perform wl_data_offer.destroy right away. - * - * This request can only be made on drag-and-drop offers, a - * protocol error will be raised otherwise. - * @param dnd_actions actions supported by the destination client - * @param preferred_action action preferred by the destination client - * @since 3 - */ - void (*set_actions)(struct wl_client *client, - struct wl_resource *resource, - uint32_t dnd_actions, - uint32_t preferred_action); -}; - -#define WL_DATA_OFFER_OFFER 0 -#define WL_DATA_OFFER_SOURCE_ACTIONS 1 -#define WL_DATA_OFFER_ACTION 2 - -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_OFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_ACTION_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_ACCEPT_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_RECEIVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_FINISH_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_offer - */ -#define WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_data_offer - * Sends an offer event to the client owning the resource. - * @param resource_ The client's resource - * @param mime_type offered mime type - */ -static inline void -wl_data_offer_send_offer(struct wl_resource *resource_, const char *mime_type) -{ - wl_resource_post_event(resource_, WL_DATA_OFFER_OFFER, mime_type); -} - -/** - * @ingroup iface_wl_data_offer - * Sends an source_actions event to the client owning the resource. - * @param resource_ The client's resource - * @param source_actions actions offered by the data source - */ -static inline void -wl_data_offer_send_source_actions(struct wl_resource *resource_, uint32_t source_actions) -{ - wl_resource_post_event(resource_, WL_DATA_OFFER_SOURCE_ACTIONS, source_actions); -} - -/** - * @ingroup iface_wl_data_offer - * Sends an action event to the client owning the resource. - * @param resource_ The client's resource - * @param dnd_action action selected by the compositor - */ -static inline void -wl_data_offer_send_action(struct wl_resource *resource_, uint32_t dnd_action) -{ - wl_resource_post_event(resource_, WL_DATA_OFFER_ACTION, dnd_action); -} - -#ifndef WL_DATA_SOURCE_ERROR_ENUM -#define WL_DATA_SOURCE_ERROR_ENUM -enum wl_data_source_error { - /** - * action mask contains invalid values - */ - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0, - /** - * source doesn't accept this request - */ - WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1, -}; -#endif /* WL_DATA_SOURCE_ERROR_ENUM */ - -#ifndef WL_DATA_SOURCE_ERROR_ENUM_IS_VALID -#define WL_DATA_SOURCE_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_data_source - * Validate a wl_data_source error value. - * - * @return true on success, false on error. - * @ref wl_data_source_error - */ -static inline bool -wl_data_source_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK: - return version >= 1; - case WL_DATA_SOURCE_ERROR_INVALID_SOURCE: - return version >= 1; - default: - return false; - } -} -#endif /* WL_DATA_SOURCE_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_data_source - * @struct wl_data_source_interface - */ -struct wl_data_source_interface { - /** - * add an offered mime type - * - * This request adds a mime type to the set of mime types - * advertised to targets. Can be called several times to offer - * multiple types. - * @param mime_type mime type offered by the data source - */ - void (*offer)(struct wl_client *client, - struct wl_resource *resource, - const char *mime_type); - /** - * destroy the data source - * - * Destroy the data source. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the available drag-and-drop actions - * - * Sets the actions that the source side client supports for this - * operation. This request may trigger wl_data_source.action and - * wl_data_offer.action events if the compositor needs to change - * the selected action. - * - * The dnd_actions argument must contain only values expressed in - * the wl_data_device_manager.dnd_actions enum, otherwise it will - * result in a protocol error. - * - * This request must be made once only, and can only be made on - * sources used in drag-and-drop, so it must be performed before - * wl_data_device.start_drag. Attempting to use the source other - * than for drag-and-drop will raise a protocol error. - * @param dnd_actions actions supported by the data source - * @since 3 - */ - void (*set_actions)(struct wl_client *client, - struct wl_resource *resource, - uint32_t dnd_actions); -}; - -#define WL_DATA_SOURCE_TARGET 0 -#define WL_DATA_SOURCE_SEND 1 -#define WL_DATA_SOURCE_CANCELLED 2 -#define WL_DATA_SOURCE_DND_DROP_PERFORMED 3 -#define WL_DATA_SOURCE_DND_FINISHED 4 -#define WL_DATA_SOURCE_ACTION 5 - -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_TARGET_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_SEND_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_CANCELLED_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION 3 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_ACTION_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_OFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_source - */ -#define WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_data_source - * Sends an target event to the client owning the resource. - * @param resource_ The client's resource - * @param mime_type mime type accepted by the target - */ -static inline void -wl_data_source_send_target(struct wl_resource *resource_, const char *mime_type) -{ - wl_resource_post_event(resource_, WL_DATA_SOURCE_TARGET, mime_type); -} - -/** - * @ingroup iface_wl_data_source - * Sends an send event to the client owning the resource. - * @param resource_ The client's resource - * @param mime_type mime type for the data - * @param fd file descriptor for the data - */ -static inline void -wl_data_source_send_send(struct wl_resource *resource_, const char *mime_type, int32_t fd) -{ - wl_resource_post_event(resource_, WL_DATA_SOURCE_SEND, mime_type, fd); -} - -/** - * @ingroup iface_wl_data_source - * Sends an cancelled event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_data_source_send_cancelled(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_DATA_SOURCE_CANCELLED); -} - -/** - * @ingroup iface_wl_data_source - * Sends an dnd_drop_performed event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_data_source_send_dnd_drop_performed(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_DATA_SOURCE_DND_DROP_PERFORMED); -} - -/** - * @ingroup iface_wl_data_source - * Sends an dnd_finished event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_data_source_send_dnd_finished(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_DATA_SOURCE_DND_FINISHED); -} - -/** - * @ingroup iface_wl_data_source - * Sends an action event to the client owning the resource. - * @param resource_ The client's resource - * @param dnd_action action selected by the compositor - */ -static inline void -wl_data_source_send_action(struct wl_resource *resource_, uint32_t dnd_action) -{ - wl_resource_post_event(resource_, WL_DATA_SOURCE_ACTION, dnd_action); -} - -#ifndef WL_DATA_DEVICE_ERROR_ENUM -#define WL_DATA_DEVICE_ERROR_ENUM -enum wl_data_device_error { - /** - * given wl_surface has another role - */ - WL_DATA_DEVICE_ERROR_ROLE = 0, -}; -#endif /* WL_DATA_DEVICE_ERROR_ENUM */ - -#ifndef WL_DATA_DEVICE_ERROR_ENUM_IS_VALID -#define WL_DATA_DEVICE_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_data_device - * Validate a wl_data_device error value. - * - * @return true on success, false on error. - * @ref wl_data_device_error - */ -static inline bool -wl_data_device_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_DATA_DEVICE_ERROR_ROLE: - return version >= 1; - default: - return false; - } -} -#endif /* WL_DATA_DEVICE_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_data_device - * @struct wl_data_device_interface - */ -struct wl_data_device_interface { - /** - * start drag-and-drop operation - * - * This request asks the compositor to start a drag-and-drop - * operation on behalf of the client. - * - * The source argument is the data source that provides the data - * for the eventual data transfer. If source is NULL, enter, leave - * and motion events are sent only to the client that initiated the - * drag and the client is expected to handle the data passing - * internally. - * - * The origin surface is the surface where the drag originates and - * the client must have an active implicit grab that matches the - * serial. - * - * The icon surface is an optional (can be NULL) surface that - * provides an icon to be moved around with the cursor. Initially, - * the top-left corner of the icon surface is placed at the cursor - * hotspot, but subsequent wl_surface.attach request can move the - * relative position. Attach requests must be confirmed with - * wl_surface.commit as usual. The icon surface is given the role - * of a drag-and-drop icon. If the icon surface already has another - * role, it raises a protocol error. - * - * The current and pending input regions of the icon wl_surface are - * cleared, and wl_surface.set_input_region is ignored until the - * wl_surface is no longer used as the icon surface. When the use - * as an icon ends, the current and pending input regions become - * undefined, and the wl_surface is unmapped. - * @param source data source for the eventual transfer - * @param origin surface where the drag originates - * @param icon drag-and-drop icon surface - * @param serial serial number of the implicit grab on the origin - */ - void (*start_drag)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source, - struct wl_resource *origin, - struct wl_resource *icon, - uint32_t serial); - /** - * copy data to the selection - * - * This request asks the compositor to set the selection to the - * data from the source on behalf of the client. - * - * To unset the selection, set the source to NULL. - * @param source data source for the selection - * @param serial serial number of the event that triggered this request - */ - void (*set_selection)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source, - uint32_t serial); - /** - * destroy data device - * - * This request destroys the data device. - * @since 2 - */ - void (*release)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_DATA_DEVICE_DATA_OFFER 0 -#define WL_DATA_DEVICE_ENTER 1 -#define WL_DATA_DEVICE_LEAVE 2 -#define WL_DATA_DEVICE_MOTION 3 -#define WL_DATA_DEVICE_DROP 4 -#define WL_DATA_DEVICE_SELECTION 5 - -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_DATA_OFFER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_LEAVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_MOTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_DROP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_SELECTION_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_START_DRAG_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_SET_SELECTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device - */ -#define WL_DATA_DEVICE_RELEASE_SINCE_VERSION 2 - -/** - * @ingroup iface_wl_data_device - * Sends an data_offer event to the client owning the resource. - * @param resource_ The client's resource - * @param id the new data_offer object - */ -static inline void -wl_data_device_send_data_offer(struct wl_resource *resource_, struct wl_resource *id) -{ - wl_resource_post_event(resource_, WL_DATA_DEVICE_DATA_OFFER, id); -} - -/** - * @ingroup iface_wl_data_device - * Sends an enter event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the enter event - * @param surface client surface entered - * @param x surface-local x coordinate - * @param y surface-local y coordinate - * @param id source data_offer object - */ -static inline void -wl_data_device_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y, struct wl_resource *id) -{ - wl_resource_post_event(resource_, WL_DATA_DEVICE_ENTER, serial, surface, x, y, id); -} - -/** - * @ingroup iface_wl_data_device - * Sends an leave event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_data_device_send_leave(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_DATA_DEVICE_LEAVE); -} - -/** - * @ingroup iface_wl_data_device - * Sends an motion event to the client owning the resource. - * @param resource_ The client's resource - * @param time timestamp with millisecond granularity - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ -static inline void -wl_data_device_send_motion(struct wl_resource *resource_, uint32_t time, wl_fixed_t x, wl_fixed_t y) -{ - wl_resource_post_event(resource_, WL_DATA_DEVICE_MOTION, time, x, y); -} - -/** - * @ingroup iface_wl_data_device - * Sends an drop event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_data_device_send_drop(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_DATA_DEVICE_DROP); -} - -/** - * @ingroup iface_wl_data_device - * Sends an selection event to the client owning the resource. - * @param resource_ The client's resource - * @param id selection data_offer object - */ -static inline void -wl_data_device_send_selection(struct wl_resource *resource_, struct wl_resource *id) -{ - wl_resource_post_event(resource_, WL_DATA_DEVICE_SELECTION, id); -} - -#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM -#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM -/** - * @ingroup iface_wl_data_device_manager - * drag and drop actions - * - * This is a bitmask of the available/preferred actions in a - * drag-and-drop operation. - * - * In the compositor, the selected action is a result of matching the - * actions offered by the source and destination sides. "action" events - * with a "none" action will be sent to both source and destination if - * there is no match. All further checks will effectively happen on - * (source actions ∩ destination actions). - * - * In addition, compositors may also pick different actions in - * reaction to key modifiers being pressed. One common design that - * is used in major toolkits (and the behavior recommended for - * compositors) is: - * - * - If no modifiers are pressed, the first match (in bit order) - * will be used. - * - Pressing Shift selects "move", if enabled in the mask. - * - Pressing Control selects "copy", if enabled in the mask. - * - * Behavior beyond that is considered implementation-dependent. - * Compositors may for example bind other modifiers (like Alt/Meta) - * or drags initiated with other buttons than BTN_LEFT to specific - * actions (e.g. "ask"). - */ -enum wl_data_device_manager_dnd_action { - /** - * no action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0, - /** - * copy action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1, - /** - * move action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2, - /** - * ask action - */ - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4, -}; -#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */ - -#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID -#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID -/** - * @ingroup iface_wl_data_device_manager - * Validate a wl_data_device_manager dnd_action value. - * - * @return true on success, false on error. - * @ref wl_data_device_manager_dnd_action - */ -static inline bool -wl_data_device_manager_dnd_action_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; - if (version >= 1) - valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - if (version >= 1) - valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; - if (version >= 1) - valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; - return (value & ~valid) == 0; -} -#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_data_device_manager - * @struct wl_data_device_manager_interface - */ -struct wl_data_device_manager_interface { - /** - * create a new data source - * - * Create a new data source. - * @param id data source to create - */ - void (*create_data_source)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * create a new data device - * - * Create a new data device for a given seat. - * @param id data device to create - * @param seat seat associated with the data device - */ - void (*get_data_device)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *seat); -}; - - -/** - * @ingroup iface_wl_data_device_manager - */ -#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_data_device_manager - */ -#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1 - -#ifndef WL_SHELL_ERROR_ENUM -#define WL_SHELL_ERROR_ENUM -enum wl_shell_error { - /** - * given wl_surface has another role - */ - WL_SHELL_ERROR_ROLE = 0, -}; -#endif /* WL_SHELL_ERROR_ENUM */ - -#ifndef WL_SHELL_ERROR_ENUM_IS_VALID -#define WL_SHELL_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_shell - * Validate a wl_shell error value. - * - * @return true on success, false on error. - * @ref wl_shell_error - */ -static inline bool -wl_shell_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SHELL_ERROR_ROLE: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SHELL_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_shell - * @struct wl_shell_interface - */ -struct wl_shell_interface { - /** - * create a shell surface from a surface - * - * Create a shell surface for an existing surface. This gives the - * wl_surface the role of a shell surface. If the wl_surface - * already has another role, it raises a protocol error. - * - * Only one shell surface can be associated with a given surface. - * @param id shell surface to create - * @param surface surface to be given the shell surface role - */ - void (*get_shell_surface)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface); -}; - - -/** - * @ingroup iface_wl_shell - */ -#define WL_SHELL_GET_SHELL_SURFACE_SINCE_VERSION 1 - -#ifndef WL_SHELL_SURFACE_RESIZE_ENUM -#define WL_SHELL_SURFACE_RESIZE_ENUM -/** - * @ingroup iface_wl_shell_surface - * edge values for resizing - * - * These values are used to indicate which edge of a surface - * is being dragged in a resize operation. The server may - * use this information to adapt its behavior, e.g. choose - * an appropriate cursor image. - */ -enum wl_shell_surface_resize { - /** - * no edge - */ - WL_SHELL_SURFACE_RESIZE_NONE = 0, - /** - * top edge - */ - WL_SHELL_SURFACE_RESIZE_TOP = 1, - /** - * bottom edge - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM = 2, - /** - * left edge - */ - WL_SHELL_SURFACE_RESIZE_LEFT = 4, - /** - * top and left edges - */ - WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5, - /** - * bottom and left edges - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6, - /** - * right edge - */ - WL_SHELL_SURFACE_RESIZE_RIGHT = 8, - /** - * top and right edges - */ - WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9, - /** - * bottom and right edges - */ - WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10, -}; -#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */ - -#ifndef WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID -#define WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID -/** - * @ingroup iface_wl_shell_surface - * Validate a wl_shell_surface resize value. - * - * @return true on success, false on error. - * @ref wl_shell_surface_resize - */ -static inline bool -wl_shell_surface_resize_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_NONE; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_TOP; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_LEFT; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_TOP_LEFT; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_RIGHT; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; - if (version >= 1) - valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; - return (value & ~valid) == 0; -} -#endif /* WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID */ - -#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM -#define WL_SHELL_SURFACE_TRANSIENT_ENUM -/** - * @ingroup iface_wl_shell_surface - * details of transient behaviour - * - * These flags specify details of the expected behaviour - * of transient surfaces. Used in the set_transient request. - */ -enum wl_shell_surface_transient { - /** - * do not set keyboard focus - */ - WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1, -}; -#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */ - -#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID -#define WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID -/** - * @ingroup iface_wl_shell_surface - * Validate a wl_shell_surface transient value. - * - * @return true on success, false on error. - * @ref wl_shell_surface_transient - */ -static inline bool -wl_shell_surface_transient_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE; - return (value & ~valid) == 0; -} -#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID */ - -#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM -#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM -/** - * @ingroup iface_wl_shell_surface - * different method to set the surface fullscreen - * - * Hints to indicate to the compositor how to deal with a conflict - * between the dimensions of the surface and the dimensions of the - * output. The compositor is free to ignore this parameter. - */ -enum wl_shell_surface_fullscreen_method { - /** - * no preference, apply default policy - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0, - /** - * scale, preserve the surface's aspect ratio and center on output - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1, - /** - * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2, - /** - * no upscaling, center on output and add black borders to compensate size mismatch - */ - WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3, -}; -#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */ - -#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID -#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID -/** - * @ingroup iface_wl_shell_surface - * Validate a wl_shell_surface fullscreen_method value. - * - * @return true on success, false on error. - * @ref wl_shell_surface_fullscreen_method - */ -static inline bool -wl_shell_surface_fullscreen_method_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT: - return version >= 1; - case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE: - return version >= 1; - case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER: - return version >= 1; - case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_shell_surface - * @struct wl_shell_surface_interface - */ -struct wl_shell_surface_interface { - /** - * respond to a ping event - * - * A client must respond to a ping event with a pong request or - * the client may be deemed unresponsive. - * @param serial serial number of the ping event - */ - void (*pong)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial); - /** - * start an interactive move - * - * Start a pointer-driven move of the surface. - * - * This request must be used in response to a button press event. - * The server may ignore move requests depending on the state of - * the surface (e.g. fullscreen or maximized). - * @param seat seat whose pointer is used - * @param serial serial number of the implicit grab on the pointer - */ - void (*move)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial); - /** - * start an interactive resize - * - * Start a pointer-driven resizing of the surface. - * - * This request must be used in response to a button press event. - * The server may ignore resize requests depending on the state of - * the surface (e.g. fullscreen or maximized). - * @param seat seat whose pointer is used - * @param serial serial number of the implicit grab on the pointer - * @param edges which edge or corner is being dragged - */ - void (*resize)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial, - uint32_t edges); - /** - * make the surface a toplevel surface - * - * Map the surface as a toplevel surface. - * - * A toplevel surface is not fullscreen, maximized or transient. - */ - void (*set_toplevel)(struct wl_client *client, - struct wl_resource *resource); - /** - * make the surface a transient surface - * - * Map the surface relative to an existing surface. - * - * The x and y arguments specify the location of the upper left - * corner of the surface relative to the upper left corner of the - * parent surface, in surface-local coordinates. - * - * The flags argument controls details of the transient behaviour. - * @param parent parent surface - * @param x surface-local x coordinate - * @param y surface-local y coordinate - * @param flags transient surface behavior - */ - void (*set_transient)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *parent, - int32_t x, - int32_t y, - uint32_t flags); - /** - * make the surface a fullscreen surface - * - * Map the surface as a fullscreen surface. - * - * If an output parameter is given then the surface will be made - * fullscreen on that output. If the client does not specify the - * output then the compositor will apply its policy - usually - * choosing the output on which the surface has the biggest surface - * area. - * - * The client may specify a method to resolve a size conflict - * between the output size and the surface size - this is provided - * through the method parameter. - * - * The framerate parameter is used only when the method is set to - * "driver", to indicate the preferred framerate. A value of 0 - * indicates that the client does not care about framerate. The - * framerate is specified in mHz, that is framerate of 60000 is - * 60Hz. - * - * A method of "scale" or "driver" implies a scaling operation of - * the surface, either via a direct scaling operation or a change - * of the output mode. This will override any kind of output - * scaling, so that mapping a surface with a buffer size equal to - * the mode can fill the screen independent of buffer_scale. - * - * A method of "fill" means we don't scale up the buffer, however - * any output scale is applied. This means that you may run into an - * edge case where the application maps a buffer with the same size - * of the output mode but buffer_scale 1 (thus making a surface - * larger than the output). In this case it is allowed to downscale - * the results to fit the screen. - * - * The compositor must reply to this request with a configure event - * with the dimensions for the output on which the surface will be - * made fullscreen. - * @param method method for resolving size conflict - * @param framerate framerate in mHz - * @param output output on which the surface is to be fullscreen - */ - void (*set_fullscreen)(struct wl_client *client, - struct wl_resource *resource, - uint32_t method, - uint32_t framerate, - struct wl_resource *output); - /** - * make the surface a popup surface - * - * Map the surface as a popup. - * - * A popup surface is a transient surface with an added pointer - * grab. - * - * An existing implicit grab will be changed to owner-events mode, - * and the popup grab will continue after the implicit grab ends - * (i.e. releasing the mouse button does not cause the popup to be - * unmapped). - * - * The popup grab continues until the window is destroyed or a - * mouse button is pressed in any other client's window. A click in - * any of the client's surfaces is reported as normal, however, - * clicks in other clients' surfaces will be discarded and trigger - * the callback. - * - * The x and y arguments specify the location of the upper left - * corner of the surface relative to the upper left corner of the - * parent surface, in surface-local coordinates. - * @param seat seat whose pointer is used - * @param serial serial number of the implicit grab on the pointer - * @param parent parent surface - * @param x surface-local x coordinate - * @param y surface-local y coordinate - * @param flags transient surface behavior - */ - void (*set_popup)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat, - uint32_t serial, - struct wl_resource *parent, - int32_t x, - int32_t y, - uint32_t flags); - /** - * make the surface a maximized surface - * - * Map the surface as a maximized surface. - * - * If an output parameter is given then the surface will be - * maximized on that output. If the client does not specify the - * output then the compositor will apply its policy - usually - * choosing the output on which the surface has the biggest surface - * area. - * - * The compositor will reply with a configure event telling the - * expected new surface size. The operation is completed on the - * next buffer attach to this surface. - * - * A maximized surface typically fills the entire output it is - * bound to, except for desktop elements such as panels. This is - * the main difference between a maximized shell surface and a - * fullscreen shell surface. - * - * The details depend on the compositor implementation. - * @param output output on which the surface is to be maximized - */ - void (*set_maximized)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output); - /** - * set surface title - * - * Set a short title for the surface. - * - * This string may be used to identify the surface in a task bar, - * window list, or other user interface elements provided by the - * compositor. - * - * The string must be encoded in UTF-8. - * @param title surface title - */ - void (*set_title)(struct wl_client *client, - struct wl_resource *resource, - const char *title); - /** - * set surface class - * - * Set a class for the surface. - * - * The surface class identifies the general class of applications - * to which the surface belongs. A common convention is to use the - * file name (or the full path if it is a non-standard location) of - * the application's .desktop file as the class. - * @param class_ surface class - */ - void (*set_class)(struct wl_client *client, - struct wl_resource *resource, - const char *class_); -}; - -#define WL_SHELL_SURFACE_PING 0 -#define WL_SHELL_SURFACE_CONFIGURE 1 -#define WL_SHELL_SURFACE_POPUP_DONE 2 - -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_PING_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_CONFIGURE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_POPUP_DONE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_PONG_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_MOVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_RESIZE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_TOPLEVEL_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_TRANSIENT_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_FULLSCREEN_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_POPUP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_MAXIMIZED_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_TITLE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_shell_surface - */ -#define WL_SHELL_SURFACE_SET_CLASS_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_shell_surface - * Sends an ping event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the ping - */ -static inline void -wl_shell_surface_send_ping(struct wl_resource *resource_, uint32_t serial) -{ - wl_resource_post_event(resource_, WL_SHELL_SURFACE_PING, serial); -} - -/** - * @ingroup iface_wl_shell_surface - * Sends an configure event to the client owning the resource. - * @param resource_ The client's resource - * @param edges how the surface was resized - * @param width new width of the surface - * @param height new height of the surface - */ -static inline void -wl_shell_surface_send_configure(struct wl_resource *resource_, uint32_t edges, int32_t width, int32_t height) -{ - wl_resource_post_event(resource_, WL_SHELL_SURFACE_CONFIGURE, edges, width, height); -} - -/** - * @ingroup iface_wl_shell_surface - * Sends an popup_done event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_shell_surface_send_popup_done(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_SHELL_SURFACE_POPUP_DONE); -} - -#ifndef WL_SURFACE_ERROR_ENUM -#define WL_SURFACE_ERROR_ENUM -/** - * @ingroup iface_wl_surface - * wl_surface error values - * - * These errors can be emitted in response to wl_surface requests. - */ -enum wl_surface_error { - /** - * buffer scale value is invalid - */ - WL_SURFACE_ERROR_INVALID_SCALE = 0, - /** - * buffer transform value is invalid - */ - WL_SURFACE_ERROR_INVALID_TRANSFORM = 1, -}; -#endif /* WL_SURFACE_ERROR_ENUM */ - -#ifndef WL_SURFACE_ERROR_ENUM_IS_VALID -#define WL_SURFACE_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_surface - * Validate a wl_surface error value. - * - * @return true on success, false on error. - * @ref wl_surface_error - */ -static inline bool -wl_surface_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SURFACE_ERROR_INVALID_SCALE: - return version >= 1; - case WL_SURFACE_ERROR_INVALID_TRANSFORM: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SURFACE_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_surface - * @struct wl_surface_interface - */ -struct wl_surface_interface { - /** - * delete surface - * - * Deletes the surface and invalidates its object ID. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * set the surface contents - * - * Set a buffer as the content of this surface. - * - * The new size of the surface is calculated based on the buffer - * size transformed by the inverse buffer_transform and the inverse - * buffer_scale. This means that the supplied buffer must be an - * integer multiple of the buffer_scale. - * - * The x and y arguments specify the location of the new pending - * buffer's upper left corner, relative to the current buffer's - * upper left corner, in surface-local coordinates. In other words, - * the x and y, combined with the new surface size define in which - * directions the surface's size changes. - * - * Surface contents are double-buffered state, see - * wl_surface.commit. - * - * The initial surface contents are void; there is no content. - * wl_surface.attach assigns the given wl_buffer as the pending - * wl_buffer. wl_surface.commit makes the pending wl_buffer the new - * surface contents, and the size of the surface becomes the size - * calculated from the wl_buffer, as described above. After commit, - * there is no pending buffer until the next attach. - * - * Committing a pending wl_buffer allows the compositor to read the - * pixels in the wl_buffer. The compositor may access the pixels at - * any time after the wl_surface.commit request. When the - * compositor will not access the pixels anymore, it will send the - * wl_buffer.release event. Only after receiving wl_buffer.release, - * the client may reuse the wl_buffer. A wl_buffer that has been - * attached and then replaced by another attach instead of - * committed will not receive a release event, and is not used by - * the compositor. - * - * Destroying the wl_buffer after wl_buffer.release does not change - * the surface contents. However, if the client destroys the - * wl_buffer before receiving the wl_buffer.release event, the - * surface contents become undefined immediately. - * - * If wl_surface.attach is sent with a NULL wl_buffer, the - * following wl_surface.commit will remove the surface content. - * @param buffer buffer of surface contents - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ - void (*attach)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *buffer, - int32_t x, - int32_t y); - /** - * mark part of the surface damaged - * - * This request is used to describe the regions where the pending - * buffer is different from the current surface contents, and where - * the surface therefore needs to be repainted. The compositor - * ignores the parts of the damage that fall outside of the - * surface. - * - * Damage is double-buffered state, see wl_surface.commit. - * - * The damage rectangle is specified in surface-local coordinates, - * where x and y specify the upper left corner of the damage - * rectangle. - * - * The initial value for pending damage is empty: no damage. - * wl_surface.damage adds pending damage: the new pending damage is - * the union of old pending damage and the given rectangle. - * - * wl_surface.commit assigns pending damage as the current damage, - * and clears pending damage. The server will clear the current - * damage as it repaints the surface. - * - * Alternatively, damage can be posted with - * wl_surface.damage_buffer which uses buffer coordinates instead - * of surface coordinates, and is probably the preferred and - * intuitive way of doing this. - * @param x surface-local x coordinate - * @param y surface-local y coordinate - * @param width width of damage rectangle - * @param height height of damage rectangle - */ - void (*damage)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - /** - * request a frame throttling hint - * - * Request a notification when it is a good time to start drawing - * a new frame, by creating a frame callback. This is useful for - * throttling redrawing operations, and driving animations. - * - * When a client is animating on a wl_surface, it can use the - * 'frame' request to get notified when it is a good time to draw - * and commit the next frame of animation. If the client commits an - * update earlier than that, it is likely that some updates will - * not make it to the display, and the client is wasting resources - * by drawing too often. - * - * The frame request will take effect on the next - * wl_surface.commit. The notification will only be posted for one - * frame unless requested again. For a wl_surface, the - * notifications are posted in the order the frame requests were - * committed. - * - * The server must send the notifications so that a client will not - * send excessive updates, while still allowing the highest - * possible update rate for clients that wait for the reply before - * drawing again. The server should give some time for the client - * to draw and commit after sending the frame callback events to - * let it hit the next output refresh. - * - * A server should avoid signaling the frame callbacks if the - * surface is not visible in any way, e.g. the surface is - * off-screen, or completely obscured by other opaque surfaces. - * - * The object returned by this request will be destroyed by the - * compositor after the callback is fired and as such the client - * must not attempt to use it after that point. - * - * The callback_data passed in the callback is the current time, in - * milliseconds, with an undefined base. - * @param callback callback object for the frame request - */ - void (*frame)(struct wl_client *client, - struct wl_resource *resource, - uint32_t callback); - /** - * set opaque region - * - * This request sets the region of the surface that contains - * opaque content. - * - * The opaque region is an optimization hint for the compositor - * that lets it optimize the redrawing of content behind opaque - * regions. Setting an opaque region is not required for correct - * behaviour, but marking transparent content as opaque will result - * in repaint artifacts. - * - * The opaque region is specified in surface-local coordinates. - * - * The compositor ignores the parts of the opaque region that fall - * outside of the surface. - * - * Opaque region is double-buffered state, see wl_surface.commit. - * - * wl_surface.set_opaque_region changes the pending opaque region. - * wl_surface.commit copies the pending region to the current - * region. Otherwise, the pending and current regions are never - * changed. - * - * The initial value for an opaque region is empty. Setting the - * pending opaque region has copy semantics, and the wl_region - * object can be destroyed immediately. A NULL wl_region causes the - * pending opaque region to be set to empty. - * @param region opaque region of the surface - */ - void (*set_opaque_region)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *region); - /** - * set input region - * - * This request sets the region of the surface that can receive - * pointer and touch events. - * - * Input events happening outside of this region will try the next - * surface in the server surface stack. The compositor ignores the - * parts of the input region that fall outside of the surface. - * - * The input region is specified in surface-local coordinates. - * - * Input region is double-buffered state, see wl_surface.commit. - * - * wl_surface.set_input_region changes the pending input region. - * wl_surface.commit copies the pending region to the current - * region. Otherwise the pending and current regions are never - * changed, except cursor and icon surfaces are special cases, see - * wl_pointer.set_cursor and wl_data_device.start_drag. - * - * The initial value for an input region is infinite. That means - * the whole surface will accept input. Setting the pending input - * region has copy semantics, and the wl_region object can be - * destroyed immediately. A NULL wl_region causes the input region - * to be set to infinite. - * @param region input region of the surface - */ - void (*set_input_region)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *region); - /** - * commit pending surface state - * - * Surface state (input, opaque, and damage regions, attached - * buffers, etc.) is double-buffered. Protocol requests modify the - * pending state, as opposed to the current state in use by the - * compositor. A commit request atomically applies all pending - * state, replacing the current state. After commit, the new - * pending state is as documented for each related request. - * - * On commit, a pending wl_buffer is applied first, and all other - * state second. This means that all coordinates in double-buffered - * state are relative to the new wl_buffer coming into use, except - * for wl_surface.attach itself. If there is no pending wl_buffer, - * the coordinates are relative to the current surface contents. - * - * All requests that need a commit to become effective are - * documented to affect double-buffered state. - * - * Other interfaces may add further double-buffered surface state. - */ - void (*commit)(struct wl_client *client, - struct wl_resource *resource); - /** - * sets the buffer transformation - * - * This request sets an optional transformation on how the - * compositor interprets the contents of the buffer attached to the - * surface. The accepted values for the transform parameter are the - * values for wl_output.transform. - * - * Buffer transform is double-buffered state, see - * wl_surface.commit. - * - * A newly created surface has its buffer transformation set to - * normal. - * - * wl_surface.set_buffer_transform changes the pending buffer - * transformation. wl_surface.commit copies the pending buffer - * transformation to the current one. Otherwise, the pending and - * current values are never changed. - * - * The purpose of this request is to allow clients to render - * content according to the output transform, thus permitting the - * compositor to use certain optimizations even if the display is - * rotated. Using hardware overlays and scanning out a client - * buffer for fullscreen surfaces are examples of such - * optimizations. Those optimizations are highly dependent on the - * compositor implementation, so the use of this request should be - * considered on a case-by-case basis. - * - * Note that if the transform value includes 90 or 270 degree - * rotation, the width of the buffer will become the surface height - * and the height of the buffer will become the surface width. - * - * If transform is not one of the values from the - * wl_output.transform enum the invalid_transform protocol error is - * raised. - * @param transform transform for interpreting buffer contents - * @since 2 - */ - void (*set_buffer_transform)(struct wl_client *client, - struct wl_resource *resource, - int32_t transform); - /** - * sets the buffer scaling factor - * - * This request sets an optional scaling factor on how the - * compositor interprets the contents of the buffer attached to the - * window. - * - * Buffer scale is double-buffered state, see wl_surface.commit. - * - * A newly created surface has its buffer scale set to 1. - * - * wl_surface.set_buffer_scale changes the pending buffer scale. - * wl_surface.commit copies the pending buffer scale to the current - * one. Otherwise, the pending and current values are never - * changed. - * - * The purpose of this request is to allow clients to supply higher - * resolution buffer data for use on high resolution outputs. It is - * intended that you pick the same buffer scale as the scale of the - * output that the surface is displayed on. This means the - * compositor can avoid scaling when rendering the surface on that - * output. - * - * Note that if the scale is larger than 1, then you have to attach - * a buffer that is larger (by a factor of scale in each dimension) - * than the desired surface size. - * - * If scale is not positive the invalid_scale protocol error is - * raised. - * @param scale positive scale for interpreting buffer contents - * @since 3 - */ - void (*set_buffer_scale)(struct wl_client *client, - struct wl_resource *resource, - int32_t scale); - /** - * mark part of the surface damaged using buffer coordinates - * - * This request is used to describe the regions where the pending - * buffer is different from the current surface contents, and where - * the surface therefore needs to be repainted. The compositor - * ignores the parts of the damage that fall outside of the - * surface. - * - * Damage is double-buffered state, see wl_surface.commit. - * - * The damage rectangle is specified in buffer coordinates, where x - * and y specify the upper left corner of the damage rectangle. - * - * The initial value for pending damage is empty: no damage. - * wl_surface.damage_buffer adds pending damage: the new pending - * damage is the union of old pending damage and the given - * rectangle. - * - * wl_surface.commit assigns pending damage as the current damage, - * and clears pending damage. The server will clear the current - * damage as it repaints the surface. - * - * This request differs from wl_surface.damage in only one way - it - * takes damage in buffer coordinates instead of surface-local - * coordinates. While this generally is more intuitive than surface - * coordinates, it is especially desirable when using wp_viewport - * or when a drawing library (like EGL) is unaware of buffer scale - * and buffer transform. - * - * Note: Because buffer transformation changes and damage requests - * may be interleaved in the protocol stream, it is impossible to - * determine the actual mapping between surface and buffer damage - * until wl_surface.commit time. Therefore, compositors wishing to - * take both kinds of damage into account will have to accumulate - * damage from the two requests separately and only transform from - * one to the other after receiving the wl_surface.commit. - * @param x buffer-local x coordinate - * @param y buffer-local y coordinate - * @param width width of damage rectangle - * @param height height of damage rectangle - * @since 4 - */ - void (*damage_buffer)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height); -}; - -#define WL_SURFACE_ENTER 0 -#define WL_SURFACE_LEAVE 1 - -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_LEAVE_SINCE_VERSION 1 - -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_ATTACH_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_DAMAGE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_FRAME_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_OPAQUE_REGION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_INPUT_REGION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_COMMIT_SINCE_VERSION 1 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_BUFFER_TRANSFORM_SINCE_VERSION 2 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION 3 -/** - * @ingroup iface_wl_surface - */ -#define WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION 4 - -/** - * @ingroup iface_wl_surface - * Sends an enter event to the client owning the resource. - * @param resource_ The client's resource - * @param output output entered by the surface - */ -static inline void -wl_surface_send_enter(struct wl_resource *resource_, struct wl_resource *output) -{ - wl_resource_post_event(resource_, WL_SURFACE_ENTER, output); -} - -/** - * @ingroup iface_wl_surface - * Sends an leave event to the client owning the resource. - * @param resource_ The client's resource - * @param output output left by the surface - */ -static inline void -wl_surface_send_leave(struct wl_resource *resource_, struct wl_resource *output) -{ - wl_resource_post_event(resource_, WL_SURFACE_LEAVE, output); -} - -#ifndef WL_SEAT_CAPABILITY_ENUM -#define WL_SEAT_CAPABILITY_ENUM -/** - * @ingroup iface_wl_seat - * seat capability bitmask - * - * This is a bitmask of capabilities this seat has; if a member is - * set, then it is present on the seat. - */ -enum wl_seat_capability { - /** - * the seat has pointer devices - */ - WL_SEAT_CAPABILITY_POINTER = 1, - /** - * the seat has one or more keyboards - */ - WL_SEAT_CAPABILITY_KEYBOARD = 2, - /** - * the seat has touch devices - */ - WL_SEAT_CAPABILITY_TOUCH = 4, -}; -#endif /* WL_SEAT_CAPABILITY_ENUM */ - -#ifndef WL_SEAT_CAPABILITY_ENUM_IS_VALID -#define WL_SEAT_CAPABILITY_ENUM_IS_VALID -/** - * @ingroup iface_wl_seat - * Validate a wl_seat capability value. - * - * @return true on success, false on error. - * @ref wl_seat_capability - */ -static inline bool -wl_seat_capability_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= WL_SEAT_CAPABILITY_POINTER; - if (version >= 1) - valid |= WL_SEAT_CAPABILITY_KEYBOARD; - if (version >= 1) - valid |= WL_SEAT_CAPABILITY_TOUCH; - return (value & ~valid) == 0; -} -#endif /* WL_SEAT_CAPABILITY_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_seat - * @struct wl_seat_interface - */ -struct wl_seat_interface { - /** - * return pointer object - * - * The ID provided will be initialized to the wl_pointer - * interface for this seat. - * - * This request only takes effect if the seat has the pointer - * capability, or has had the pointer capability in the past. It is - * a protocol violation to issue this request on a seat that has - * never had the pointer capability. - * @param id seat pointer - */ - void (*get_pointer)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * return keyboard object - * - * The ID provided will be initialized to the wl_keyboard - * interface for this seat. - * - * This request only takes effect if the seat has the keyboard - * capability, or has had the keyboard capability in the past. It - * is a protocol violation to issue this request on a seat that has - * never had the keyboard capability. - * @param id seat keyboard - */ - void (*get_keyboard)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * return touch object - * - * The ID provided will be initialized to the wl_touch interface - * for this seat. - * - * This request only takes effect if the seat has the touch - * capability, or has had the touch capability in the past. It is a - * protocol violation to issue this request on a seat that has - * never had the touch capability. - * @param id seat touch interface - */ - void (*get_touch)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id); - /** - * release the seat object - * - * Using this request a client can tell the server that it is not - * going to use the seat object anymore. - * @since 5 - */ - void (*release)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_SEAT_CAPABILITIES 0 -#define WL_SEAT_NAME 1 - -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_CAPABILITIES_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_NAME_SINCE_VERSION 2 - -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_GET_POINTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_GET_KEYBOARD_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_GET_TOUCH_SINCE_VERSION 1 -/** - * @ingroup iface_wl_seat - */ -#define WL_SEAT_RELEASE_SINCE_VERSION 5 - -/** - * @ingroup iface_wl_seat - * Sends an capabilities event to the client owning the resource. - * @param resource_ The client's resource - * @param capabilities capabilities of the seat - */ -static inline void -wl_seat_send_capabilities(struct wl_resource *resource_, uint32_t capabilities) -{ - wl_resource_post_event(resource_, WL_SEAT_CAPABILITIES, capabilities); -} - -/** - * @ingroup iface_wl_seat - * Sends an name event to the client owning the resource. - * @param resource_ The client's resource - * @param name seat identifier - */ -static inline void -wl_seat_send_name(struct wl_resource *resource_, const char *name) -{ - wl_resource_post_event(resource_, WL_SEAT_NAME, name); -} - -#ifndef WL_POINTER_ERROR_ENUM -#define WL_POINTER_ERROR_ENUM -enum wl_pointer_error { - /** - * given wl_surface has another role - */ - WL_POINTER_ERROR_ROLE = 0, -}; -#endif /* WL_POINTER_ERROR_ENUM */ - -#ifndef WL_POINTER_ERROR_ENUM_IS_VALID -#define WL_POINTER_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_pointer - * Validate a wl_pointer error value. - * - * @return true on success, false on error. - * @ref wl_pointer_error - */ -static inline bool -wl_pointer_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_POINTER_ERROR_ROLE: - return version >= 1; - default: - return false; - } -} -#endif /* WL_POINTER_ERROR_ENUM_IS_VALID */ - -#ifndef WL_POINTER_BUTTON_STATE_ENUM -#define WL_POINTER_BUTTON_STATE_ENUM -/** - * @ingroup iface_wl_pointer - * physical button state - * - * Describes the physical state of a button that produced the button - * event. - */ -enum wl_pointer_button_state { - /** - * the button is not pressed - */ - WL_POINTER_BUTTON_STATE_RELEASED = 0, - /** - * the button is pressed - */ - WL_POINTER_BUTTON_STATE_PRESSED = 1, -}; -#endif /* WL_POINTER_BUTTON_STATE_ENUM */ - -#ifndef WL_POINTER_BUTTON_STATE_ENUM_IS_VALID -#define WL_POINTER_BUTTON_STATE_ENUM_IS_VALID -/** - * @ingroup iface_wl_pointer - * Validate a wl_pointer button_state value. - * - * @return true on success, false on error. - * @ref wl_pointer_button_state - */ -static inline bool -wl_pointer_button_state_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_POINTER_BUTTON_STATE_RELEASED: - return version >= 1; - case WL_POINTER_BUTTON_STATE_PRESSED: - return version >= 1; - default: - return false; - } -} -#endif /* WL_POINTER_BUTTON_STATE_ENUM_IS_VALID */ - -#ifndef WL_POINTER_AXIS_ENUM -#define WL_POINTER_AXIS_ENUM -/** - * @ingroup iface_wl_pointer - * axis types - * - * Describes the axis types of scroll events. - */ -enum wl_pointer_axis { - /** - * vertical axis - */ - WL_POINTER_AXIS_VERTICAL_SCROLL = 0, - /** - * horizontal axis - */ - WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1, -}; -#endif /* WL_POINTER_AXIS_ENUM */ - -#ifndef WL_POINTER_AXIS_ENUM_IS_VALID -#define WL_POINTER_AXIS_ENUM_IS_VALID -/** - * @ingroup iface_wl_pointer - * Validate a wl_pointer axis value. - * - * @return true on success, false on error. - * @ref wl_pointer_axis - */ -static inline bool -wl_pointer_axis_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - return version >= 1; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - return version >= 1; - default: - return false; - } -} -#endif /* WL_POINTER_AXIS_ENUM_IS_VALID */ - -#ifndef WL_POINTER_AXIS_SOURCE_ENUM -#define WL_POINTER_AXIS_SOURCE_ENUM -/** - * @ingroup iface_wl_pointer - * axis source types - * - * Describes the source types for axis events. This indicates to the - * client how an axis event was physically generated; a client may - * adjust the user interface accordingly. For example, scroll events - * from a "finger" source may be in a smooth coordinate space with - * kinetic scrolling whereas a "wheel" source may be in discrete steps - * of a number of lines. - */ -enum wl_pointer_axis_source { - /** - * a physical wheel rotation - */ - WL_POINTER_AXIS_SOURCE_WHEEL = 0, - /** - * finger on a touch surface - */ - WL_POINTER_AXIS_SOURCE_FINGER = 1, - /** - * continuous coordinate space - * - * A device generating events in a continuous coordinate space, - * but using something other than a finger. One example for this - * source is button-based scrolling where the vertical motion of a - * device is converted to scroll events while a button is held - * down. - */ - WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2, - /** - * a physical wheel tilt - * - * Indicates that the actual device is a wheel but the scroll - * event is not caused by a rotation but a (usually sideways) tilt - * of the wheel. - * @since 6 - */ - WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3, -}; -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6 -#endif /* WL_POINTER_AXIS_SOURCE_ENUM */ - -#ifndef WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID -#define WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID -/** - * @ingroup iface_wl_pointer - * Validate a wl_pointer axis_source value. - * - * @return true on success, false on error. - * @ref wl_pointer_axis_source - */ -static inline bool -wl_pointer_axis_source_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_POINTER_AXIS_SOURCE_WHEEL: - return version >= 1; - case WL_POINTER_AXIS_SOURCE_FINGER: - return version >= 1; - case WL_POINTER_AXIS_SOURCE_CONTINUOUS: - return version >= 1; - case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: - return version >= 6; - default: - return false; - } -} -#endif /* WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_pointer - * @struct wl_pointer_interface - */ -struct wl_pointer_interface { - /** - * set the pointer surface - * - * Set the pointer surface, i.e., the surface that contains the - * pointer image (cursor). This request gives the surface the role - * of a cursor. If the surface already has another role, it raises - * a protocol error. - * - * The cursor actually changes only if the pointer focus for this - * device is one of the requesting client's surfaces or the surface - * parameter is the current pointer surface. If there was a - * previous surface set with this request it is replaced. If - * surface is NULL, the pointer image is hidden. - * - * The parameters hotspot_x and hotspot_y define the position of - * the pointer surface relative to the pointer location. Its - * top-left corner is always at (x, y) - (hotspot_x, hotspot_y), - * where (x, y) are the coordinates of the pointer location, in - * surface-local coordinates. - * - * On surface.attach requests to the pointer surface, hotspot_x and - * hotspot_y are decremented by the x and y parameters passed to - * the request. Attach must be confirmed by wl_surface.commit as - * usual. - * - * The hotspot can also be updated by passing the currently set - * pointer surface to this request with new values for hotspot_x - * and hotspot_y. - * - * The current and pending input regions of the wl_surface are - * cleared, and wl_surface.set_input_region is ignored until the - * wl_surface is no longer used as the cursor. When the use as a - * cursor ends, the current and pending input regions become - * undefined, and the wl_surface is unmapped. - * @param serial serial number of the enter event - * @param surface pointer surface - * @param hotspot_x surface-local x coordinate - * @param hotspot_y surface-local y coordinate - */ - void (*set_cursor)(struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - struct wl_resource *surface, - int32_t hotspot_x, - int32_t hotspot_y); - /** - * release the pointer object - * - * Using this request a client can tell the server that it is not - * going to use the pointer object anymore. - * - * This request destroys the pointer proxy object, so clients must - * not call wl_pointer_destroy() after using this request. - * @since 3 - */ - void (*release)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_POINTER_ENTER 0 -#define WL_POINTER_LEAVE 1 -#define WL_POINTER_MOTION 2 -#define WL_POINTER_BUTTON 3 -#define WL_POINTER_AXIS 4 -#define WL_POINTER_FRAME 5 -#define WL_POINTER_AXIS_SOURCE 6 -#define WL_POINTER_AXIS_STOP 7 -#define WL_POINTER_AXIS_DISCRETE 8 - -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_LEAVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_MOTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_BUTTON_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_FRAME_SINCE_VERSION 5 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_SOURCE_SINCE_VERSION 5 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_STOP_SINCE_VERSION 5 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_AXIS_DISCRETE_SINCE_VERSION 5 - -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_SET_CURSOR_SINCE_VERSION 1 -/** - * @ingroup iface_wl_pointer - */ -#define WL_POINTER_RELEASE_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_pointer - * Sends an enter event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the enter event - * @param surface surface entered by the pointer - * @param surface_x surface-local x coordinate - * @param surface_y surface-local y coordinate - */ -static inline void -wl_pointer_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) -{ - wl_resource_post_event(resource_, WL_POINTER_ENTER, serial, surface, surface_x, surface_y); -} - -/** - * @ingroup iface_wl_pointer - * Sends an leave event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the leave event - * @param surface surface left by the pointer - */ -static inline void -wl_pointer_send_leave(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface) -{ - wl_resource_post_event(resource_, WL_POINTER_LEAVE, serial, surface); -} - -/** - * @ingroup iface_wl_pointer - * Sends an motion event to the client owning the resource. - * @param resource_ The client's resource - * @param time timestamp with millisecond granularity - * @param surface_x surface-local x coordinate - * @param surface_y surface-local y coordinate - */ -static inline void -wl_pointer_send_motion(struct wl_resource *resource_, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) -{ - wl_resource_post_event(resource_, WL_POINTER_MOTION, time, surface_x, surface_y); -} - -/** - * @ingroup iface_wl_pointer - * Sends an button event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the button event - * @param time timestamp with millisecond granularity - * @param button button that produced the event - * @param state physical state of the button - */ -static inline void -wl_pointer_send_button(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) -{ - wl_resource_post_event(resource_, WL_POINTER_BUTTON, serial, time, button, state); -} - -/** - * @ingroup iface_wl_pointer - * Sends an axis event to the client owning the resource. - * @param resource_ The client's resource - * @param time timestamp with millisecond granularity - * @param axis axis type - * @param value length of vector in surface-local coordinate space - */ -static inline void -wl_pointer_send_axis(struct wl_resource *resource_, uint32_t time, uint32_t axis, wl_fixed_t value) -{ - wl_resource_post_event(resource_, WL_POINTER_AXIS, time, axis, value); -} - -/** - * @ingroup iface_wl_pointer - * Sends an frame event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_pointer_send_frame(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_POINTER_FRAME); -} - -/** - * @ingroup iface_wl_pointer - * Sends an axis_source event to the client owning the resource. - * @param resource_ The client's resource - * @param axis_source source of the axis event - */ -static inline void -wl_pointer_send_axis_source(struct wl_resource *resource_, uint32_t axis_source) -{ - wl_resource_post_event(resource_, WL_POINTER_AXIS_SOURCE, axis_source); -} - -/** - * @ingroup iface_wl_pointer - * Sends an axis_stop event to the client owning the resource. - * @param resource_ The client's resource - * @param time timestamp with millisecond granularity - * @param axis the axis stopped with this event - */ -static inline void -wl_pointer_send_axis_stop(struct wl_resource *resource_, uint32_t time, uint32_t axis) -{ - wl_resource_post_event(resource_, WL_POINTER_AXIS_STOP, time, axis); -} - -/** - * @ingroup iface_wl_pointer - * Sends an axis_discrete event to the client owning the resource. - * @param resource_ The client's resource - * @param axis axis type - * @param discrete number of steps - */ -static inline void -wl_pointer_send_axis_discrete(struct wl_resource *resource_, uint32_t axis, int32_t discrete) -{ - wl_resource_post_event(resource_, WL_POINTER_AXIS_DISCRETE, axis, discrete); -} - -#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM -#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM -/** - * @ingroup iface_wl_keyboard - * keyboard mapping format - * - * This specifies the format of the keymap provided to the - * client with the wl_keyboard.keymap event. - */ -enum wl_keyboard_keymap_format { - /** - * no keymap; client must understand how to interpret the raw keycode - */ - WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0, - /** - * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode - */ - WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1, -}; -#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */ - -#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID -#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID -/** - * @ingroup iface_wl_keyboard - * Validate a wl_keyboard keymap_format value. - * - * @return true on success, false on error. - * @ref wl_keyboard_keymap_format - */ -static inline bool -wl_keyboard_keymap_format_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP: - return version >= 1; - case WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1: - return version >= 1; - default: - return false; - } -} -#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID */ - -#ifndef WL_KEYBOARD_KEY_STATE_ENUM -#define WL_KEYBOARD_KEY_STATE_ENUM -/** - * @ingroup iface_wl_keyboard - * physical key state - * - * Describes the physical state of a key that produced the key event. - */ -enum wl_keyboard_key_state { - /** - * key is not pressed - */ - WL_KEYBOARD_KEY_STATE_RELEASED = 0, - /** - * key is pressed - */ - WL_KEYBOARD_KEY_STATE_PRESSED = 1, -}; -#endif /* WL_KEYBOARD_KEY_STATE_ENUM */ - -#ifndef WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID -#define WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID -/** - * @ingroup iface_wl_keyboard - * Validate a wl_keyboard key_state value. - * - * @return true on success, false on error. - * @ref wl_keyboard_key_state - */ -static inline bool -wl_keyboard_key_state_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_KEYBOARD_KEY_STATE_RELEASED: - return version >= 1; - case WL_KEYBOARD_KEY_STATE_PRESSED: - return version >= 1; - default: - return false; - } -} -#endif /* WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_keyboard - * @struct wl_keyboard_interface - */ -struct wl_keyboard_interface { - /** - * release the keyboard object - * - * - * @since 3 - */ - void (*release)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_KEYBOARD_KEYMAP 0 -#define WL_KEYBOARD_ENTER 1 -#define WL_KEYBOARD_LEAVE 2 -#define WL_KEYBOARD_KEY 3 -#define WL_KEYBOARD_MODIFIERS 4 -#define WL_KEYBOARD_REPEAT_INFO 5 - -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_KEYMAP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_ENTER_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_LEAVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_KEY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_MODIFIERS_SINCE_VERSION 1 -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION 4 - -/** - * @ingroup iface_wl_keyboard - */ -#define WL_KEYBOARD_RELEASE_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_keyboard - * Sends an keymap event to the client owning the resource. - * @param resource_ The client's resource - * @param format keymap format - * @param fd keymap file descriptor - * @param size keymap size, in bytes - */ -static inline void -wl_keyboard_send_keymap(struct wl_resource *resource_, uint32_t format, int32_t fd, uint32_t size) -{ - wl_resource_post_event(resource_, WL_KEYBOARD_KEYMAP, format, fd, size); -} - -/** - * @ingroup iface_wl_keyboard - * Sends an enter event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the enter event - * @param surface surface gaining keyboard focus - * @param keys the currently pressed keys - */ -static inline void -wl_keyboard_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, struct wl_array *keys) -{ - wl_resource_post_event(resource_, WL_KEYBOARD_ENTER, serial, surface, keys); -} - -/** - * @ingroup iface_wl_keyboard - * Sends an leave event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the leave event - * @param surface surface that lost keyboard focus - */ -static inline void -wl_keyboard_send_leave(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface) -{ - wl_resource_post_event(resource_, WL_KEYBOARD_LEAVE, serial, surface); -} - -/** - * @ingroup iface_wl_keyboard - * Sends an key event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the key event - * @param time timestamp with millisecond granularity - * @param key key that produced the event - * @param state physical state of the key - */ -static inline void -wl_keyboard_send_key(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) -{ - wl_resource_post_event(resource_, WL_KEYBOARD_KEY, serial, time, key, state); -} - -/** - * @ingroup iface_wl_keyboard - * Sends an modifiers event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the modifiers event - * @param mods_depressed depressed modifiers - * @param mods_latched latched modifiers - * @param mods_locked locked modifiers - * @param group keyboard layout - */ -static inline void -wl_keyboard_send_modifiers(struct wl_resource *resource_, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) -{ - wl_resource_post_event(resource_, WL_KEYBOARD_MODIFIERS, serial, mods_depressed, mods_latched, mods_locked, group); -} - -/** - * @ingroup iface_wl_keyboard - * Sends an repeat_info event to the client owning the resource. - * @param resource_ The client's resource - * @param rate the rate of repeating keys in characters per second - * @param delay delay in milliseconds since key down until repeating starts - */ -static inline void -wl_keyboard_send_repeat_info(struct wl_resource *resource_, int32_t rate, int32_t delay) -{ - wl_resource_post_event(resource_, WL_KEYBOARD_REPEAT_INFO, rate, delay); -} - -/** - * @ingroup iface_wl_touch - * @struct wl_touch_interface - */ -struct wl_touch_interface { - /** - * release the touch object - * - * - * @since 3 - */ - void (*release)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_TOUCH_DOWN 0 -#define WL_TOUCH_UP 1 -#define WL_TOUCH_MOTION 2 -#define WL_TOUCH_FRAME 3 -#define WL_TOUCH_CANCEL 4 -#define WL_TOUCH_SHAPE 5 -#define WL_TOUCH_ORIENTATION 6 - -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_DOWN_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_UP_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_MOTION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_FRAME_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_CANCEL_SINCE_VERSION 1 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_SHAPE_SINCE_VERSION 6 -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_ORIENTATION_SINCE_VERSION 6 - -/** - * @ingroup iface_wl_touch - */ -#define WL_TOUCH_RELEASE_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_touch - * Sends an down event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the touch down event - * @param time timestamp with millisecond granularity - * @param surface surface touched - * @param id the unique ID of this touch point - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ -static inline void -wl_touch_send_down(struct wl_resource *resource_, uint32_t serial, uint32_t time, struct wl_resource *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) -{ - wl_resource_post_event(resource_, WL_TOUCH_DOWN, serial, time, surface, id, x, y); -} - -/** - * @ingroup iface_wl_touch - * Sends an up event to the client owning the resource. - * @param resource_ The client's resource - * @param serial serial number of the touch up event - * @param time timestamp with millisecond granularity - * @param id the unique ID of this touch point - */ -static inline void -wl_touch_send_up(struct wl_resource *resource_, uint32_t serial, uint32_t time, int32_t id) -{ - wl_resource_post_event(resource_, WL_TOUCH_UP, serial, time, id); -} - -/** - * @ingroup iface_wl_touch - * Sends an motion event to the client owning the resource. - * @param resource_ The client's resource - * @param time timestamp with millisecond granularity - * @param id the unique ID of this touch point - * @param x surface-local x coordinate - * @param y surface-local y coordinate - */ -static inline void -wl_touch_send_motion(struct wl_resource *resource_, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) -{ - wl_resource_post_event(resource_, WL_TOUCH_MOTION, time, id, x, y); -} - -/** - * @ingroup iface_wl_touch - * Sends an frame event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_touch_send_frame(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_TOUCH_FRAME); -} - -/** - * @ingroup iface_wl_touch - * Sends an cancel event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_touch_send_cancel(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_TOUCH_CANCEL); -} - -/** - * @ingroup iface_wl_touch - * Sends an shape event to the client owning the resource. - * @param resource_ The client's resource - * @param id the unique ID of this touch point - * @param major length of the major axis in surface-local coordinates - * @param minor length of the minor axis in surface-local coordinates - */ -static inline void -wl_touch_send_shape(struct wl_resource *resource_, int32_t id, wl_fixed_t major, wl_fixed_t minor) -{ - wl_resource_post_event(resource_, WL_TOUCH_SHAPE, id, major, minor); -} - -/** - * @ingroup iface_wl_touch - * Sends an orientation event to the client owning the resource. - * @param resource_ The client's resource - * @param id the unique ID of this touch point - * @param orientation angle between major axis and positive surface y-axis in degrees - */ -static inline void -wl_touch_send_orientation(struct wl_resource *resource_, int32_t id, wl_fixed_t orientation) -{ - wl_resource_post_event(resource_, WL_TOUCH_ORIENTATION, id, orientation); -} - -#ifndef WL_OUTPUT_SUBPIXEL_ENUM -#define WL_OUTPUT_SUBPIXEL_ENUM -/** - * @ingroup iface_wl_output - * subpixel geometry information - * - * This enumeration describes how the physical - * pixels on an output are laid out. - */ -enum wl_output_subpixel { - /** - * unknown geometry - */ - WL_OUTPUT_SUBPIXEL_UNKNOWN = 0, - /** - * no geometry - */ - WL_OUTPUT_SUBPIXEL_NONE = 1, - /** - * horizontal RGB - */ - WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2, - /** - * horizontal BGR - */ - WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3, - /** - * vertical RGB - */ - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4, - /** - * vertical BGR - */ - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5, -}; -#endif /* WL_OUTPUT_SUBPIXEL_ENUM */ - -#ifndef WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID -#define WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID -/** - * @ingroup iface_wl_output - * Validate a wl_output subpixel value. - * - * @return true on success, false on error. - * @ref wl_output_subpixel - */ -static inline bool -wl_output_subpixel_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_OUTPUT_SUBPIXEL_UNKNOWN: - return version >= 1; - case WL_OUTPUT_SUBPIXEL_NONE: - return version >= 1; - case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: - return version >= 1; - case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: - return version >= 1; - case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: - return version >= 1; - case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: - return version >= 1; - default: - return false; - } -} -#endif /* WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID */ - -#ifndef WL_OUTPUT_TRANSFORM_ENUM -#define WL_OUTPUT_TRANSFORM_ENUM -/** - * @ingroup iface_wl_output - * transform from framebuffer to output - * - * This describes the transform that a compositor will apply to a - * surface to compensate for the rotation or mirroring of an - * output device. - * - * The flipped values correspond to an initial flip around a - * vertical axis followed by rotation. - * - * The purpose is mainly to allow clients to render accordingly and - * tell the compositor, so that for fullscreen surfaces, the - * compositor will still be able to scan out directly from client - * surfaces. - */ -enum wl_output_transform { - /** - * no transform - */ - WL_OUTPUT_TRANSFORM_NORMAL = 0, - /** - * 90 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_90 = 1, - /** - * 180 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_180 = 2, - /** - * 270 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_270 = 3, - /** - * 180 degree flip around a vertical axis - */ - WL_OUTPUT_TRANSFORM_FLIPPED = 4, - /** - * flip and rotate 90 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5, - /** - * flip and rotate 180 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6, - /** - * flip and rotate 270 degrees counter-clockwise - */ - WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7, -}; -#endif /* WL_OUTPUT_TRANSFORM_ENUM */ - -#ifndef WL_OUTPUT_TRANSFORM_ENUM_IS_VALID -#define WL_OUTPUT_TRANSFORM_ENUM_IS_VALID -/** - * @ingroup iface_wl_output - * Validate a wl_output transform value. - * - * @return true on success, false on error. - * @ref wl_output_transform - */ -static inline bool -wl_output_transform_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_OUTPUT_TRANSFORM_NORMAL: - return version >= 1; - case WL_OUTPUT_TRANSFORM_90: - return version >= 1; - case WL_OUTPUT_TRANSFORM_180: - return version >= 1; - case WL_OUTPUT_TRANSFORM_270: - return version >= 1; - case WL_OUTPUT_TRANSFORM_FLIPPED: - return version >= 1; - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - return version >= 1; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - return version >= 1; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - return version >= 1; - default: - return false; - } -} -#endif /* WL_OUTPUT_TRANSFORM_ENUM_IS_VALID */ - -#ifndef WL_OUTPUT_MODE_ENUM -#define WL_OUTPUT_MODE_ENUM -/** - * @ingroup iface_wl_output - * mode information - * - * These flags describe properties of an output mode. - * They are used in the flags bitfield of the mode event. - */ -enum wl_output_mode { - /** - * indicates this is the current mode - */ - WL_OUTPUT_MODE_CURRENT = 0x1, - /** - * indicates this is the preferred mode - */ - WL_OUTPUT_MODE_PREFERRED = 0x2, -}; -#endif /* WL_OUTPUT_MODE_ENUM */ - -#ifndef WL_OUTPUT_MODE_ENUM_IS_VALID -#define WL_OUTPUT_MODE_ENUM_IS_VALID -/** - * @ingroup iface_wl_output - * Validate a wl_output mode value. - * - * @return true on success, false on error. - * @ref wl_output_mode - */ -static inline bool -wl_output_mode_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= WL_OUTPUT_MODE_CURRENT; - if (version >= 1) - valid |= WL_OUTPUT_MODE_PREFERRED; - return (value & ~valid) == 0; -} -#endif /* WL_OUTPUT_MODE_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_output - * @struct wl_output_interface - */ -struct wl_output_interface { - /** - * release the output object - * - * Using this request a client can tell the server that it is not - * going to use the output object anymore. - * @since 3 - */ - void (*release)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define WL_OUTPUT_GEOMETRY 0 -#define WL_OUTPUT_MODE 1 -#define WL_OUTPUT_DONE 2 -#define WL_OUTPUT_SCALE 3 - -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_GEOMETRY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_MODE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_DONE_SINCE_VERSION 2 -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_SCALE_SINCE_VERSION 2 - -/** - * @ingroup iface_wl_output - */ -#define WL_OUTPUT_RELEASE_SINCE_VERSION 3 - -/** - * @ingroup iface_wl_output - * Sends an geometry event to the client owning the resource. - * @param resource_ The client's resource - * @param x x position within the global compositor space - * @param y y position within the global compositor space - * @param physical_width width in millimeters of the output - * @param physical_height height in millimeters of the output - * @param subpixel subpixel orientation of the output - * @param make textual description of the manufacturer - * @param model textual description of the model - * @param transform transform that maps framebuffer to output - */ -static inline void -wl_output_send_geometry(struct wl_resource *resource_, 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 transform) -{ - wl_resource_post_event(resource_, WL_OUTPUT_GEOMETRY, x, y, physical_width, physical_height, subpixel, make, model, transform); -} - -/** - * @ingroup iface_wl_output - * Sends an mode event to the client owning the resource. - * @param resource_ The client's resource - * @param flags bitfield of mode flags - * @param width width of the mode in hardware units - * @param height height of the mode in hardware units - * @param refresh vertical refresh rate in mHz - */ -static inline void -wl_output_send_mode(struct wl_resource *resource_, uint32_t flags, int32_t width, int32_t height, int32_t refresh) -{ - wl_resource_post_event(resource_, WL_OUTPUT_MODE, flags, width, height, refresh); -} - -/** - * @ingroup iface_wl_output - * Sends an done event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -wl_output_send_done(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, WL_OUTPUT_DONE); -} - -/** - * @ingroup iface_wl_output - * Sends an scale event to the client owning the resource. - * @param resource_ The client's resource - * @param factor scaling factor of output - */ -static inline void -wl_output_send_scale(struct wl_resource *resource_, int32_t factor) -{ - wl_resource_post_event(resource_, WL_OUTPUT_SCALE, factor); -} - -/** - * @ingroup iface_wl_region - * @struct wl_region_interface - */ -struct wl_region_interface { - /** - * destroy region - * - * Destroy the region. This will invalidate the object ID. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * add rectangle to region - * - * Add the specified rectangle to the region. - * @param x region-local x coordinate - * @param y region-local y coordinate - * @param width rectangle width - * @param height rectangle height - */ - void (*add)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - /** - * subtract rectangle from region - * - * Subtract the specified rectangle from the region. - * @param x region-local x coordinate - * @param y region-local y coordinate - * @param width rectangle width - * @param height rectangle height - */ - void (*subtract)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height); -}; - - -/** - * @ingroup iface_wl_region - */ -#define WL_REGION_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_region - */ -#define WL_REGION_ADD_SINCE_VERSION 1 -/** - * @ingroup iface_wl_region - */ -#define WL_REGION_SUBTRACT_SINCE_VERSION 1 - -#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM -#define WL_SUBCOMPOSITOR_ERROR_ENUM -enum wl_subcompositor_error { - /** - * the to-be sub-surface is invalid - */ - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0, -}; -#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */ - -#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID -#define WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_subcompositor - * Validate a wl_subcompositor error value. - * - * @return true on success, false on error. - * @ref wl_subcompositor_error - */ -static inline bool -wl_subcompositor_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_subcompositor - * @struct wl_subcompositor_interface - */ -struct wl_subcompositor_interface { - /** - * unbind from the subcompositor interface - * - * Informs the server that the client will not be using this - * protocol object anymore. This does not affect any other objects, - * wl_subsurface objects included. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * give a surface the role sub-surface - * - * Create a sub-surface interface for the given surface, and - * associate it with the given parent surface. This turns a plain - * wl_surface into a sub-surface. - * - * The to-be sub-surface must not already have another role, and it - * must not have an existing wl_subsurface object. Otherwise a - * protocol error is raised. - * @param id the new sub-surface object ID - * @param surface the surface to be turned into a sub-surface - * @param parent the parent surface - */ - void (*get_subsurface)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface, - struct wl_resource *parent); -}; - - -/** - * @ingroup iface_wl_subcompositor - */ -#define WL_SUBCOMPOSITOR_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subcompositor - */ -#define WL_SUBCOMPOSITOR_GET_SUBSURFACE_SINCE_VERSION 1 - -#ifndef WL_SUBSURFACE_ERROR_ENUM -#define WL_SUBSURFACE_ERROR_ENUM -enum wl_subsurface_error { - /** - * wl_surface is not a sibling or the parent - */ - WL_SUBSURFACE_ERROR_BAD_SURFACE = 0, -}; -#endif /* WL_SUBSURFACE_ERROR_ENUM */ - -#ifndef WL_SUBSURFACE_ERROR_ENUM_IS_VALID -#define WL_SUBSURFACE_ERROR_ENUM_IS_VALID -/** - * @ingroup iface_wl_subsurface - * Validate a wl_subsurface error value. - * - * @return true on success, false on error. - * @ref wl_subsurface_error - */ -static inline bool -wl_subsurface_error_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case WL_SUBSURFACE_ERROR_BAD_SURFACE: - return version >= 1; - default: - return false; - } -} -#endif /* WL_SUBSURFACE_ERROR_ENUM_IS_VALID */ - -/** - * @ingroup iface_wl_subsurface - * @struct wl_subsurface_interface - */ -struct wl_subsurface_interface { - /** - * remove sub-surface interface - * - * The sub-surface interface is removed from the wl_surface - * object that was turned into a sub-surface with a - * wl_subcompositor.get_subsurface request. The wl_surface's - * association to the parent is deleted, and the wl_surface loses - * its role as a sub-surface. The wl_surface is unmapped. - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); - /** - * reposition the sub-surface - * - * This schedules a sub-surface position change. The sub-surface - * will be moved so that its origin (top left corner pixel) will be - * at the location x, y of the parent surface coordinate system. - * The coordinates are not restricted to the parent surface area. - * Negative values are allowed. - * - * The scheduled coordinates will take effect whenever the state of - * the parent surface is applied. When this happens depends on - * whether the parent surface is in synchronized mode or not. See - * wl_subsurface.set_sync and wl_subsurface.set_desync for details. - * - * If more than one set_position request is invoked by the client - * before the commit of the parent surface, the position of a new - * request always replaces the scheduled position from any previous - * request. - * - * The initial position is 0, 0. - * @param x x coordinate in the parent surface - * @param y y coordinate in the parent surface - */ - void (*set_position)(struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y); - /** - * restack the sub-surface - * - * This sub-surface is taken from the stack, and put back just - * above the reference surface, changing the z-order of the - * sub-surfaces. The reference surface must be one of the sibling - * surfaces, or the parent surface. Using any other surface, - * including this sub-surface, will cause a protocol error. - * - * The z-order is double-buffered. Requests are handled in order - * and applied immediately to a pending state. The final pending - * state is copied to the active state the next time the state of - * the parent surface is applied. When this happens depends on - * whether the parent surface is in synchronized mode or not. See - * wl_subsurface.set_sync and wl_subsurface.set_desync for details. - * - * A new sub-surface is initially added as the top-most in the - * stack of its siblings and parent. - * @param sibling the reference surface - */ - void (*place_above)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *sibling); - /** - * restack the sub-surface - * - * The sub-surface is placed just below the reference surface. - * See wl_subsurface.place_above. - * @param sibling the reference surface - */ - void (*place_below)(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *sibling); - /** - * set sub-surface to synchronized mode - * - * Change the commit behaviour of the sub-surface to synchronized - * mode, also described as the parent dependent mode. - * - * In synchronized mode, wl_surface.commit on a sub-surface will - * accumulate the committed state in a cache, but the state will - * not be applied and hence will not change the compositor output. - * The cached state is applied to the sub-surface immediately after - * the parent surface's state is applied. This ensures atomic - * updates of the parent and all its synchronized sub-surfaces. - * Applying the cached state will invalidate the cache, so further - * parent surface commits do not (re-)apply old state. - * - * See wl_subsurface for the recursive effect of this mode. - */ - void (*set_sync)(struct wl_client *client, - struct wl_resource *resource); - /** - * set sub-surface to desynchronized mode - * - * Change the commit behaviour of the sub-surface to - * desynchronized mode, also described as independent or freely - * running mode. - * - * In desynchronized mode, wl_surface.commit on a sub-surface will - * apply the pending state directly, without caching, as happens - * normally with a wl_surface. Calling wl_surface.commit on the - * parent surface has no effect on the sub-surface's wl_surface - * state. This mode allows a sub-surface to be updated on its own. - * - * If cached state exists when wl_surface.commit is called in - * desynchronized mode, the pending state is added to the cached - * state, and applied as a whole. This invalidates the cache. - * - * Note: even if a sub-surface is set to desynchronized, a parent - * sub-surface may override it to behave as synchronized. For - * details, see wl_subsurface. - * - * If a surface's parent surface behaves as desynchronized, then - * the cached state is applied on set_desync. - */ - void (*set_desync)(struct wl_client *client, - struct wl_resource *resource); -}; - - -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_SET_POSITION_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_PLACE_ABOVE_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_SET_SYNC_SINCE_VERSION 1 -/** - * @ingroup iface_wl_subsurface - */ -#define WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION 1 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/example.xml b/tests/data/example.xml deleted file mode 100644 index 2d769408..00000000 --- a/tests/data/example.xml +++ /dev/null @@ -1,2748 +0,0 @@ - - - - - Copyright © 2008-2011 Kristian Høgsberg - Copyright © 2010-2011 Intel Corporation - Copyright © 2012-2013 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. - - - - - The core global object. This is a special singleton object. It - is used for internal Wayland protocol features. - - - - - The sync request asks the server to emit the 'done' event - on the returned wl_callback object. Since requests are - handled in-order and events are delivered in-order, this can - be used as a barrier to ensure all previous requests and the - resulting events have been handled. - - The object returned by this request will be destroyed by the - compositor after the callback is fired and as such the client must not - attempt to use it after that point. - - The callback_data passed in the callback is the event serial. - - - - - - - This request creates a registry object that allows the client - to list and bind the global objects available from the - compositor. - - - - - - - The error event is sent out when a fatal (non-recoverable) - error has occurred. The object_id argument is the object - where the error occurred, most often in response to a request - to that object. The code identifies the error and is defined - by the object interface. As such, each interface defines its - own set of error codes. The message is a brief description - of the error, for (debugging) convenience. - - - - - - - - - These errors are global and can be emitted in response to any - server request. - - - - - - - - - This event is used internally by the object ID management - logic. When a client deletes an object, the server will send - this event to acknowledge that it has seen the delete request. - When the client receives this event, it will know that it can - safely reuse the object ID. - - - - - - - - The singleton global registry object. The server has a number of - global objects that are available to all clients. These objects - typically represent an actual object in the server (for example, - an input device) or they are singleton objects that provide - extension functionality. - - When a client creates a registry object, the registry object - will emit a global event for each global currently in the - registry. Globals come and go as a result of device or - monitor hotplugs, reconfiguration or other events, and the - registry will send out global and global_remove events to - keep the client up to date with the changes. To mark the end - of the initial burst of events, the client can use the - wl_display.sync request immediately after calling - wl_display.get_registry. - - A client can bind to a global object by using the bind - request. This creates a client-side handle that lets the object - emit events to the client and lets the client invoke requests on - the object. - - - - - Binds a new, client-created object to the server using the - specified name as the identifier. - - - - - - - - Notify the client of global objects. - - The event notifies the client that a global object with - the given name is now available, and it implements the - given version of the given interface. - - - - - - - - - Notify the client of removed global objects. - - This event notifies the client that the global identified - by name is no longer available. If the client bound to - the global using the bind request, the client should now - destroy that object. - - The object remains valid and requests to the object will be - ignored until the client destroys it, to avoid races between - the global going away and a client sending a request to it. - - - - - - - - Clients can handle the 'done' event to get notified when - the related request is done. - - - - - Notify the client when the related request is done. - - - - - - - - A compositor. This object is a singleton global. The - compositor is in charge of combining the contents of multiple - surfaces into one displayable output. - - - - - Ask the compositor to create a new surface. - - - - - - - Ask the compositor to create a new region. - - - - - - - - The wl_shm_pool object encapsulates a piece of memory shared - between the compositor and client. Through the wl_shm_pool - object, the client can allocate shared memory wl_buffer objects. - All objects created through the same pool share the same - underlying mapped memory. Reusing the mapped memory avoids the - setup/teardown overhead and is useful when interactively resizing - a surface or for many small buffers. - - - - - Create a wl_buffer object from the pool. - - The buffer is created offset bytes into the pool and has - width and height as specified. The stride argument specifies - the number of bytes from the beginning of one row to the beginning - of the next. The format is the pixel format of the buffer and - must be one of those advertised through the wl_shm.format event. - - A buffer will keep a reference to the pool it was created from - so it is valid to destroy the pool immediately after creating - a buffer from it. - - - - - - - - - - - - Destroy the shared memory pool. - - The mmapped memory will be released when all - buffers that have been created from this pool - are gone. - - - - - - This request will cause the server to remap the backing memory - for the pool from the file descriptor passed when the pool was - created, but using the new size. This request can only be - used to make the pool bigger. - - - - - - - - A singleton global object that provides support for shared - memory. - - Clients can create wl_shm_pool objects using the create_pool - request. - - At connection setup time, the wl_shm object emits one or more - format events to inform clients about the valid pixel formats - that can be used for buffers. - - - - - These errors can be emitted in response to wl_shm requests. - - - - - - - - - This describes the memory layout of an individual pixel. - - All renderers should support argb8888 and xrgb8888 but any other - formats are optional and may not be supported by the particular - renderer in use. - - The drm format codes match the macros defined in drm_fourcc.h. - The formats actually supported by the compositor will be - reported by the format event. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create a new wl_shm_pool object. - - The pool can be used to create shared memory based buffer - objects. The server will mmap size bytes of the passed file - descriptor, to use as backing memory for the pool. - - - - - - - - - Informs the client about a valid pixel format that - can be used for buffers. Known formats include - argb8888 and xrgb8888. - - - - - - - - A buffer provides the content for a wl_surface. Buffers are - created through factory interfaces such as wl_drm, wl_shm or - similar. It has a width and a height and can be attached to a - wl_surface, but the mechanism by which a client provides and - updates the contents is defined by the buffer factory interface. - - - - - Destroy a buffer. If and how you need to release the backing - storage is defined by the buffer factory interface. - - For possible side-effects to a surface, see wl_surface.attach. - - - - - - Sent when this wl_buffer is no longer used by the compositor. - The client is now free to reuse or destroy this buffer and its - backing storage. - - If a client receives a release event before the frame callback - requested in the same wl_surface.commit that attaches this - wl_buffer to a surface, then the client is immediately free to - reuse the buffer and its backing storage, and does not need a - second buffer for the next surface content update. Typically - this is possible, when the compositor maintains a copy of the - wl_surface contents, e.g. as a GL texture. This is an important - optimization for GL(ES) compositors with wl_shm clients. - - - - - - - A wl_data_offer represents a piece of data offered for transfer - by another client (the source client). It is used by the - copy-and-paste and drag-and-drop mechanisms. The offer - describes the different mime types that the data can be - converted to and provides the mechanism for transferring the - data directly from the source client. - - - - - - - - - - - - Indicate that the client can accept the given mime type, or - NULL for not accepted. - - For objects of version 2 or older, this request is used by the - client to give feedback whether the client can receive the given - mime type, or NULL if none is accepted; the feedback does not - determine whether the drag-and-drop operation succeeds or not. - - For objects of version 3 or newer, this request determines the - final result of the drag-and-drop operation. If the end result - is that no mime types were accepted, the drag-and-drop operation - will be cancelled and the corresponding drag source will receive - wl_data_source.cancelled. Clients may still use this event in - conjunction with wl_data_source.action for feedback. - - - - - - - - To transfer the offered data, the client issues this request - and indicates the mime type it wants to receive. The transfer - happens through the passed file descriptor (typically created - with the pipe system call). The source client writes the data - in the mime type representation requested and then closes the - file descriptor. - - The receiving client reads from the read end of the pipe until - EOF and then closes its end, at which point the transfer is - complete. - - This request may happen multiple times for different mime types, - both before and after wl_data_device.drop. Drag-and-drop destination - clients may preemptively fetch data or examine it more closely to - determine acceptance. - - - - - - - - Destroy the data offer. - - - - - - Sent immediately after creating the wl_data_offer object. One - event per offered mime type. - - - - - - - - - Notifies the compositor that the drag destination successfully - finished the drag-and-drop operation. - - Upon receiving this request, the compositor will emit - wl_data_source.dnd_finished on the drag source client. - - It is a client error to perform other requests than - wl_data_offer.destroy after this one. It is also an error to perform - this request after a NULL mime type has been set in - wl_data_offer.accept or no action was received through - wl_data_offer.action. - - - - - - Sets the actions that the destination side client supports for - this operation. This request may trigger the emission of - wl_data_source.action and wl_data_offer.action events if the compositor - needs to change the selected action. - - This request can be called multiple times throughout the - drag-and-drop operation, typically in response to wl_data_device.enter - or wl_data_device.motion events. - - This request determines the final result of the drag-and-drop - operation. If the end result is that no action is accepted, - the drag source will receive wl_drag_source.cancelled. - - The dnd_actions argument must contain only values expressed in the - wl_data_device_manager.dnd_actions enum, and the preferred_action - argument must only contain one of those values set, otherwise it - will result in a protocol error. - - While managing an "ask" action, the destination drag-and-drop client - may perform further wl_data_offer.receive requests, and is expected - to perform one last wl_data_offer.set_actions request with a preferred - action other than "ask" (and optionally wl_data_offer.accept) before - requesting wl_data_offer.finish, in order to convey the action selected - by the user. If the preferred action is not in the - wl_data_offer.source_actions mask, an error will be raised. - - If the "ask" action is dismissed (e.g. user cancellation), the client - is expected to perform wl_data_offer.destroy right away. - - This request can only be made on drag-and-drop offers, a protocol error - will be raised otherwise. - - - - - - - - This event indicates the actions offered by the data source. It - will be sent right after wl_data_device.enter, or anytime the source - side changes its offered actions through wl_data_source.set_actions. - - - - - - - This event indicates the action selected by the compositor after - matching the source/destination side actions. Only one action (or - none) will be offered here. - - This event can be emitted multiple times during the drag-and-drop - operation in response to destination side action changes through - wl_data_offer.set_actions. - - This event will no longer be emitted after wl_data_device.drop - happened on the drag-and-drop destination, the client must - honor the last action received, or the last preferred one set - through wl_data_offer.set_actions when handling an "ask" action. - - Compositors may also change the selected action on the fly, mainly - in response to keyboard modifier changes during the drag-and-drop - operation. - - The most recent action received is always the valid one. Prior to - receiving wl_data_device.drop, the chosen action may change (e.g. - due to keyboard modifiers being pressed). At the time of receiving - wl_data_device.drop the drag-and-drop destination must honor the - last action received. - - Action changes may still happen after wl_data_device.drop, - especially on "ask" actions, where the drag-and-drop destination - may choose another action afterwards. Action changes happening - at this stage are always the result of inter-client negotiation, the - compositor shall no longer be able to induce a different action. - - Upon "ask" actions, it is expected that the drag-and-drop destination - may potentially choose a different action and/or mime type, - based on wl_data_offer.source_actions and finally chosen by the - user (e.g. popping up a menu with the available options). The - final wl_data_offer.set_actions and wl_data_offer.accept requests - must happen before the call to wl_data_offer.finish. - - - - - - - - The wl_data_source object is the source side of a wl_data_offer. - It is created by the source client in a data transfer and - provides a way to describe the offered data and a way to respond - to requests to transfer the data. - - - - - - - - - - This request adds a mime type to the set of mime types - advertised to targets. Can be called several times to offer - multiple types. - - - - - - - Destroy the data source. - - - - - - Sent when a target accepts pointer_focus or motion events. If - a target does not accept any of the offered types, type is NULL. - - Used for feedback during drag-and-drop. - - - - - - - Request for data from the client. Send the data as the - specified mime type over the passed file descriptor, then - close it. - - - - - - - - This data source is no longer valid. There are several reasons why - this could happen: - - - The data source has been replaced by another data source. - - The drag-and-drop operation was performed, but the drop destination - did not accept any of the mime types offered through - wl_data_source.target. - - The drag-and-drop operation was performed, but the drop destination - did not select any of the actions present in the mask offered through - wl_data_source.action. - - The drag-and-drop operation was performed but didn't happen over a - surface. - - The compositor cancelled the drag-and-drop operation (e.g. compositor - dependent timeouts to avoid stale drag-and-drop transfers). - - The client should clean up and destroy this data source. - - For objects of version 2 or older, wl_data_source.cancelled will - only be emitted if the data source was replaced by another data - source. - - - - - - - - Sets the actions that the source side client supports for this - operation. This request may trigger wl_data_source.action and - wl_data_offer.action events if the compositor needs to change the - selected action. - - The dnd_actions argument must contain only values expressed in the - wl_data_device_manager.dnd_actions enum, otherwise it will result - in a protocol error. - - This request must be made once only, and can only be made on sources - used in drag-and-drop, so it must be performed before - wl_data_device.start_drag. Attempting to use the source other than - for drag-and-drop will raise a protocol error. - - - - - - - The user performed the drop action. This event does not indicate - acceptance, wl_data_source.cancelled may still be emitted afterwards - if the drop destination does not accept any mime type. - - However, this event might however not be received if the compositor - cancelled the drag-and-drop operation before this event could happen. - - Note that the data_source may still be used in the future and should - not be destroyed here. - - - - - - The drop destination finished interoperating with this data - source, so the client is now free to destroy this data source and - free all associated data. - - If the action used to perform the operation was "move", the - source can now delete the transferred data. - - - - - - This event indicates the action selected by the compositor after - matching the source/destination side actions. Only one action (or - none) will be offered here. - - This event can be emitted multiple times during the drag-and-drop - operation, mainly in response to destination side changes through - wl_data_offer.set_actions, and as the data device enters/leaves - surfaces. - - It is only possible to receive this event after - wl_data_source.dnd_drop_performed if the drag-and-drop operation - ended in an "ask" action, in which case the final wl_data_source.action - event will happen immediately before wl_data_source.dnd_finished. - - Compositors may also change the selected action on the fly, mainly - in response to keyboard modifier changes during the drag-and-drop - operation. - - The most recent action received is always the valid one. The chosen - action may change alongside negotiation (e.g. an "ask" action can turn - into a "move" operation), so the effects of the final action must - always be applied in wl_data_offer.dnd_finished. - - Clients can trigger cursor surface changes from this point, so - they reflect the current action. - - - - - - - - There is one wl_data_device per seat which can be obtained - from the global wl_data_device_manager singleton. - - A wl_data_device provides access to inter-client data transfer - mechanisms such as copy-and-paste and drag-and-drop. - - - - - - - - - This request asks the compositor to start a drag-and-drop - operation on behalf of the client. - - The source argument is the data source that provides the data - for the eventual data transfer. If source is NULL, enter, leave - and motion events are sent only to the client that initiated the - drag and the client is expected to handle the data passing - internally. - - The origin surface is the surface where the drag originates and - the client must have an active implicit grab that matches the - serial. - - The icon surface is an optional (can be NULL) surface that - provides an icon to be moved around with the cursor. Initially, - the top-left corner of the icon surface is placed at the cursor - hotspot, but subsequent wl_surface.attach request can move the - relative position. Attach requests must be confirmed with - wl_surface.commit as usual. The icon surface is given the role of - a drag-and-drop icon. If the icon surface already has another role, - it raises a protocol error. - - The current and pending input regions of the icon wl_surface are - cleared, and wl_surface.set_input_region is ignored until the - wl_surface is no longer used as the icon surface. When the use - as an icon ends, the current and pending input regions become - undefined, and the wl_surface is unmapped. - - - - - - - - - - This request asks the compositor to set the selection - to the data from the source on behalf of the client. - - To unset the selection, set the source to NULL. - - - - - - - - The data_offer event introduces a new wl_data_offer object, - which will subsequently be used in either the - data_device.enter event (for drag-and-drop) or the - data_device.selection event (for selections). Immediately - following the data_device.data_offer event, the new data_offer - object will send out data_offer.offer events to describe the - mime types it offers. - - - - - - - This event is sent when an active drag-and-drop pointer enters - a surface owned by the client. The position of the pointer at - enter time is provided by the x and y arguments, in surface-local - coordinates. - - - - - - - - - - - This event is sent when the drag-and-drop pointer leaves the - surface and the session ends. The client must destroy the - wl_data_offer introduced at enter time at this point. - - - - - - This event is sent when the drag-and-drop pointer moves within - the currently focused surface. The new position of the pointer - is provided by the x and y arguments, in surface-local - coordinates. - - - - - - - - - The event is sent when a drag-and-drop operation is ended - because the implicit grab is removed. - - The drag-and-drop destination is expected to honor the last action - received through wl_data_offer.action, if the resulting action is - "copy" or "move", the destination can still perform - wl_data_offer.receive requests, and is expected to end all - transfers with a wl_data_offer.finish request. - - If the resulting action is "ask", the action will not be considered - final. The drag-and-drop destination is expected to perform one last - wl_data_offer.set_actions request, or wl_data_offer.destroy in order - to cancel the operation. - - - - - - The selection event is sent out to notify the client of a new - wl_data_offer for the selection for this device. The - data_device.data_offer and the data_offer.offer events are - sent out immediately before this event to introduce the data - offer object. The selection event is sent to a client - immediately before receiving keyboard focus and when a new - selection is set while the client has keyboard focus. The - data_offer is valid until a new data_offer or NULL is received - or until the client loses keyboard focus. The client must - destroy the previous selection data_offer, if any, upon receiving - this event. - - - - - - - - - This request destroys the data device. - - - - - - - The wl_data_device_manager is a singleton global object that - provides access to inter-client data transfer mechanisms such as - copy-and-paste and drag-and-drop. These mechanisms are tied to - a wl_seat and this interface lets a client get a wl_data_device - corresponding to a wl_seat. - - Depending on the version bound, the objects created from the bound - wl_data_device_manager object will have different requirements for - functioning properly. See wl_data_source.set_actions, - wl_data_offer.accept and wl_data_offer.finish for details. - - - - - Create a new data source. - - - - - - - Create a new data device for a given seat. - - - - - - - - - - This is a bitmask of the available/preferred actions in a - drag-and-drop operation. - - In the compositor, the selected action is a result of matching the - actions offered by the source and destination sides. "action" events - with a "none" action will be sent to both source and destination if - there is no match. All further checks will effectively happen on - (source actions ∩ destination actions). - - In addition, compositors may also pick different actions in - reaction to key modifiers being pressed. One common design that - is used in major toolkits (and the behavior recommended for - compositors) is: - - - If no modifiers are pressed, the first match (in bit order) - will be used. - - Pressing Shift selects "move", if enabled in the mask. - - Pressing Control selects "copy", if enabled in the mask. - - Behavior beyond that is considered implementation-dependent. - Compositors may for example bind other modifiers (like Alt/Meta) - or drags initiated with other buttons than BTN_LEFT to specific - actions (e.g. "ask"). - - - - - - - - - - - This interface is implemented by servers that provide - desktop-style user interfaces. - - It allows clients to associate a wl_shell_surface with - a basic surface. - - - - - - - - - Create a shell surface for an existing surface. This gives - the wl_surface the role of a shell surface. If the wl_surface - already has another role, it raises a protocol error. - - Only one shell surface can be associated with a given surface. - - - - - - - - - An interface that may be implemented by a wl_surface, for - implementations that provide a desktop-style user interface. - - It provides requests to treat surfaces like toplevel, fullscreen - or popup windows, move, resize or maximize them, associate - metadata like title and class, etc. - - On the server side the object is automatically destroyed when - the related wl_surface is destroyed. On the client side, - wl_shell_surface_destroy() must be called before destroying - the wl_surface object. - - - - - A client must respond to a ping event with a pong request or - the client may be deemed unresponsive. - - - - - - - Start a pointer-driven move of the surface. - - This request must be used in response to a button press event. - The server may ignore move requests depending on the state of - the surface (e.g. fullscreen or maximized). - - - - - - - - These values are used to indicate which edge of a surface - is being dragged in a resize operation. The server may - use this information to adapt its behavior, e.g. choose - an appropriate cursor image. - - - - - - - - - - - - - - - Start a pointer-driven resizing of the surface. - - This request must be used in response to a button press event. - The server may ignore resize requests depending on the state of - the surface (e.g. fullscreen or maximized). - - - - - - - - - Map the surface as a toplevel surface. - - A toplevel surface is not fullscreen, maximized or transient. - - - - - - These flags specify details of the expected behaviour - of transient surfaces. Used in the set_transient request. - - - - - - - Map the surface relative to an existing surface. - - The x and y arguments specify the location of the upper left - corner of the surface relative to the upper left corner of the - parent surface, in surface-local coordinates. - - The flags argument controls details of the transient behaviour. - - - - - - - - - - Hints to indicate to the compositor how to deal with a conflict - between the dimensions of the surface and the dimensions of the - output. The compositor is free to ignore this parameter. - - - - - - - - - - Map the surface as a fullscreen surface. - - If an output parameter is given then the surface will be made - fullscreen on that output. If the client does not specify the - output then the compositor will apply its policy - usually - choosing the output on which the surface has the biggest surface - area. - - The client may specify a method to resolve a size conflict - between the output size and the surface size - this is provided - through the method parameter. - - The framerate parameter is used only when the method is set - to "driver", to indicate the preferred framerate. A value of 0 - indicates that the client does not care about framerate. The - framerate is specified in mHz, that is framerate of 60000 is 60Hz. - - A method of "scale" or "driver" implies a scaling operation of - the surface, either via a direct scaling operation or a change of - the output mode. This will override any kind of output scaling, so - that mapping a surface with a buffer size equal to the mode can - fill the screen independent of buffer_scale. - - A method of "fill" means we don't scale up the buffer, however - any output scale is applied. This means that you may run into - an edge case where the application maps a buffer with the same - size of the output mode but buffer_scale 1 (thus making a - surface larger than the output). In this case it is allowed to - downscale the results to fit the screen. - - The compositor must reply to this request with a configure event - with the dimensions for the output on which the surface will - be made fullscreen. - - - - - - - - - Map the surface as a popup. - - A popup surface is a transient surface with an added pointer - grab. - - An existing implicit grab will be changed to owner-events mode, - and the popup grab will continue after the implicit grab ends - (i.e. releasing the mouse button does not cause the popup to - be unmapped). - - The popup grab continues until the window is destroyed or a - mouse button is pressed in any other client's window. A click - in any of the client's surfaces is reported as normal, however, - clicks in other clients' surfaces will be discarded and trigger - the callback. - - The x and y arguments specify the location of the upper left - corner of the surface relative to the upper left corner of the - parent surface, in surface-local coordinates. - - - - - - - - - - - - Map the surface as a maximized surface. - - If an output parameter is given then the surface will be - maximized on that output. If the client does not specify the - output then the compositor will apply its policy - usually - choosing the output on which the surface has the biggest surface - area. - - The compositor will reply with a configure event telling - the expected new surface size. The operation is completed - on the next buffer attach to this surface. - - A maximized surface typically fills the entire output it is - bound to, except for desktop elements such as panels. This is - the main difference between a maximized shell surface and a - fullscreen shell surface. - - The details depend on the compositor implementation. - - - - - - - Set a short title for the surface. - - This string may be used to identify the surface in a task bar, - window list, or other user interface elements provided by the - compositor. - - The string must be encoded in UTF-8. - - - - - - - Set a class for the surface. - - The surface class identifies the general class of applications - to which the surface belongs. A common convention is to use the - file name (or the full path if it is a non-standard location) of - the application's .desktop file as the class. - - - - - - - Ping a client to check if it is receiving events and sending - requests. A client is expected to reply with a pong request. - - - - - - - The configure event asks the client to resize its surface. - - The size is a hint, in the sense that the client is free to - ignore it if it doesn't resize, pick a smaller size (to - satisfy aspect ratio or resize in steps of NxM pixels). - - The edges parameter provides a hint about how the surface - was resized. The client may use this information to decide - how to adjust its content to the new size (e.g. a scrolling - area might adjust its content position to leave the viewable - content unmoved). - - The client is free to dismiss all but the last configure - event it received. - - The width and height arguments specify the size of the window - in surface-local coordinates. - - - - - - - - - The popup_done event is sent out when a popup grab is broken, - that is, when the user clicks a surface that doesn't belong - to the client owning the popup surface. - - - - - - - A surface is a rectangular area that is displayed on the screen. - It has a location, size and pixel contents. - - The size of a surface (and relative positions on it) is described - in surface-local coordinates, which may differ from the buffer - coordinates of the pixel content, in case a buffer_transform - or a buffer_scale is used. - - A surface without a "role" is fairly useless: a compositor does - not know where, when or how to present it. The role is the - purpose of a wl_surface. Examples of roles are a cursor for a - pointer (as set by wl_pointer.set_cursor), a drag icon - (wl_data_device.start_drag), a sub-surface - (wl_subcompositor.get_subsurface), and a window as defined by a - shell protocol (e.g. wl_shell.get_shell_surface). - - A surface can have only one role at a time. Initially a - wl_surface does not have a role. Once a wl_surface is given a - role, it is set permanently for the whole lifetime of the - wl_surface object. Giving the current role again is allowed, - unless explicitly forbidden by the relevant interface - specification. - - Surface roles are given by requests in other interfaces such as - wl_pointer.set_cursor. The request should explicitly mention - that this request gives a role to a wl_surface. Often, this - request also creates a new protocol object that represents the - role and adds additional functionality to wl_surface. When a - client wants to destroy a wl_surface, they must destroy this 'role - object' before the wl_surface. - - Destroying the role object does not remove the role from the - wl_surface, but it may stop the wl_surface from "playing the role". - For instance, if a wl_subsurface object is destroyed, the wl_surface - it was created for will be unmapped and forget its position and - z-order. It is allowed to create a wl_subsurface for the same - wl_surface again, but it is not allowed to use the wl_surface as - a cursor (cursor is a different role than sub-surface, and role - switching is not allowed). - - - - - These errors can be emitted in response to wl_surface requests. - - - - - - - - Deletes the surface and invalidates its object ID. - - - - - - Set a buffer as the content of this surface. - - The new size of the surface is calculated based on the buffer - size transformed by the inverse buffer_transform and the - inverse buffer_scale. This means that the supplied buffer - must be an integer multiple of the buffer_scale. - - The x and y arguments specify the location of the new pending - buffer's upper left corner, relative to the current buffer's upper - left corner, in surface-local coordinates. In other words, the - x and y, combined with the new surface size define in which - directions the surface's size changes. - - Surface contents are double-buffered state, see wl_surface.commit. - - The initial surface contents are void; there is no content. - wl_surface.attach assigns the given wl_buffer as the pending - wl_buffer. wl_surface.commit makes the pending wl_buffer the new - surface contents, and the size of the surface becomes the size - calculated from the wl_buffer, as described above. After commit, - there is no pending buffer until the next attach. - - Committing a pending wl_buffer allows the compositor to read the - pixels in the wl_buffer. The compositor may access the pixels at - any time after the wl_surface.commit request. When the compositor - will not access the pixels anymore, it will send the - wl_buffer.release event. Only after receiving wl_buffer.release, - the client may reuse the wl_buffer. A wl_buffer that has been - attached and then replaced by another attach instead of committed - will not receive a release event, and is not used by the - compositor. - - Destroying the wl_buffer after wl_buffer.release does not change - the surface contents. However, if the client destroys the - wl_buffer before receiving the wl_buffer.release event, the surface - contents become undefined immediately. - - If wl_surface.attach is sent with a NULL wl_buffer, the - following wl_surface.commit will remove the surface content. - - - - - - - - - This request is used to describe the regions where the pending - buffer is different from the current surface contents, and where - the surface therefore needs to be repainted. The compositor - ignores the parts of the damage that fall outside of the surface. - - Damage is double-buffered state, see wl_surface.commit. - - The damage rectangle is specified in surface-local coordinates, - where x and y specify the upper left corner of the damage rectangle. - - The initial value for pending damage is empty: no damage. - wl_surface.damage adds pending damage: the new pending damage - is the union of old pending damage and the given rectangle. - - wl_surface.commit assigns pending damage as the current damage, - and clears pending damage. The server will clear the current - damage as it repaints the surface. - - Alternatively, damage can be posted with wl_surface.damage_buffer - which uses buffer coordinates instead of surface coordinates, - and is probably the preferred and intuitive way of doing this. - - - - - - - - - - Request a notification when it is a good time to start drawing a new - frame, by creating a frame callback. This is useful for throttling - redrawing operations, and driving animations. - - When a client is animating on a wl_surface, it can use the 'frame' - request to get notified when it is a good time to draw and commit the - next frame of animation. If the client commits an update earlier than - that, it is likely that some updates will not make it to the display, - and the client is wasting resources by drawing too often. - - The frame request will take effect on the next wl_surface.commit. - The notification will only be posted for one frame unless - requested again. For a wl_surface, the notifications are posted in - the order the frame requests were committed. - - The server must send the notifications so that a client - will not send excessive updates, while still allowing - the highest possible update rate for clients that wait for the reply - before drawing again. The server should give some time for the client - to draw and commit after sending the frame callback events to let it - hit the next output refresh. - - A server should avoid signaling the frame callbacks if the - surface is not visible in any way, e.g. the surface is off-screen, - or completely obscured by other opaque surfaces. - - The object returned by this request will be destroyed by the - compositor after the callback is fired and as such the client must not - attempt to use it after that point. - - The callback_data passed in the callback is the current time, in - milliseconds, with an undefined base. - - - - - - - This request sets the region of the surface that contains - opaque content. - - The opaque region is an optimization hint for the compositor - that lets it optimize the redrawing of content behind opaque - regions. Setting an opaque region is not required for correct - behaviour, but marking transparent content as opaque will result - in repaint artifacts. - - The opaque region is specified in surface-local coordinates. - - The compositor ignores the parts of the opaque region that fall - outside of the surface. - - Opaque region is double-buffered state, see wl_surface.commit. - - wl_surface.set_opaque_region changes the pending opaque region. - wl_surface.commit copies the pending region to the current region. - Otherwise, the pending and current regions are never changed. - - The initial value for an opaque region is empty. Setting the pending - opaque region has copy semantics, and the wl_region object can be - destroyed immediately. A NULL wl_region causes the pending opaque - region to be set to empty. - - - - - - - This request sets the region of the surface that can receive - pointer and touch events. - - Input events happening outside of this region will try the next - surface in the server surface stack. The compositor ignores the - parts of the input region that fall outside of the surface. - - The input region is specified in surface-local coordinates. - - Input region is double-buffered state, see wl_surface.commit. - - wl_surface.set_input_region changes the pending input region. - wl_surface.commit copies the pending region to the current region. - Otherwise the pending and current regions are never changed, - except cursor and icon surfaces are special cases, see - wl_pointer.set_cursor and wl_data_device.start_drag. - - The initial value for an input region is infinite. That means the - whole surface will accept input. Setting the pending input region - has copy semantics, and the wl_region object can be destroyed - immediately. A NULL wl_region causes the input region to be set - to infinite. - - - - - - - Surface state (input, opaque, and damage regions, attached buffers, - etc.) is double-buffered. Protocol requests modify the pending state, - as opposed to the current state in use by the compositor. A commit - request atomically applies all pending state, replacing the current - state. After commit, the new pending state is as documented for each - related request. - - On commit, a pending wl_buffer is applied first, and all other state - second. This means that all coordinates in double-buffered state are - relative to the new wl_buffer coming into use, except for - wl_surface.attach itself. If there is no pending wl_buffer, the - coordinates are relative to the current surface contents. - - All requests that need a commit to become effective are documented - to affect double-buffered state. - - Other interfaces may add further double-buffered surface state. - - - - - - This is emitted whenever a surface's creation, movement, or resizing - results in some part of it being within the scanout region of an - output. - - Note that a surface may be overlapping with zero or more outputs. - - - - - - - This is emitted whenever a surface's creation, movement, or resizing - results in it no longer having any part of it within the scanout region - of an output. - - - - - - - - - This request sets an optional transformation on how the compositor - interprets the contents of the buffer attached to the surface. The - accepted values for the transform parameter are the values for - wl_output.transform. - - Buffer transform is double-buffered state, see wl_surface.commit. - - A newly created surface has its buffer transformation set to normal. - - wl_surface.set_buffer_transform changes the pending buffer - transformation. wl_surface.commit copies the pending buffer - transformation to the current one. Otherwise, the pending and current - values are never changed. - - The purpose of this request is to allow clients to render content - according to the output transform, thus permitting the compositor to - use certain optimizations even if the display is rotated. Using - hardware overlays and scanning out a client buffer for fullscreen - surfaces are examples of such optimizations. Those optimizations are - highly dependent on the compositor implementation, so the use of this - request should be considered on a case-by-case basis. - - Note that if the transform value includes 90 or 270 degree rotation, - the width of the buffer will become the surface height and the height - of the buffer will become the surface width. - - If transform is not one of the values from the - wl_output.transform enum the invalid_transform protocol error - is raised. - - - - - - - - - This request sets an optional scaling factor on how the compositor - interprets the contents of the buffer attached to the window. - - Buffer scale is double-buffered state, see wl_surface.commit. - - A newly created surface has its buffer scale set to 1. - - wl_surface.set_buffer_scale changes the pending buffer scale. - wl_surface.commit copies the pending buffer scale to the current one. - Otherwise, the pending and current values are never changed. - - The purpose of this request is to allow clients to supply higher - resolution buffer data for use on high resolution outputs. It is - intended that you pick the same buffer scale as the scale of the - output that the surface is displayed on. This means the compositor - can avoid scaling when rendering the surface on that output. - - Note that if the scale is larger than 1, then you have to attach - a buffer that is larger (by a factor of scale in each dimension) - than the desired surface size. - - If scale is not positive the invalid_scale protocol error is - raised. - - - - - - - - This request is used to describe the regions where the pending - buffer is different from the current surface contents, and where - the surface therefore needs to be repainted. The compositor - ignores the parts of the damage that fall outside of the surface. - - Damage is double-buffered state, see wl_surface.commit. - - The damage rectangle is specified in buffer coordinates, - where x and y specify the upper left corner of the damage rectangle. - - The initial value for pending damage is empty: no damage. - wl_surface.damage_buffer adds pending damage: the new pending - damage is the union of old pending damage and the given rectangle. - - wl_surface.commit assigns pending damage as the current damage, - and clears pending damage. The server will clear the current - damage as it repaints the surface. - - This request differs from wl_surface.damage in only one way - it - takes damage in buffer coordinates instead of surface-local - coordinates. While this generally is more intuitive than surface - coordinates, it is especially desirable when using wp_viewport - or when a drawing library (like EGL) is unaware of buffer scale - and buffer transform. - - Note: Because buffer transformation changes and damage requests may - be interleaved in the protocol stream, it is impossible to determine - the actual mapping between surface and buffer damage until - wl_surface.commit time. Therefore, compositors wishing to take both - kinds of damage into account will have to accumulate damage from the - two requests separately and only transform from one to the other - after receiving the wl_surface.commit. - - - - - - - - - - - A seat is a group of keyboards, pointer and touch devices. This - object is published as a global during start up, or when such a - device is hot plugged. A seat typically has a pointer and - maintains a keyboard focus and a pointer focus. - - - - - This is a bitmask of capabilities this seat has; if a member is - set, then it is present on the seat. - - - - - - - - - This is emitted whenever a seat gains or loses the pointer, - keyboard or touch capabilities. The argument is a capability - enum containing the complete set of capabilities this seat has. - - When the pointer capability is added, a client may create a - wl_pointer object using the wl_seat.get_pointer request. This object - will receive pointer events until the capability is removed in the - future. - - When the pointer capability is removed, a client should destroy the - wl_pointer objects associated with the seat where the capability was - removed, using the wl_pointer.release request. No further pointer - events will be received on these objects. - - In some compositors, if a seat regains the pointer capability and a - client has a previously obtained wl_pointer object of version 4 or - less, that object may start sending pointer events again. This - behavior is considered a misinterpretation of the intended behavior - and must not be relied upon by the client. wl_pointer objects of - version 5 or later must not send events if created before the most - recent event notifying the client of an added pointer capability. - - The above behavior also applies to wl_keyboard and wl_touch with the - keyboard and touch capabilities, respectively. - - - - - - - The ID provided will be initialized to the wl_pointer interface - for this seat. - - This request only takes effect if the seat has the pointer - capability, or has had the pointer capability in the past. - It is a protocol violation to issue this request on a seat that has - never had the pointer capability. - - - - - - - The ID provided will be initialized to the wl_keyboard interface - for this seat. - - This request only takes effect if the seat has the keyboard - capability, or has had the keyboard capability in the past. - It is a protocol violation to issue this request on a seat that has - never had the keyboard capability. - - - - - - - The ID provided will be initialized to the wl_touch interface - for this seat. - - This request only takes effect if the seat has the touch - capability, or has had the touch capability in the past. - It is a protocol violation to issue this request on a seat that has - never had the touch capability. - - - - - - - - - In a multiseat configuration this can be used by the client to help - identify which physical devices the seat represents. Based on - the seat configuration used by the compositor. - - - - - - - - - Using this request a client can tell the server that it is not going to - use the seat object anymore. - - - - - - - - The wl_pointer interface represents one or more input devices, - such as mice, which control the pointer location and pointer_focus - of a seat. - - The wl_pointer interface generates motion, enter and leave - events for the surfaces that the pointer is located over, - and button and axis events for button presses, button releases - and scrolling. - - - - - - - - - Set the pointer surface, i.e., the surface that contains the - pointer image (cursor). This request gives the surface the role - of a cursor. If the surface already has another role, it raises - a protocol error. - - The cursor actually changes only if the pointer - focus for this device is one of the requesting client's surfaces - or the surface parameter is the current pointer surface. If - there was a previous surface set with this request it is - replaced. If surface is NULL, the pointer image is hidden. - - The parameters hotspot_x and hotspot_y define the position of - the pointer surface relative to the pointer location. Its - top-left corner is always at (x, y) - (hotspot_x, hotspot_y), - where (x, y) are the coordinates of the pointer location, in - surface-local coordinates. - - On surface.attach requests to the pointer surface, hotspot_x - and hotspot_y are decremented by the x and y parameters - passed to the request. Attach must be confirmed by - wl_surface.commit as usual. - - The hotspot can also be updated by passing the currently set - pointer surface to this request with new values for hotspot_x - and hotspot_y. - - The current and pending input regions of the wl_surface are - cleared, and wl_surface.set_input_region is ignored until the - wl_surface is no longer used as the cursor. When the use as a - cursor ends, the current and pending input regions become - undefined, and the wl_surface is unmapped. - - - - - - - - - - Notification that this seat's pointer is focused on a certain - surface. - - When a seat's focus enters a surface, the pointer image - is undefined and a client should respond to this event by setting - an appropriate pointer image with the set_cursor request. - - - - - - - - - - Notification that this seat's pointer is no longer focused on - a certain surface. - - The leave notification is sent before the enter notification - for the new focus. - - - - - - - - Notification of pointer location change. The arguments - surface_x and surface_y are the location relative to the - focused surface. - - - - - - - - - Describes the physical state of a button that produced the button - event. - - - - - - - - Mouse button click and release notifications. - - The location of the click is given by the last motion or - enter event. - The time argument is a timestamp with millisecond - granularity, with an undefined base. - - The button is a button code as defined in the Linux kernel's - linux/input-event-codes.h header file, e.g. BTN_LEFT. - - Any 16-bit button code value is reserved for future additions to the - kernel's event code list. All other button codes above 0xFFFF are - currently undefined but may be used in future versions of this - protocol. - - - - - - - - - - Describes the axis types of scroll events. - - - - - - - - Scroll and other axis notifications. - - For scroll events (vertical and horizontal scroll axes), the - value parameter is the length of a vector along the specified - axis in a coordinate space identical to those of motion events, - representing a relative movement along the specified axis. - - For devices that support movements non-parallel to axes multiple - axis events will be emitted. - - When applicable, for example for touch pads, the server can - choose to emit scroll events where the motion vector is - equivalent to a motion event vector. - - When applicable, a client can transform its content relative to the - scroll distance. - - - - - - - - - - - Using this request a client can tell the server that it is not going to - use the pointer object anymore. - - This request destroys the pointer proxy object, so clients must not call - wl_pointer_destroy() after using this request. - - - - - - - - Indicates the end of a set of events that logically belong together. - A client is expected to accumulate the data in all events within the - frame before proceeding. - - All wl_pointer events before a wl_pointer.frame event belong - logically together. For example, in a diagonal scroll motion the - compositor will send an optional wl_pointer.axis_source event, two - wl_pointer.axis events (horizontal and vertical) and finally a - wl_pointer.frame event. The client may use this information to - calculate a diagonal vector for scrolling. - - When multiple wl_pointer.axis events occur within the same frame, - the motion vector is the combined motion of all events. - When a wl_pointer.axis and a wl_pointer.axis_stop event occur within - the same frame, this indicates that axis movement in one axis has - stopped but continues in the other axis. - When multiple wl_pointer.axis_stop events occur within the same - frame, this indicates that these axes stopped in the same instance. - - A wl_pointer.frame event is sent for every logical event group, - even if the group only contains a single wl_pointer event. - Specifically, a client may get a sequence: motion, frame, button, - frame, axis, frame, axis_stop, frame. - - The wl_pointer.enter and wl_pointer.leave events are logical events - generated by the compositor and not the hardware. These events are - also grouped by a wl_pointer.frame. When a pointer moves from one - surface to another, a compositor should group the - wl_pointer.leave event within the same wl_pointer.frame. - However, a client must not rely on wl_pointer.leave and - wl_pointer.enter being in the same wl_pointer.frame. - Compositor-specific policies may require the wl_pointer.leave and - wl_pointer.enter event being split across multiple wl_pointer.frame - groups. - - - - - - Describes the source types for axis events. This indicates to the - client how an axis event was physically generated; a client may - adjust the user interface accordingly. For example, scroll events - from a "finger" source may be in a smooth coordinate space with - kinetic scrolling whereas a "wheel" source may be in discrete steps - of a number of lines. - - - - - - A device generating events in a continuous coordinate space, but - using something other than a finger. One example for this source - is button-based scrolling where the vertical motion of a device - is converted to scroll events while a button is held down. - - - - - Indicates that the actual device is a wheel but the scroll event is - not caused by a rotation but a (usually sideways) tilt of the wheel. - - - - - - - Source information for scroll and other axes. - - This event does not occur on its own. It is sent before a - wl_pointer.frame event and carries the source information for - all events within that frame. - - The source specifies how this event was generated. If the source is - wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be - sent when the user lifts the finger off the device. - - If the source is wl_pointer.axis_source.wheel, - wl_pointer.axis_source.wheel_tilt or - wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may - or may not be sent. Whether a compositor sends an axis_stop event - for these sources is hardware-specific and implementation-dependent; - clients must not rely on receiving an axis_stop event for these - scroll sources and should treat scroll sequences from these scroll - sources as unterminated by default. - - This event is optional. If the source is unknown for a particular - axis event sequence, no event is sent. - Only one wl_pointer.axis_source event is permitted per frame. - - The order of wl_pointer.axis_discrete and wl_pointer.axis_source is - not guaranteed. - - - - - - - Stop notification for scroll and other axes. - - For some wl_pointer.axis_source types, a wl_pointer.axis_stop event - is sent to notify a client that the axis sequence has terminated. - This enables the client to implement kinetic scrolling. - See the wl_pointer.axis_source documentation for information on when - this event may be generated. - - Any wl_pointer.axis events with the same axis_source after this - event should be considered as the start of a new axis motion. - - The timestamp is to be interpreted identical to the timestamp in the - wl_pointer.axis event. The timestamp value may be the same as a - preceding wl_pointer.axis event. - - - - - - - - Discrete step information for scroll and other axes. - - This event carries the axis value of the wl_pointer.axis event in - discrete steps (e.g. mouse wheel clicks). - - This event does not occur on its own, it is coupled with a - wl_pointer.axis event that represents this axis value on a - continuous scale. The protocol guarantees that each axis_discrete - event is always followed by exactly one axis event with the same - axis number within the same wl_pointer.frame. Note that the protocol - allows for other events to occur between the axis_discrete and - its coupled axis event, including other axis_discrete or axis - events. - - This event is optional; continuous scrolling devices - like two-finger scrolling on touchpads do not have discrete - steps and do not generate this event. - - The discrete value carries the directional information. e.g. a value - of -2 is two steps towards the negative direction of this axis. - - The axis number is identical to the axis number in the associated - axis event. - - The order of wl_pointer.axis_discrete and wl_pointer.axis_source is - not guaranteed. - - - - - - - - - The wl_keyboard interface represents one or more keyboards - associated with a seat. - - - - - This specifies the format of the keymap provided to the - client with the wl_keyboard.keymap event. - - - - - - - - This event provides a file descriptor to the client which can be - memory-mapped to provide a keyboard mapping description. - - - - - - - - - Notification that this seat's keyboard focus is on a certain - surface. - - - - - - - - - Notification that this seat's keyboard focus is no longer on - a certain surface. - - The leave notification is sent before the enter notification - for the new focus. - - - - - - - - Describes the physical state of a key that produced the key event. - - - - - - - - A key was pressed or released. - The time argument is a timestamp with millisecond - granularity, with an undefined base. - - - - - - - - - - Notifies clients that the modifier and/or group state has - changed, and it should update its local state. - - - - - - - - - - - - - - - - - - - Informs the client about the keyboard's repeat rate and delay. - - This event is sent as soon as the wl_keyboard object has been created, - and is guaranteed to be received by the client before any key press - event. - - Negative values for either rate or delay are illegal. A rate of zero - will disable any repeating (regardless of the value of delay). - - This event can be sent later on as well with a new value if necessary, - so clients should continue listening for the event past the creation - of wl_keyboard. - - - - - - - - - The wl_touch interface represents a touchscreen - associated with a seat. - - Touch interactions can consist of one or more contacts. - For each contact, a series of events is generated, starting - with a down event, followed by zero or more motion events, - and ending with an up event. Events relating to the same - contact point can be identified by the ID of the sequence. - - - - - A new touch point has appeared on the surface. This touch point is - assigned a unique ID. Future events from this touch point reference - this ID. The ID ceases to be valid after a touch up event and may be - reused in the future. - - - - - - - - - - - - The touch point has disappeared. No further events will be sent for - this touch point and the touch point's ID is released and may be - reused in a future touch down event. - - - - - - - - - A touch point has changed coordinates. - - - - - - - - - - Indicates the end of a set of events that logically belong together. - A client is expected to accumulate the data in all events within the - frame before proceeding. - - A wl_touch.frame terminates at least one event but otherwise no - guarantee is provided about the set of events within a frame. A client - must assume that any state not updated in a frame is unchanged from the - previously known state. - - - - - - Sent if the compositor decides the touch stream is a global - gesture. No further events are sent to the clients from that - particular gesture. Touch cancellation applies to all touch points - currently active on this client's surface. The client is - responsible for finalizing the touch points, future touch points on - this surface may reuse the touch point ID. - - - - - - - - - - - - - - Sent when a touchpoint has changed its shape. - - This event does not occur on its own. It is sent before a - wl_touch.frame event and carries the new shape information for - any previously reported, or new touch points of that frame. - - Other events describing the touch point such as wl_touch.down, - wl_touch.motion or wl_touch.orientation may be sent within the - same wl_touch.frame. A client should treat these events as a single - logical touch point update. The order of wl_touch.shape, - wl_touch.orientation and wl_touch.motion is not guaranteed. - A wl_touch.down event is guaranteed to occur before the first - wl_touch.shape event for this touch ID but both events may occur within - the same wl_touch.frame. - - A touchpoint shape is approximated by an ellipse through the major and - minor axis length. The major axis length describes the longer diameter - of the ellipse, while the minor axis length describes the shorter - diameter. Major and minor are orthogonal and both are specified in - surface-local coordinates. The center of the ellipse is always at the - touchpoint location as reported by wl_touch.down or wl_touch.move. - - This event is only sent by the compositor if the touch device supports - shape reports. The client has to make reasonable assumptions about the - shape if it did not receive this event. - - - - - - - - - Sent when a touchpoint has changed its orientation. - - This event does not occur on its own. It is sent before a - wl_touch.frame event and carries the new shape information for - any previously reported, or new touch points of that frame. - - Other events describing the touch point such as wl_touch.down, - wl_touch.motion or wl_touch.shape may be sent within the - same wl_touch.frame. A client should treat these events as a single - logical touch point update. The order of wl_touch.shape, - wl_touch.orientation and wl_touch.motion is not guaranteed. - A wl_touch.down event is guaranteed to occur before the first - wl_touch.orientation event for this touch ID but both events may occur - within the same wl_touch.frame. - - The orientation describes the clockwise angle of a touchpoint's major - axis to the positive surface y-axis and is normalized to the -180 to - +180 degree range. The granularity of orientation depends on the touch - device, some devices only support binary rotation values between 0 and - 90 degrees. - - This event is only sent by the compositor if the touch device supports - orientation reports. - - - - - - - - - An output describes part of the compositor geometry. The - compositor works in the 'compositor coordinate system' and an - output corresponds to a rectangular area in that space that is - actually visible. This typically corresponds to a monitor that - displays part of the compositor space. This object is published - as global during start up, or when a monitor is hotplugged. - - - - - This enumeration describes how the physical - pixels on an output are laid out. - - - - - - - - - - - - This describes the transform that a compositor will apply to a - surface to compensate for the rotation or mirroring of an - output device. - - The flipped values correspond to an initial flip around a - vertical axis followed by rotation. - - The purpose is mainly to allow clients to render accordingly and - tell the compositor, so that for fullscreen surfaces, the - compositor will still be able to scan out directly from client - surfaces. - - - - - - - - - - - - - - The geometry event describes geometric properties of the output. - The event is sent when binding to the output object and whenever - any of the properties change. - - - - - - - - - - - - - - These flags describe properties of an output mode. - They are used in the flags bitfield of the mode event. - - - - - - - - The mode event describes an available mode for the output. - - The event is sent when binding to the output object and there - will always be one mode, the current mode. The event is sent - again if an output changes mode, for the mode that is now - current. In other words, the current mode is always the last - mode that was received with the current flag set. - - The size of a mode is given in physical hardware units of - the output device. This is not necessarily the same as - the output size in the global compositor space. For instance, - the output may be scaled, as described in wl_output.scale, - or transformed, as described in wl_output.transform. - - - - - - - - - - - - This event is sent after all other properties have been - sent after binding to the output object and after any - other property changes done after that. This allows - changes to the output properties to be seen as - atomic, even if they happen via multiple events. - - - - - - This event contains scaling geometry information - that is not in the geometry event. It may be sent after - binding the output object or if the output scale changes - later. If it is not sent, the client should assume a - scale of 1. - - A scale larger than 1 means that the compositor will - automatically scale surface buffers by this amount - when rendering. This is used for very high resolution - displays where applications rendering at the native - resolution would be too small to be legible. - - It is intended that scaling aware clients track the - current output of a surface, and if it is on a scaled - output it should use wl_surface.set_buffer_scale with - the scale of the output. That way the compositor can - avoid scaling the surface, and the client can supply - a higher detail image. - - - - - - - - - Using this request a client can tell the server that it is not going to - use the output object anymore. - - - - - - - A region object describes an area. - - Region objects are used to describe the opaque and input - regions of a surface. - - - - - Destroy the region. This will invalidate the object ID. - - - - - - Add the specified rectangle to the region. - - - - - - - - - - Subtract the specified rectangle from the region. - - - - - - - - - - - The global interface exposing sub-surface compositing capabilities. - A wl_surface, that has sub-surfaces associated, is called the - parent surface. Sub-surfaces can be arbitrarily nested and create - a tree of sub-surfaces. - - The root surface in a tree of sub-surfaces is the main - surface. The main surface cannot be a sub-surface, because - sub-surfaces must always have a parent. - - A main surface with its sub-surfaces forms a (compound) window. - For window management purposes, this set of wl_surface objects is - to be considered as a single window, and it should also behave as - such. - - The aim of sub-surfaces is to offload some of the compositing work - within a window from clients to the compositor. A prime example is - a video player with decorations and video in separate wl_surface - objects. This should allow the compositor to pass YUV video buffer - processing to dedicated overlay hardware when possible. - - - - - Informs the server that the client will not be using this - protocol object anymore. This does not affect any other - objects, wl_subsurface objects included. - - - - - - - - - - Create a sub-surface interface for the given surface, and - associate it with the given parent surface. This turns a - plain wl_surface into a sub-surface. - - The to-be sub-surface must not already have another role, and it - must not have an existing wl_subsurface object. Otherwise a protocol - error is raised. - - - - - - - - - - An additional interface to a wl_surface object, which has been - made a sub-surface. A sub-surface has one parent surface. A - sub-surface's size and position are not limited to that of the parent. - Particularly, a sub-surface is not automatically clipped to its - parent's area. - - A sub-surface becomes mapped, when a non-NULL wl_buffer is applied - and the parent surface is mapped. The order of which one happens - first is irrelevant. A sub-surface is hidden if the parent becomes - hidden, or if a NULL wl_buffer is applied. These rules apply - recursively through the tree of surfaces. - - The behaviour of a wl_surface.commit request on a sub-surface - depends on the sub-surface's mode. The possible modes are - synchronized and desynchronized, see methods - wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized - mode caches the wl_surface state to be applied when the parent's - state gets applied, and desynchronized mode applies the pending - wl_surface state directly. A sub-surface is initially in the - synchronized mode. - - Sub-surfaces have also other kind of state, which is managed by - wl_subsurface requests, as opposed to wl_surface requests. This - state includes the sub-surface position relative to the parent - surface (wl_subsurface.set_position), and the stacking order of - the parent and its sub-surfaces (wl_subsurface.place_above and - .place_below). This state is applied when the parent surface's - wl_surface state is applied, regardless of the sub-surface's mode. - As the exception, set_sync and set_desync are effective immediately. - - The main surface can be thought to be always in desynchronized mode, - since it does not have a parent in the sub-surfaces sense. - - Even if a sub-surface is in desynchronized mode, it will behave as - in synchronized mode, if its parent surface behaves as in - synchronized mode. This rule is applied recursively throughout the - tree of surfaces. This means, that one can set a sub-surface into - synchronized mode, and then assume that all its child and grand-child - sub-surfaces are synchronized, too, without explicitly setting them. - - If the wl_surface associated with the wl_subsurface is destroyed, the - wl_subsurface object becomes inert. Note, that destroying either object - takes effect immediately. If you need to synchronize the removal - of a sub-surface to the parent surface update, unmap the sub-surface - first by attaching a NULL wl_buffer, update parent, and then destroy - the sub-surface. - - If the parent wl_surface object is destroyed, the sub-surface is - unmapped. - - - - - The sub-surface interface is removed from the wl_surface object - that was turned into a sub-surface with a - wl_subcompositor.get_subsurface request. The wl_surface's association - to the parent is deleted, and the wl_surface loses its role as - a sub-surface. The wl_surface is unmapped. - - - - - - - - - - This schedules a sub-surface position change. - The sub-surface will be moved so that its origin (top left - corner pixel) will be at the location x, y of the parent surface - coordinate system. The coordinates are not restricted to the parent - surface area. Negative values are allowed. - - The scheduled coordinates will take effect whenever the state of the - parent surface is applied. When this happens depends on whether the - parent surface is in synchronized mode or not. See - wl_subsurface.set_sync and wl_subsurface.set_desync for details. - - If more than one set_position request is invoked by the client before - the commit of the parent surface, the position of a new request always - replaces the scheduled position from any previous request. - - The initial position is 0, 0. - - - - - - - - This sub-surface is taken from the stack, and put back just - above the reference surface, changing the z-order of the sub-surfaces. - The reference surface must be one of the sibling surfaces, or the - parent surface. Using any other surface, including this sub-surface, - will cause a protocol error. - - The z-order is double-buffered. Requests are handled in order and - applied immediately to a pending state. The final pending state is - copied to the active state the next time the state of the parent - surface is applied. When this happens depends on whether the parent - surface is in synchronized mode or not. See wl_subsurface.set_sync and - wl_subsurface.set_desync for details. - - A new sub-surface is initially added as the top-most in the stack - of its siblings and parent. - - - - - - - The sub-surface is placed just below the reference surface. - See wl_subsurface.place_above. - - - - - - - Change the commit behaviour of the sub-surface to synchronized - mode, also described as the parent dependent mode. - - In synchronized mode, wl_surface.commit on a sub-surface will - accumulate the committed state in a cache, but the state will - not be applied and hence will not change the compositor output. - The cached state is applied to the sub-surface immediately after - the parent surface's state is applied. This ensures atomic - updates of the parent and all its synchronized sub-surfaces. - Applying the cached state will invalidate the cache, so further - parent surface commits do not (re-)apply old state. - - See wl_subsurface for the recursive effect of this mode. - - - - - - Change the commit behaviour of the sub-surface to desynchronized - mode, also described as independent or freely running mode. - - In desynchronized mode, wl_surface.commit on a sub-surface will - apply the pending state directly, without caching, as happens - normally with a wl_surface. Calling wl_surface.commit on the - parent surface has no effect on the sub-surface's wl_surface - state. This mode allows a sub-surface to be updated on its own. - - If cached state exists when wl_surface.commit is called in - desynchronized mode, the pending state is added to the cached - state, and applied as a whole. This invalidates the cache. - - Note: even if a sub-surface is set to desynchronized, a parent - sub-surface may override it to behave as synchronized. For details, - see wl_subsurface. - - If a surface's parent surface behaves as desynchronized, then - the cached state is applied on set_desync. - - - - - diff --git a/tests/data/small-client-core.h b/tests/data/small-client-core.h deleted file mode 100644 index 03f889c8..00000000 --- a/tests/data/small-client-core.h +++ /dev/null @@ -1,248 +0,0 @@ -/* SCANNER TEST */ - -#ifndef SMALL_TEST_CLIENT_PROTOCOL_H -#define SMALL_TEST_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client-core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_small_test The small_test protocol - * @section page_ifaces_small_test Interfaces - * - @subpage page_iface_intf_A - the thing A - * @section page_copyright_small_test Copyright - *
- *
- * Copyright © 2016 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.
- * 
- */ -struct another_intf; -struct intf_A; -struct intf_not_here; - -#ifndef INTF_A_INTERFACE -#define INTF_A_INTERFACE -/** - * @page page_iface_intf_A intf_A - * @section page_iface_intf_A_desc Description - * - * A useless example trying to tickle the scanner. - * @section page_iface_intf_A_api API - * See @ref iface_intf_A. - */ -/** - * @defgroup iface_intf_A The intf_A interface - * - * A useless example trying to tickle the scanner. - */ -extern const struct wl_interface intf_A_interface; -#endif - -#ifndef INTF_A_FOO_ENUM -#define INTF_A_FOO_ENUM -enum intf_A_foo { - /** - * this is the first - */ - INTF_A_FOO_FIRST = 0, - /** - * this is the second - */ - INTF_A_FOO_SECOND = 1, - /** - * this is the third - * @since 2 - */ - INTF_A_FOO_THIRD = 2, - /** - * this is a negative value - * @since 2 - */ - INTF_A_FOO_NEGATIVE = -1, - /** - * this is a deprecated value - * @since 2 - * @deprecated Deprecated since version 3 - */ - INTF_A_FOO_DEPRECATED = 3, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_THIRD_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2 -#endif /* INTF_A_FOO_ENUM */ - -#ifndef INTF_A_BAR_ENUM -#define INTF_A_BAR_ENUM -enum intf_A_bar { - /** - * this is the first - */ - INTF_A_BAR_FIRST = 0x01, - /** - * this is the second - */ - INTF_A_BAR_SECOND = 0x02, - /** - * this is the third - * @since 2 - */ - INTF_A_BAR_THIRD = 0x04, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_BAR_THIRD_SINCE_VERSION 2 -#endif /* INTF_A_BAR_ENUM */ - -/** - * @ingroup iface_intf_A - * @struct intf_A_listener - */ -struct intf_A_listener { - /** - */ - void (*hey)(void *data, - struct intf_A *intf_A); - /** - * @since 2 - * @deprecated Deprecated since version 3 - */ - void (*yo)(void *data, - struct intf_A *intf_A); -}; - -/** - * @ingroup iface_intf_A - */ -static inline int -intf_A_add_listener(struct intf_A *intf_A, - const struct intf_A_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) intf_A, - (void (**)(void)) listener, data); -} - -#define INTF_A_RQ1 0 -#define INTF_A_RQ2 1 -#define INTF_A_DESTROY 2 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_HEY_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_YO_SINCE_VERSION 2 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ1_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ2_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_DESTROY_SINCE_VERSION 1 - -/** @ingroup iface_intf_A */ -static inline void -intf_A_set_user_data(struct intf_A *intf_A, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) intf_A, user_data); -} - -/** @ingroup iface_intf_A */ -static inline void * -intf_A_get_user_data(struct intf_A *intf_A) -{ - return wl_proxy_get_user_data((struct wl_proxy *) intf_A); -} - -static inline uint32_t -intf_A_get_version(struct intf_A *intf_A) -{ - return wl_proxy_get_version((struct wl_proxy *) intf_A); -} - -/** - * @ingroup iface_intf_A - */ -static inline void * -intf_A_rq1(struct intf_A *intf_A, const struct wl_interface *interface, uint32_t version) -{ - struct wl_proxy *untyped_new; - - untyped_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A, - INTF_A_RQ1, interface, version, 0, interface->name, version, NULL); - - return (void *) untyped_new; -} - -/** - * @ingroup iface_intf_A - */ -static inline struct intf_not_here * -intf_A_rq2(struct intf_A *intf_A, const char *str, int32_t i, uint32_t u, wl_fixed_t f, int32_t fd, struct another_intf *obj) -{ - struct wl_proxy *typed_new; - - typed_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A, - INTF_A_RQ2, &intf_not_here_interface, wl_proxy_get_version((struct wl_proxy *) intf_A), 0, NULL, str, i, u, f, fd, obj); - - return (struct intf_not_here *) typed_new; -} - -/** - * @ingroup iface_intf_A - */ -static inline void -intf_A_destroy(struct intf_A *intf_A) -{ - wl_proxy_marshal_flags((struct wl_proxy *) intf_A, - INTF_A_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) intf_A), WL_MARSHAL_FLAG_DESTROY); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/small-client.h b/tests/data/small-client.h deleted file mode 100644 index 0d5b6055..00000000 --- a/tests/data/small-client.h +++ /dev/null @@ -1,248 +0,0 @@ -/* SCANNER TEST */ - -#ifndef SMALL_TEST_CLIENT_PROTOCOL_H -#define SMALL_TEST_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_small_test The small_test protocol - * @section page_ifaces_small_test Interfaces - * - @subpage page_iface_intf_A - the thing A - * @section page_copyright_small_test Copyright - *
- *
- * Copyright © 2016 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.
- * 
- */ -struct another_intf; -struct intf_A; -struct intf_not_here; - -#ifndef INTF_A_INTERFACE -#define INTF_A_INTERFACE -/** - * @page page_iface_intf_A intf_A - * @section page_iface_intf_A_desc Description - * - * A useless example trying to tickle the scanner. - * @section page_iface_intf_A_api API - * See @ref iface_intf_A. - */ -/** - * @defgroup iface_intf_A The intf_A interface - * - * A useless example trying to tickle the scanner. - */ -extern const struct wl_interface intf_A_interface; -#endif - -#ifndef INTF_A_FOO_ENUM -#define INTF_A_FOO_ENUM -enum intf_A_foo { - /** - * this is the first - */ - INTF_A_FOO_FIRST = 0, - /** - * this is the second - */ - INTF_A_FOO_SECOND = 1, - /** - * this is the third - * @since 2 - */ - INTF_A_FOO_THIRD = 2, - /** - * this is a negative value - * @since 2 - */ - INTF_A_FOO_NEGATIVE = -1, - /** - * this is a deprecated value - * @since 2 - * @deprecated Deprecated since version 3 - */ - INTF_A_FOO_DEPRECATED = 3, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_THIRD_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2 -#endif /* INTF_A_FOO_ENUM */ - -#ifndef INTF_A_BAR_ENUM -#define INTF_A_BAR_ENUM -enum intf_A_bar { - /** - * this is the first - */ - INTF_A_BAR_FIRST = 0x01, - /** - * this is the second - */ - INTF_A_BAR_SECOND = 0x02, - /** - * this is the third - * @since 2 - */ - INTF_A_BAR_THIRD = 0x04, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_BAR_THIRD_SINCE_VERSION 2 -#endif /* INTF_A_BAR_ENUM */ - -/** - * @ingroup iface_intf_A - * @struct intf_A_listener - */ -struct intf_A_listener { - /** - */ - void (*hey)(void *data, - struct intf_A *intf_A); - /** - * @since 2 - * @deprecated Deprecated since version 3 - */ - void (*yo)(void *data, - struct intf_A *intf_A); -}; - -/** - * @ingroup iface_intf_A - */ -static inline int -intf_A_add_listener(struct intf_A *intf_A, - const struct intf_A_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) intf_A, - (void (**)(void)) listener, data); -} - -#define INTF_A_RQ1 0 -#define INTF_A_RQ2 1 -#define INTF_A_DESTROY 2 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_HEY_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_YO_SINCE_VERSION 2 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ1_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ2_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_DESTROY_SINCE_VERSION 1 - -/** @ingroup iface_intf_A */ -static inline void -intf_A_set_user_data(struct intf_A *intf_A, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) intf_A, user_data); -} - -/** @ingroup iface_intf_A */ -static inline void * -intf_A_get_user_data(struct intf_A *intf_A) -{ - return wl_proxy_get_user_data((struct wl_proxy *) intf_A); -} - -static inline uint32_t -intf_A_get_version(struct intf_A *intf_A) -{ - return wl_proxy_get_version((struct wl_proxy *) intf_A); -} - -/** - * @ingroup iface_intf_A - */ -static inline void * -intf_A_rq1(struct intf_A *intf_A, const struct wl_interface *interface, uint32_t version) -{ - struct wl_proxy *untyped_new; - - untyped_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A, - INTF_A_RQ1, interface, version, 0, interface->name, version, NULL); - - return (void *) untyped_new; -} - -/** - * @ingroup iface_intf_A - */ -static inline struct intf_not_here * -intf_A_rq2(struct intf_A *intf_A, const char *str, int32_t i, uint32_t u, wl_fixed_t f, int32_t fd, struct another_intf *obj) -{ - struct wl_proxy *typed_new; - - typed_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A, - INTF_A_RQ2, &intf_not_here_interface, wl_proxy_get_version((struct wl_proxy *) intf_A), 0, NULL, str, i, u, f, fd, obj); - - return (struct intf_not_here *) typed_new; -} - -/** - * @ingroup iface_intf_A - */ -static inline void -intf_A_destroy(struct intf_A *intf_A) -{ - wl_proxy_marshal_flags((struct wl_proxy *) intf_A, - INTF_A_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) intf_A), WL_MARSHAL_FLAG_DESTROY); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/small-code-core.c b/tests/data/small-code-core.c deleted file mode 100644 index b6545493..00000000 --- a/tests/data/small-code-core.c +++ /dev/null @@ -1,63 +0,0 @@ -/* SCANNER TEST */ - -/* - * Copyright © 2016 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 -#include -#include -#include "wayland-util.h" - -extern const struct wl_interface another_intf_interface; -extern const struct wl_interface intf_not_here_interface; - -static const struct wl_interface *small_test_types[] = { - NULL, - &intf_not_here_interface, - NULL, - NULL, - NULL, - NULL, - NULL, - &another_intf_interface, -}; - -static const struct wl_message intf_A_requests[] = { - { "rq1", "sun", small_test_types + 0 }, - { "rq2", "nsiufho", small_test_types + 1 }, - { "destroy", "", small_test_types + 0 }, -}; - -static const struct wl_message intf_A_events[] = { - { "hey", "", small_test_types + 0 }, - { "yo", "2", small_test_types + 0 }, -}; - -WL_EXPORT const struct wl_interface intf_A_interface = { - "intf_A", 3, - 3, intf_A_requests, - 2, intf_A_events, -}; - diff --git a/tests/data/small-code.c b/tests/data/small-code.c deleted file mode 100644 index b6545493..00000000 --- a/tests/data/small-code.c +++ /dev/null @@ -1,63 +0,0 @@ -/* SCANNER TEST */ - -/* - * Copyright © 2016 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 -#include -#include -#include "wayland-util.h" - -extern const struct wl_interface another_intf_interface; -extern const struct wl_interface intf_not_here_interface; - -static const struct wl_interface *small_test_types[] = { - NULL, - &intf_not_here_interface, - NULL, - NULL, - NULL, - NULL, - NULL, - &another_intf_interface, -}; - -static const struct wl_message intf_A_requests[] = { - { "rq1", "sun", small_test_types + 0 }, - { "rq2", "nsiufho", small_test_types + 1 }, - { "destroy", "", small_test_types + 0 }, -}; - -static const struct wl_message intf_A_events[] = { - { "hey", "", small_test_types + 0 }, - { "yo", "2", small_test_types + 0 }, -}; - -WL_EXPORT const struct wl_interface intf_A_interface = { - "intf_A", 3, - 3, intf_A_requests, - 2, intf_A_events, -}; - diff --git a/tests/data/small-private-code.c b/tests/data/small-private-code.c deleted file mode 100644 index b2bbf0a3..00000000 --- a/tests/data/small-private-code.c +++ /dev/null @@ -1,73 +0,0 @@ -/* SCANNER TEST */ - -/* - * Copyright © 2016 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 -#include -#include -#include "wayland-util.h" - -#ifndef __has_attribute -# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ -#endif - -#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) -#define WL_PRIVATE __attribute__ ((visibility("hidden"))) -#else -#define WL_PRIVATE -#endif - -extern const struct wl_interface another_intf_interface; -extern const struct wl_interface intf_not_here_interface; - -static const struct wl_interface *small_test_types[] = { - NULL, - &intf_not_here_interface, - NULL, - NULL, - NULL, - NULL, - NULL, - &another_intf_interface, -}; - -static const struct wl_message intf_A_requests[] = { - { "rq1", "sun", small_test_types + 0 }, - { "rq2", "nsiufho", small_test_types + 1 }, - { "destroy", "", small_test_types + 0 }, -}; - -static const struct wl_message intf_A_events[] = { - { "hey", "", small_test_types + 0 }, - { "yo", "2", small_test_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface intf_A_interface = { - "intf_A", 3, - 3, intf_A_requests, - 2, intf_A_events, -}; - diff --git a/tests/data/small-server-core.h b/tests/data/small-server-core.h deleted file mode 100644 index 4248d455..00000000 --- a/tests/data/small-server-core.h +++ /dev/null @@ -1,265 +0,0 @@ -/* SCANNER TEST */ - -#ifndef SMALL_TEST_SERVER_PROTOCOL_H -#define SMALL_TEST_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server-core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_small_test The small_test protocol - * @section page_ifaces_small_test Interfaces - * - @subpage page_iface_intf_A - the thing A - * @section page_copyright_small_test Copyright - *
- *
- * Copyright © 2016 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.
- * 
- */ -struct another_intf; -struct intf_A; -struct intf_not_here; - -#ifndef INTF_A_INTERFACE -#define INTF_A_INTERFACE -/** - * @page page_iface_intf_A intf_A - * @section page_iface_intf_A_desc Description - * - * A useless example trying to tickle the scanner. - * @section page_iface_intf_A_api API - * See @ref iface_intf_A. - */ -/** - * @defgroup iface_intf_A The intf_A interface - * - * A useless example trying to tickle the scanner. - */ -extern const struct wl_interface intf_A_interface; -#endif - -#ifndef INTF_A_FOO_ENUM -#define INTF_A_FOO_ENUM -enum intf_A_foo { - /** - * this is the first - */ - INTF_A_FOO_FIRST = 0, - /** - * this is the second - */ - INTF_A_FOO_SECOND = 1, - /** - * this is the third - * @since 2 - */ - INTF_A_FOO_THIRD = 2, - /** - * this is a negative value - * @since 2 - */ - INTF_A_FOO_NEGATIVE = -1, - /** - * this is a deprecated value - * @since 2 - * @deprecated Deprecated since version 3 - */ - INTF_A_FOO_DEPRECATED = 3, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_THIRD_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2 -#endif /* INTF_A_FOO_ENUM */ - -#ifndef INTF_A_FOO_ENUM_IS_VALID -#define INTF_A_FOO_ENUM_IS_VALID -/** - * @ingroup iface_intf_A - * Validate a intf_A foo value. - * - * @return true on success, false on error. - * @ref intf_A_foo - */ -static inline bool -intf_A_foo_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case INTF_A_FOO_FIRST: - return version >= 1; - case INTF_A_FOO_SECOND: - return version >= 1; - case INTF_A_FOO_THIRD: - return version >= 2; - case (uint32_t)INTF_A_FOO_NEGATIVE: - return version >= 2; - case INTF_A_FOO_DEPRECATED: - return version >= 2; - default: - return false; - } -} -#endif /* INTF_A_FOO_ENUM_IS_VALID */ - -#ifndef INTF_A_BAR_ENUM -#define INTF_A_BAR_ENUM -enum intf_A_bar { - /** - * this is the first - */ - INTF_A_BAR_FIRST = 0x01, - /** - * this is the second - */ - INTF_A_BAR_SECOND = 0x02, - /** - * this is the third - * @since 2 - */ - INTF_A_BAR_THIRD = 0x04, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_BAR_THIRD_SINCE_VERSION 2 -#endif /* INTF_A_BAR_ENUM */ - -#ifndef INTF_A_BAR_ENUM_IS_VALID -#define INTF_A_BAR_ENUM_IS_VALID -/** - * @ingroup iface_intf_A - * Validate a intf_A bar value. - * - * @return true on success, false on error. - * @ref intf_A_bar - */ -static inline bool -intf_A_bar_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= INTF_A_BAR_FIRST; - if (version >= 1) - valid |= INTF_A_BAR_SECOND; - if (version >= 2) - valid |= INTF_A_BAR_THIRD; - return (value & ~valid) == 0; -} -#endif /* INTF_A_BAR_ENUM_IS_VALID */ - -/** - * @ingroup iface_intf_A - * @struct intf_A_interface - */ -struct intf_A_interface { - /** - * @param interface name of the objects interface - * @param version version of the objects interface - */ - void (*rq1)(struct wl_client *client, - struct wl_resource *resource, - const char *interface, uint32_t version, uint32_t untyped_new); - /** - */ - void (*rq2)(struct wl_client *client, - struct wl_resource *resource, - uint32_t typed_new, - const char *str, - int32_t i, - uint32_t u, - wl_fixed_t f, - int32_t fd, - struct wl_resource *obj); - /** - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define INTF_A_HEY 0 -#define INTF_A_YO 1 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_HEY_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_YO_SINCE_VERSION 2 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ1_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ2_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_DESTROY_SINCE_VERSION 1 - -/** - * @ingroup iface_intf_A - * Sends an hey event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -intf_A_send_hey(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, INTF_A_HEY); -} - -/** - * @ingroup iface_intf_A - * Sends an yo event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -intf_A_send_yo(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, INTF_A_YO); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/small-server.h b/tests/data/small-server.h deleted file mode 100644 index 743fc8d7..00000000 --- a/tests/data/small-server.h +++ /dev/null @@ -1,265 +0,0 @@ -/* SCANNER TEST */ - -#ifndef SMALL_TEST_SERVER_PROTOCOL_H -#define SMALL_TEST_SERVER_PROTOCOL_H - -#include -#include -#include "wayland-server.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_client; -struct wl_resource; - -/** - * @page page_small_test The small_test protocol - * @section page_ifaces_small_test Interfaces - * - @subpage page_iface_intf_A - the thing A - * @section page_copyright_small_test Copyright - *
- *
- * Copyright © 2016 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.
- * 
- */ -struct another_intf; -struct intf_A; -struct intf_not_here; - -#ifndef INTF_A_INTERFACE -#define INTF_A_INTERFACE -/** - * @page page_iface_intf_A intf_A - * @section page_iface_intf_A_desc Description - * - * A useless example trying to tickle the scanner. - * @section page_iface_intf_A_api API - * See @ref iface_intf_A. - */ -/** - * @defgroup iface_intf_A The intf_A interface - * - * A useless example trying to tickle the scanner. - */ -extern const struct wl_interface intf_A_interface; -#endif - -#ifndef INTF_A_FOO_ENUM -#define INTF_A_FOO_ENUM -enum intf_A_foo { - /** - * this is the first - */ - INTF_A_FOO_FIRST = 0, - /** - * this is the second - */ - INTF_A_FOO_SECOND = 1, - /** - * this is the third - * @since 2 - */ - INTF_A_FOO_THIRD = 2, - /** - * this is a negative value - * @since 2 - */ - INTF_A_FOO_NEGATIVE = -1, - /** - * this is a deprecated value - * @since 2 - * @deprecated Deprecated since version 3 - */ - INTF_A_FOO_DEPRECATED = 3, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_THIRD_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2 -#endif /* INTF_A_FOO_ENUM */ - -#ifndef INTF_A_FOO_ENUM_IS_VALID -#define INTF_A_FOO_ENUM_IS_VALID -/** - * @ingroup iface_intf_A - * Validate a intf_A foo value. - * - * @return true on success, false on error. - * @ref intf_A_foo - */ -static inline bool -intf_A_foo_is_valid(uint32_t value, uint32_t version) { - switch (value) { - case INTF_A_FOO_FIRST: - return version >= 1; - case INTF_A_FOO_SECOND: - return version >= 1; - case INTF_A_FOO_THIRD: - return version >= 2; - case (uint32_t)INTF_A_FOO_NEGATIVE: - return version >= 2; - case INTF_A_FOO_DEPRECATED: - return version >= 2; - default: - return false; - } -} -#endif /* INTF_A_FOO_ENUM_IS_VALID */ - -#ifndef INTF_A_BAR_ENUM -#define INTF_A_BAR_ENUM -enum intf_A_bar { - /** - * this is the first - */ - INTF_A_BAR_FIRST = 0x01, - /** - * this is the second - */ - INTF_A_BAR_SECOND = 0x02, - /** - * this is the third - * @since 2 - */ - INTF_A_BAR_THIRD = 0x04, -}; -/** - * @ingroup iface_intf_A - */ -#define INTF_A_BAR_THIRD_SINCE_VERSION 2 -#endif /* INTF_A_BAR_ENUM */ - -#ifndef INTF_A_BAR_ENUM_IS_VALID -#define INTF_A_BAR_ENUM_IS_VALID -/** - * @ingroup iface_intf_A - * Validate a intf_A bar value. - * - * @return true on success, false on error. - * @ref intf_A_bar - */ -static inline bool -intf_A_bar_is_valid(uint32_t value, uint32_t version) { - uint32_t valid = 0; - if (version >= 1) - valid |= INTF_A_BAR_FIRST; - if (version >= 1) - valid |= INTF_A_BAR_SECOND; - if (version >= 2) - valid |= INTF_A_BAR_THIRD; - return (value & ~valid) == 0; -} -#endif /* INTF_A_BAR_ENUM_IS_VALID */ - -/** - * @ingroup iface_intf_A - * @struct intf_A_interface - */ -struct intf_A_interface { - /** - * @param interface name of the objects interface - * @param version version of the objects interface - */ - void (*rq1)(struct wl_client *client, - struct wl_resource *resource, - const char *interface, uint32_t version, uint32_t untyped_new); - /** - */ - void (*rq2)(struct wl_client *client, - struct wl_resource *resource, - uint32_t typed_new, - const char *str, - int32_t i, - uint32_t u, - wl_fixed_t f, - int32_t fd, - struct wl_resource *obj); - /** - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); -}; - -#define INTF_A_HEY 0 -#define INTF_A_YO 1 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_HEY_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_YO_SINCE_VERSION 2 - -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ1_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_RQ2_SINCE_VERSION 1 -/** - * @ingroup iface_intf_A - */ -#define INTF_A_DESTROY_SINCE_VERSION 1 - -/** - * @ingroup iface_intf_A - * Sends an hey event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -intf_A_send_hey(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, INTF_A_HEY); -} - -/** - * @ingroup iface_intf_A - * Sends an yo event to the client owning the resource. - * @param resource_ The client's resource - */ -static inline void -intf_A_send_yo(struct wl_resource *resource_) -{ - wl_resource_post_event(resource_, INTF_A_YO); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tests/data/small.xml b/tests/data/small.xml deleted file mode 100644 index ab297490..00000000 --- a/tests/data/small.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - Copyright © 2016 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. - - - - - A useless example trying to tickle the scanner. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/display-test.c b/tests/display-test.c index e6efa41e..1289866f 100644 --- a/tests/display-test.c +++ b/tests/display-test.c @@ -2,34 +2,28 @@ * Copyright © 2012 Intel Corporation * Copyright © 2013 Jason Ekstrand * - * 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: + * 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 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. + * 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. */ -#define _GNU_SOURCE -#include #include #include #include -#include #include #include #include @@ -37,10 +31,7 @@ #include #include #include -#include - #include -#include #include "wayland-private.h" #include "wayland-server.h" @@ -48,66 +39,6 @@ #include "test-runner.h" #include "test-compositor.h" -#include "tests-server-protocol.h" -#include "tests-client-protocol.h" - -static void -registry_handle_global_noop(void *data, - struct wl_registry *registry, - uint32_t id, const char *interface, - uint32_t ver) -{ -} - -static void -registry_handle_global_remove_noop(void *data, - struct wl_registry *registry, - uint32_t id) -{ -} - -static void -fixes_destroy(struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy(resource); -} - -static void -fixes_destroy_registry(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *registry) -{ - wl_resource_destroy(registry); -} - -static void -fixes_ack_global_remove(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *registry, - uint32_t global_id) -{ - wl_fixes_handle_ack_global_remove(resource, registry, global_id); -} - -static const struct wl_fixes_interface fixes_implementation = { - .destroy = fixes_destroy, - .destroy_registry = fixes_destroy_registry, - .ack_global_remove = fixes_ack_global_remove, -}; - -static void -bind_fixes(struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create(client, &wl_fixes_interface, version, id); - wl_resource_set_implementation(resource, &fixes_implementation, NULL, NULL); -} - struct display_destroy_listener { struct wl_listener listener; int done; @@ -118,7 +49,7 @@ display_destroy_notify(struct wl_listener *l, void *data) { struct display_destroy_listener *listener; - listener = wl_container_of(l, listener, listener); + listener = container_of(l, struct display_destroy_listener, listener); listener->done = 1; } @@ -149,65 +80,16 @@ TEST(display_destroy_listener) assert(b.done); } -/* Fake 'client' which does not use wl_display_connect, and thus leaves the - * file descriptor passed through WAYLAND_SOCKET intact. This should not - * trigger an assertion in the leak check. */ -static void -empty_client(void) -{ - return; -} - -TEST(tc_leaks_tests) -{ - struct display *d = display_create(); - client_create_noarg(d, empty_client); - display_run(d); - display_destroy(d); -} - -/* This is how pre proxy-version registry binds worked, - * this should create a proxy that shares the display's - * version number: 0 */ -static void * -old_registry_bind(struct wl_registry *wl_registry, - uint32_t name, - const struct wl_interface *interface, - uint32_t version) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_constructor( - (struct wl_proxy *) wl_registry, WL_REGISTRY_BIND, - interface, name, interface->name, version, NULL); - - return (void *) id; -} - -struct handler_info { - struct wl_seat *seat; - uint32_t bind_version; - bool use_unversioned; -}; - static void registry_handle_globals(void *data, struct wl_registry *registry, uint32_t id, const char *intf, uint32_t ver) { - struct handler_info *hi = data; - - /* This is only for the proxy version test */ - if (hi->bind_version) - ver = hi->bind_version; + struct wl_seat **seat = data; if (strcmp(intf, "wl_seat") == 0) { - if (hi->use_unversioned) - hi->seat = old_registry_bind(registry, id, - &wl_seat_interface, ver); - else - hi->seat = wl_registry_bind(registry, id, - &wl_seat_interface, ver); - assert(hi->seat); + *seat = wl_registry_bind(registry, id, + &wl_seat_interface, ver); + assert(*seat); } } @@ -217,40 +99,31 @@ static const struct wl_registry_listener registry_listener = { }; static struct wl_seat * -client_get_seat_with_info(struct client *c, struct handler_info *hi) +client_get_seat(struct client *c) { + struct wl_seat *seat; struct wl_registry *reg = wl_display_get_registry(c->wl_display); assert(reg); - assert(hi); - hi->seat = NULL; - wl_registry_add_listener(reg, ®istry_listener, hi); + wl_registry_add_listener(reg, ®istry_listener, &seat); wl_display_roundtrip(c->wl_display); - assert(hi->seat); + assert(seat); wl_registry_destroy(reg); - return hi->seat; -} - -static struct wl_seat * -client_get_seat(struct client *c) -{ - struct handler_info hi; - - hi.use_unversioned = false; - hi.bind_version = 0; - - return client_get_seat_with_info(c, &hi); + return seat; } static void -check_pending_error(struct client *c, struct wl_proxy *proxy) +check_for_error(struct client *c, struct wl_proxy *proxy) { uint32_t ec, id; int err; const struct wl_interface *intf; + /* client should be disconnected */ + assert(wl_display_roundtrip(c->wl_display) == -1); + err = wl_display_get_error(c->wl_display); assert(err == EPROTO); @@ -260,28 +133,6 @@ check_pending_error(struct client *c, struct wl_proxy *proxy) assert(id == wl_proxy_get_id(proxy)); } -static void -check_for_error(struct client *c, struct wl_proxy *proxy) -{ - /* client should be disconnected */ - assert(wl_display_roundtrip(c->wl_display) == -1); - - check_pending_error(c, proxy); -} - -static struct client_info * -find_client_info(struct display *d, struct wl_client *client) -{ - struct client_info *ci; - - wl_list_for_each(ci, &d->clients, link) { - if (ci->wl_client == client) - return ci; - } - - return NULL; -} - static void bind_seat(struct wl_client *client, void *data, uint32_t vers, uint32_t id) @@ -290,25 +141,19 @@ bind_seat(struct wl_client *client, void *data, struct client_info *ci; struct wl_resource *res; - ci = find_client_info(d, client); - assert(ci); + /* find the right client_info struct and save the + * resource as its data, so that we can use it later */ + wl_list_for_each(ci, &d->clients, link) { + if (ci->wl_client == client) + break; + } res = wl_resource_create(client, &wl_seat_interface, vers, id); assert(res); - /* save the resource as client's info data, - * so that we can use it later */ ci->data = res; } -static void -client_disconnect_nocheck(struct client *c) -{ - wl_proxy_destroy((struct wl_proxy *) c->tc); - wl_display_disconnect(c->wl_display); - free(c); -} - static void post_error_main(void) { @@ -325,7 +170,8 @@ post_error_main(void) /* don't call client_disconnect(c), because then the test would be * aborted due to checks for error in this function */ wl_proxy_destroy((struct wl_proxy *) seat); - client_disconnect_nocheck(c); + wl_proxy_destroy((struct wl_proxy *) c->tc); + wl_display_disconnect(c->wl_display); } TEST(post_error_to_one_client) @@ -336,7 +182,7 @@ TEST(post_error_to_one_client) wl_global_create(d->wl_display, &wl_seat_interface, 1, d, bind_seat); - cl = client_create_noarg(d, post_error_main); + cl = client_create(d, post_error_main); display_run(d); /* the display was stopped by client, so it can @@ -378,7 +224,8 @@ post_error_main3(void) /* don't call client_disconnect(c), because then the test would be * aborted due to checks for error in this function */ wl_proxy_destroy((struct wl_proxy *) seat); - client_disconnect_nocheck(c); + wl_proxy_destroy((struct wl_proxy *) c->tc); + wl_display_disconnect(c->wl_display); } /* all the testcases could be in one TEST, but splitting it @@ -391,8 +238,8 @@ TEST(post_error_to_one_from_two_clients) wl_global_create(d->wl_display, &wl_seat_interface, 1, d, bind_seat); - client_create_noarg(d, post_error_main2); - cl = client_create_noarg(d, post_error_main3); + client_create(d, post_error_main2); + cl = client_create(d, post_error_main3); display_run(d); /* post error only to the second client */ @@ -416,8 +263,8 @@ TEST(post_error_to_two_clients) wl_global_create(d->wl_display, &wl_seat_interface, 1, d, bind_seat); - cl = client_create_noarg(d, post_error_main3); - cl2 = client_create_noarg(d, post_error_main3); + cl = client_create(d, post_error_main3); + cl2 = client_create(d, post_error_main3); display_run(d); @@ -447,7 +294,8 @@ post_nomem_main(void) assert(wl_display_get_error(c->wl_display) == ENOMEM); wl_proxy_destroy((struct wl_proxy *) seat); - client_disconnect_nocheck(c); + wl_proxy_destroy((struct wl_proxy *) c->tc); + wl_display_disconnect(c->wl_display); } TEST(post_nomem_tst) @@ -458,7 +306,7 @@ TEST(post_nomem_tst) wl_global_create(d->wl_display, &wl_seat_interface, 1, d, bind_seat); - cl = client_create_noarg(d, post_nomem_main); + cl = client_create(d, post_nomem_main); display_run(d); assert(cl->data); @@ -467,7 +315,7 @@ TEST(post_nomem_tst) /* first client terminated. Run it again, * but post no memory to client */ - cl = client_create_noarg(d, post_nomem_main); + cl = client_create(d, post_nomem_main); display_run(d); assert(cl->data); @@ -477,46 +325,6 @@ TEST(post_nomem_tst) display_destroy(d); } -static void -post_implementation_error_main(void) -{ - struct client *c = client_connect(); - struct wl_seat *seat = client_get_seat(c); - uint32_t object_id, protocol_error; - const struct wl_interface *interface; - - assert(stop_display(c, 1) == -1); - int err = wl_display_get_error(c->wl_display); - fprintf(stderr, "Err is %i\n", err); - assert(err == EPROTO); - protocol_error = wl_display_get_protocol_error(c->wl_display, - &interface, - &object_id); - assert(protocol_error == WL_DISPLAY_ERROR_IMPLEMENTATION); - assert(interface == &wl_display_interface); - - wl_proxy_destroy((struct wl_proxy *) seat); - client_disconnect_nocheck(c); -} - -TEST(post_internal_error_tst) -{ - struct display *d = display_create(); - struct client_info *cl; - - wl_global_create(d->wl_display, &wl_seat_interface, - 1, d, bind_seat); - - cl = client_create_noarg(d, post_implementation_error_main); - display_run(d); - - wl_client_post_implementation_error(cl->wl_client, "Error %i", 20); - - display_resume(d); - - display_destroy(d); -} - static void register_reading(struct wl_display *display) { @@ -541,8 +349,8 @@ create_thread(struct client *c, void *(*func)(void*)) * so call usleep once again after the loop ends - it should * be sufficient... */ while (c->display_stopped == 0) - test_usleep(500); - test_usleep(10000); + usleep(500); + usleep(10000); return thread; } @@ -561,9 +369,9 @@ thread_read_error(void *data) * thread should be woken up or it will block indefinitely. */ c->display_stopped = 1; - assert(wl_display_read_events(c->wl_display) == -1); + assert(wl_display_read_events(c->wl_display) == 0); - assert(wl_display_dispatch_pending(c->wl_display) == -1); + wl_display_dispatch_pending(c->wl_display); assert(wl_display_get_error(c->wl_display)); pthread_exit(NULL); @@ -573,8 +381,6 @@ thread_read_error(void *data) static void threading_post_err(void) { - DISABLE_LEAK_CHECKS; - struct client *c = client_connect(); pthread_t thread; @@ -604,17 +410,18 @@ threading_post_err(void) /* kill test in 3 seconds. This should be enough time for the * thread to exit if it's not blocking. If everything is OK, than * the thread was woken up and the test will end before the SIGALRM */ - test_set_timeout(3); + alarm(3); pthread_join(thread, NULL); - client_disconnect_nocheck(c); + wl_proxy_destroy((struct wl_proxy *) c->tc); + wl_display_disconnect(c->wl_display); } TEST(threading_errors_tst) { struct display *d = display_create(); - client_create_noarg(d, threading_post_err); + client_create(d, threading_post_err); display_run(d); display_destroy(d); @@ -639,8 +446,6 @@ thread_prepare_and_read(void *data) static void threading_cancel_read(void) { - DISABLE_LEAK_CHECKS; - struct client *c = client_connect(); pthread_t th1, th2, th3; @@ -657,7 +462,7 @@ threading_cancel_read(void) /* kill test in 3 seconds. This should be enough time for the * thread to exit if it's not blocking. If everything is OK, than * the thread was woken up and the test will end before the SIGALRM */ - test_set_timeout(3); + alarm(3); pthread_join(th1, NULL); pthread_join(th2, NULL); pthread_join(th3, NULL); @@ -669,48 +474,7 @@ TEST(threading_cancel_read_tst) { struct display *d = display_create(); - client_create_noarg(d, threading_cancel_read); - display_run(d); - - display_destroy(d); -} - -static void -threading_read_eagain(void) -{ - DISABLE_LEAK_CHECKS; - - struct client *c = client_connect(); - pthread_t th1, th2, th3; - - register_reading(c->wl_display); - - th1 = create_thread(c, thread_prepare_and_read); - th2 = create_thread(c, thread_prepare_and_read); - th3 = create_thread(c, thread_prepare_and_read); - - /* All the threads are sleeping, waiting until read or cancel - * is called. Since we have no data on socket waiting, - * the wl_connection_read should end up with error and set errno - * to EAGAIN. Check if the threads are woken up in this case. */ - assert(wl_display_read_events(c->wl_display) == 0); - /* errno should be still set to EAGAIN if wl_connection_read - * set it - check if we're testing the right case */ - assert(errno == EAGAIN); - - test_set_timeout(3); - pthread_join(th1, NULL); - pthread_join(th2, NULL); - pthread_join(th3, NULL); - - client_disconnect(c); -} - -TEST(threading_read_eagain_tst) -{ - struct display *d = display_create(); - client_create_noarg(d, threading_read_eagain); - + client_create(d, threading_cancel_read); display_run(d); display_destroy(d); @@ -736,8 +500,6 @@ thread_prepare_and_read2(void *data) static void threading_read_after_error(void) { - DISABLE_LEAK_CHECKS; - struct client *c = client_connect(); pthread_t thread; @@ -755,1255 +517,25 @@ threading_read_after_error(void) /* make sure thread is sleeping */ while (c->display_stopped == 0) - test_usleep(500); - test_usleep(10000); + usleep(500); + usleep(10000); assert(wl_display_read_events(c->wl_display) == -1); /* kill test in 3 seconds */ - test_set_timeout(3); + alarm(3); pthread_join(thread, NULL); - client_disconnect_nocheck(c); + wl_proxy_destroy((struct wl_proxy *) c->tc); + wl_display_disconnect(c->wl_display); } TEST(threading_read_after_error_tst) { struct display *d = display_create(); - client_create_noarg(d, threading_read_after_error); + client_create(d, threading_read_after_error); display_run(d); display_destroy(d); } - -static void -wait_for_error_using_dispatch(struct client *c, struct wl_proxy *proxy) -{ - int ret; - - while (true) { - /* Dispatching should eventually hit the protocol error before - * any other error. */ - ret = wl_display_dispatch(c->wl_display); - if (ret == 0) { - continue; - } else { - assert(errno == EPROTO); - break; - } - } - - check_pending_error(c, proxy); -} - -static void -wait_for_error_using_prepare_read(struct client *c, struct wl_proxy *proxy) -{ - int ret = 0; - struct pollfd pfd[2]; - - while (true) { - while (wl_display_prepare_read(c->wl_display) != 0 && - errno == EAGAIN) { - assert(wl_display_dispatch_pending(c->wl_display) >= 0); - } - - /* Flush may fail due to EPIPE if the connection is broken, but - * this must not set a fatal display error because that would - * result in it being impossible to read a potential protocol - * error. */ - do { - ret = wl_display_flush(c->wl_display); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - assert(ret >= 0 || errno == EPIPE); - assert(wl_display_get_error(c->wl_display) == 0); - - pfd[0].fd = wl_display_get_fd(c->wl_display); - pfd[0].events = POLLIN; - do { - ret = poll(pfd, 1, -1); - } while (ret == -1 && errno == EINTR); - assert(ret != -1); - - /* We should always manage to read the error before the EPIPE - * comes this way. */ - assert(wl_display_read_events(c->wl_display) == 0); - - /* Dispatching should eventually hit the protocol error before - * any other error. */ - ret = wl_display_dispatch_pending(c->wl_display); - if (ret == 0) { - continue; - } else { - assert(errno == EPROTO); - break; - } - } - - check_pending_error(c, proxy); -} - -static void -check_error_after_epipe(void *data) -{ - bool use_dispatch_helpers = *(bool *) data; - struct client *client; - struct wl_seat *seat; - struct wl_callback *callback; - - client = client_connect(); - - /* This will, according to the implementation below, cause the server - * to post an error. */ - seat = client_get_seat(client); - wl_display_flush(client->wl_display); - - /* The server will not actually destroy the client until it receives - * input, so send something to trigger the client destruction. */ - callback = wl_display_sync(client->wl_display); - wl_callback_destroy(callback); - - /* Sleep some to give the server a chance to react and destroy the - * client. */ - test_usleep(200000); - - /* Wait for the protocol error and check that we reached it before - * EPIPE. */ - if (use_dispatch_helpers) { - wait_for_error_using_dispatch(client, (struct wl_proxy *) seat); - } else { - wait_for_error_using_prepare_read(client, - (struct wl_proxy *) seat); - } - - wl_seat_destroy(seat); - client_disconnect_nocheck(client); -} - -static void -bind_seat_and_post_error(struct wl_client *client, void *data, - uint32_t version, uint32_t id) -{ - struct display *d = data; - struct client_info *ci; - struct wl_resource *resource; - - ci = find_client_info(d, client); - assert(ci); - - resource = wl_resource_create(client, &wl_seat_interface, version, id); - assert(resource); - ci->data = resource; - - wl_resource_post_error(ci->data, 23, "Dummy error"); -} - -TEST(error_code_after_epipe) -{ - struct display *d = display_create(); - bool use_dispatch_helpers; - - wl_global_create(d->wl_display, &wl_seat_interface, - 1, d, bind_seat_and_post_error); - - use_dispatch_helpers = true; - client_create(d, check_error_after_epipe, &use_dispatch_helpers); - display_run(d); - - use_dispatch_helpers = false; - client_create(d, check_error_after_epipe, &use_dispatch_helpers); - display_run(d); - - display_destroy(d); -} - -static void -check_seat_versions(struct wl_seat *seat, uint32_t ev) -{ - struct wl_pointer *pointer; - - assert(wl_proxy_get_version((struct wl_proxy *) seat) == ev); - assert(wl_seat_get_version(seat) == ev); - - pointer = wl_seat_get_pointer(seat); - assert(wl_pointer_get_version(pointer) == ev); - assert(wl_proxy_get_version((struct wl_proxy *) pointer) == ev); - wl_proxy_destroy((struct wl_proxy *) pointer); -} - -/* Normal client with proxy versions available. */ -static void -seat_version(void *data) -{ - struct handler_info *hi = data; - struct client *c = client_connect(); - struct wl_seat *seat; - - /* display proxy should always be version 0 */ - assert(wl_proxy_get_version((struct wl_proxy *) c->wl_display) == 0); - - seat = client_get_seat_with_info(c, hi); - if (hi->use_unversioned) - check_seat_versions(seat, 0); - else - check_seat_versions(seat, hi->bind_version); - - wl_proxy_destroy((struct wl_proxy *) seat); - - client_disconnect_nocheck(c); -} - -TEST(versions) -{ - struct display *d = display_create(); - struct wl_global *global; - int i; - - global = wl_global_create(d->wl_display, &wl_seat_interface, - 5, d, bind_seat); - - for (i = 1; i <= 5; i++) { - struct handler_info hi; - - hi.bind_version = i; - hi.use_unversioned = false; - client_create(d, seat_version, &hi); - hi.use_unversioned = true; - client_create(d, seat_version, &hi); - } - - display_run(d); - - wl_global_destroy(global); - - display_destroy(d); -} - -static void -check_error_on_destroyed_object(void) -{ - struct client *c; - struct wl_seat *seat; - uint32_t id; - const struct wl_interface *intf; - - c = client_connect(); - seat = client_get_seat(c); - - /* destroy the seat proxy. The display won't know - * about it yet, so it will post the error as usual */ - wl_proxy_destroy((struct wl_proxy *) seat); - - /* let display post the error. The error will - * be caught in stop_display while dispatching */ - assert(stop_display(c, 1) == -1); - - /* check the returned error. Since the object was destroyed, - * we don't know the interface and id */ - assert(wl_display_get_error(c->wl_display) == EPROTO); - assert(wl_display_get_protocol_error(c->wl_display, &intf, &id) == 23); - assert(intf == NULL); - assert(id == 0); - - client_disconnect_nocheck(c); -} - -TEST(error_on_destroyed_object) -{ - struct client_info *cl; - struct display *d = display_create(); - - wl_global_create(d->wl_display, &wl_seat_interface, - 1, d, bind_seat); - - cl = client_create_noarg(d, check_error_on_destroyed_object); - display_run(d); - - /* did client bind to the seat? */ - assert(cl->data); - - /* post error on the destroyed object */ - wl_resource_post_error((struct wl_resource *) cl->data, - 23, "Dummy error"); - display_resume(d); - display_destroy(d); -} - -static bool -global_filter(const struct wl_client *client, - const struct wl_global *global, - void *data) -{ - /* Hide the wl_data_offer interface if no data was provided */ - if (wl_global_get_interface(global) == &wl_data_offer_interface) - return data != NULL; - - /* Show all the others */ - return true; -} - -static void -bind_data_offer(struct wl_client *client, void *data, - uint32_t vers, uint32_t id) -{ - /* Client should not be able to bind to this interface! */ - assert(false); -} - -static void -registry_handle_filtered(void *data, struct wl_registry *registry, - uint32_t id, const char *intf, uint32_t ver) -{ - uint32_t *name = data; - - if (strcmp (intf, "wl_data_offer") == 0) { - assert(name); - *name = id; - } -} - -static void -registry_handle_remove_filtered(void *data, struct wl_registry *registry, - uint32_t id) -{ - assert(false); -} - -static const struct wl_registry_listener registry_listener_filtered = { - registry_handle_filtered, - registry_handle_remove_filtered, -}; - -static void -get_globals(void *data) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, ®istry_listener_filtered, data); - wl_display_roundtrip(c->wl_display); - - wl_registry_destroy(registry); - client_disconnect_nocheck(c); -} - -TEST(filtered_global_is_hidden) -{ - struct display *d; - struct wl_global *g; - - d = display_create(); - - g = wl_global_create(d->wl_display, &wl_data_offer_interface, - 1, d, bind_data_offer); - wl_display_set_global_filter(d->wl_display, global_filter, NULL); - - client_create(d, get_globals, NULL); - display_run(d); - - wl_global_destroy(g); - - display_destroy(d); -} - -static void -get_dynamic_globals(void) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, ®istry_listener_filtered, NULL); - wl_display_roundtrip(c->wl_display); - - /* Wait for the server to create a new global */ - assert(stop_display(c, 1) >= 0); - - /* Check that we don't see it */ - wl_display_roundtrip(c->wl_display); - - /* Wait for the server to remove that global */ - assert(stop_display(c, 1) >= 0); - - /* Check that we don't get a global_remove event */ - wl_display_roundtrip(c->wl_display); - - wl_registry_destroy(registry); - client_disconnect_nocheck(c); -} - -TEST(filtered_dynamic_global_is_hidden) -{ - struct display *d; - struct wl_global *g; - - d = display_create(); - wl_display_set_global_filter(d->wl_display, global_filter, NULL); - - /* Create a client and let it enumerate the globals */ - client_create_noarg(d, get_dynamic_globals); - display_run(d); - - /* Dynamically create a new global */ - g = wl_global_create(d->wl_display, &wl_data_offer_interface, - 1, d, bind_data_offer); - - display_resume(d); - - /* Dynamically remove the global */ - wl_global_destroy(g); - - display_resume(d); - - display_destroy(d); -} - -static void -check_bind_error(struct client *c) -{ - uint32_t errorcode, id; - int err; - const struct wl_interface *intf; - - err = wl_display_get_error(c->wl_display); - assert(err == EPROTO); - - errorcode = wl_display_get_protocol_error(c->wl_display, &intf, &id); - assert(errorcode == WL_DISPLAY_ERROR_INVALID_OBJECT); -} - -static void -force_bind(void *data) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - void *ptr; - uint32_t *name = data; - - registry = wl_display_get_registry(c->wl_display); - - ptr = wl_registry_bind (registry, *name, &wl_data_offer_interface, 1); - wl_display_roundtrip(c->wl_display); - check_bind_error(c); - - wl_proxy_destroy((struct wl_proxy *) ptr); - wl_registry_destroy(registry); - - client_disconnect_nocheck(c); -} - -TEST(bind_fails_on_filtered_global) -{ - struct display *d; - struct wl_global *g; - uint32_t *name; - - /* Create a anonymous shared memory to pass the interface name */ - name = mmap(NULL, sizeof(uint32_t), - PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); - - d = display_create(); - - g = wl_global_create(d->wl_display, &wl_data_offer_interface, - 1, d, bind_data_offer); - wl_display_set_global_filter(d->wl_display, global_filter, name); - - client_create(d, get_globals, name); - *name = 0; - - display_run(d); - /* wl_data_offer should be 2 */ - assert(*name == 2); - wl_display_set_global_filter(d->wl_display, global_filter, NULL); - - /* Try to bind to the interface name when a global filter is in place */ - client_create(d, force_bind, name); - display_run(d); - - wl_global_destroy(g); - - display_destroy(d); -} - -static void -pre_fd(void *data, struct fd_passer *fdp) -{ - fd_passer_destroy(fdp); -} - -static void -fd(void *data, struct fd_passer *fdp, int32_t fd) -{ - /* We destroyed the resource before this event */ - assert(false); -} - -struct fd_passer_listener fd_passer_listener = { - pre_fd, - fd, -}; - -static void -zombie_fd_handle_globals(void *data, struct wl_registry *registry, - uint32_t id, const char *intf, uint32_t ver) -{ - struct fd_passer *fdp; - - if (!strcmp(intf, "fd_passer")) { - fdp = wl_registry_bind(registry, id, &fd_passer_interface, 1); - fd_passer_add_listener(fdp, &fd_passer_listener, NULL); - } -} - -static const struct wl_registry_listener zombie_fd_registry_listener = { - zombie_fd_handle_globals, - NULL -}; - -static void -zombie_client(void) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, &zombie_fd_registry_listener, NULL); - - /* Gets the registry */ - wl_display_roundtrip(c->wl_display); - - /* push out the fd_passer bind */ - wl_display_roundtrip(c->wl_display); - - /* push out our fd_passer.destroy */ - wl_display_roundtrip(c->wl_display); - - wl_registry_destroy(registry); - - client_disconnect_nocheck(c); -} - -struct passer_data { - struct wl_resource *conjoined_passer; -}; - -static void -feed_pipe(int fd, char tosend) -{ - int count; - - do { - count = write(fd, &tosend, 1); - } while (count != 1 && errno == EAGAIN); - assert(count == 1); - close(fd); -} - -static void -fd_passer_clobber(struct wl_client *client, struct wl_resource *res) -{ - struct passer_data *pdata = wl_resource_get_user_data(res); - int pipes1[2], pipes2[2], ret; - - if (pdata->conjoined_passer) { - ret = pipe(pipes1); - assert(ret == 0); - ret = pipe(pipes2); - assert(ret == 0); - - wl_resource_queue_event(res, FD_PASSER_FD, pipes1[0]); - fd_passer_send_fd(pdata->conjoined_passer, pipes2[0]); - feed_pipe(pipes1[1], '1'); - feed_pipe(pipes2[1], '2'); - close(pipes1[0]); - close(pipes2[0]); - } - wl_resource_destroy(res); -} - -static void -fd_passer_twin(struct wl_client *client, struct wl_resource *res, struct wl_resource *passer) -{ - struct passer_data *pdata = wl_resource_get_user_data(res); - - pdata->conjoined_passer = passer; -} - -static const struct fd_passer_interface fdp_interface = { - fd_passer_clobber, - fd_passer_twin -}; - -static void -pdata_destroy(struct wl_resource *res) -{ - struct passer_data *pdata = wl_resource_get_user_data(res); - - free(pdata); -} - -static void -bind_fd_passer(struct wl_client *client, void *data, - uint32_t vers, uint32_t id) -{ - struct wl_resource *res; - struct passer_data *pdata; - - pdata = malloc(sizeof(*pdata)); - assert(pdata); - pdata->conjoined_passer = NULL; - - res = wl_resource_create(client, &fd_passer_interface, vers, id); - wl_resource_set_implementation(res, &fdp_interface, pdata, pdata_destroy); - assert(res); - if (vers == 1) { - fd_passer_send_pre_fd(res); - fd_passer_send_fd(res, fileno(stdin)); - } -} - -TEST(zombie_fd) -{ - struct display *d; - struct wl_global *g; - - d = display_create(); - - g = wl_global_create(d->wl_display, &fd_passer_interface, - 1, d, bind_fd_passer); - - client_create_noarg(d, zombie_client); - display_run(d); - - wl_global_destroy(g); - - display_destroy(d); -} - - -static void -double_pre_fd(void *data, struct fd_passer *fdp) -{ - assert(false); -} - -static void -double_fd(void *data, struct fd_passer *fdp, int32_t fd) -{ - char buf; - int count; - - do { - count = read(fd, &buf, 1); - } while (count != 1 && errno == EAGAIN); - assert(count == 1); - - close(fd); - fd_passer_destroy(fdp); - assert(buf == '2'); -} - -struct fd_passer_listener double_fd_passer_listener = { - double_pre_fd, - double_fd, -}; - - -static void -double_zombie_fd_handle_globals(void *data, struct wl_registry *registry, - uint32_t id, const char *intf, uint32_t ver) -{ - struct fd_passer *fdp1, *fdp2; - - if (!strcmp(intf, "fd_passer")) { - fdp1 = wl_registry_bind(registry, id, &fd_passer_interface, 2); - fd_passer_add_listener(fdp1, &double_fd_passer_listener, NULL); - fdp2 = wl_registry_bind(registry, id, &fd_passer_interface, 2); - fd_passer_add_listener(fdp2, &double_fd_passer_listener, NULL); - fd_passer_conjoin(fdp1, fdp2); - fd_passer_destroy(fdp1); - } -} - -static const struct wl_registry_listener double_zombie_fd_registry_listener = { - double_zombie_fd_handle_globals, - NULL -}; - -static void -double_zombie_client(void) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, &double_zombie_fd_registry_listener, NULL); - - /* Gets the registry */ - wl_display_roundtrip(c->wl_display); - - /* One more so server can respond to conjoin+destroy */ - wl_display_roundtrip(c->wl_display); - - /* And finally push out our last fd_passer.destroy */ - wl_display_roundtrip(c->wl_display); - - wl_registry_destroy(registry); - - client_disconnect_nocheck(c); -} - -TEST(zombie_fd_errant_consumption) -{ - struct display *d; - struct wl_global *g; - - d = display_create(); - - g = wl_global_create(d->wl_display, &fd_passer_interface, - 2, d, bind_fd_passer); - - client_create_noarg(d, double_zombie_client); - display_run(d); - - wl_global_destroy(g); - - display_destroy(d); -} - - -static void -registry_bind_interface_mismatch_handle_global(void *data, - struct wl_registry *registry, - uint32_t id, const char *intf, - uint32_t ver) -{ - uint32_t *seat_id_ptr = data; - - if (strcmp(intf, wl_seat_interface.name) == 0) { - *seat_id_ptr = id; - } -} - -static const struct wl_registry_listener bind_interface_mismatch_registry_listener = { - registry_bind_interface_mismatch_handle_global, - NULL -}; - -static void -registry_bind_interface_mismatch_client(void) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - uint32_t seat_id = 0; - void *ptr; - int ret; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, - &bind_interface_mismatch_registry_listener, - &seat_id); - - ret = wl_display_roundtrip(c->wl_display); - assert(ret >= 0); - assert(seat_id != 0); - - /* Bind with a different interface */ - ptr = wl_registry_bind(registry, seat_id, &wl_output_interface, 1); - ret = wl_display_roundtrip(c->wl_display); - assert(ret < 0); - check_bind_error(c); - - wl_proxy_destroy((struct wl_proxy *) ptr); - wl_registry_destroy(registry); - - client_disconnect_nocheck(c); -} - -TEST(registry_bind_interface_mismatch) -{ - struct display *d; - struct wl_global *seat_global; - - d = display_create(); - - seat_global = wl_global_create(d->wl_display, &wl_seat_interface, - 1, NULL, NULL); - - client_create_noarg(d, registry_bind_interface_mismatch_client); - display_run(d); - - wl_global_destroy(seat_global); - - display_destroy(d); -} - -static void -send_overflow_client(void *data) -{ - struct client *c = client_connect(); - int i, err = 0; - int *pipes = data; - char tmp = '\0'; - int sock, optval = 16384; - - /* By default, client buffers are now unbounded, set a limit to cause - * an overflow, otherwise the client buffers will grow indefinitely. */ - wl_display_set_max_buffer_size(c->wl_display, 4096); - - /* Limit the send buffer size for the display socket to guarantee - * that the test will cause an overflow. */ - sock = wl_display_get_fd(c->wl_display); - assert(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)) == 0); - - /* Request to break out of 'display_run' in the main process */ - assert(stop_display(c, 1) >= 0); - - /* On Linux, the actual socket data + metadata space is twice `optval`; - * since each noop request requires 8 bytes, the buffer should overflow - * within <=4096 iterations. */ - for (i = 0; i < 1000000; i++) { - noop_request(c); - fprintf(stderr, "Send loop %i\n", i); - err = wl_display_get_error(c->wl_display); - if (err) - break; - } - - /* Do not close the pipe file descriptors afterwards, because the leak - * check verifies that the initial/final FD counts are the same */ - assert(write(pipes[1], &tmp, sizeof(tmp)) == (ssize_t)sizeof(tmp)); - - /* Expect an error - ring_buffer_ensure_space() returns E2BIG */ - fprintf(stderr, "Send loop failed on try %d, err = %d, %s\n", i, err, strerror(err)); - assert(err == EAGAIN || err == E2BIG); - - client_disconnect_nocheck(c); -} - -TEST(send_overflow_disconnection) -{ - struct display *d; - char tmp; - int rpipe[2]; - ssize_t ret; - - assert(pipe(rpipe) != -1); - - d = display_create(); - - (void) client_create(d, send_overflow_client, &rpipe); - - /* Close write end of the pipe, so that the later read() call gets - * interrupted if the client dies */ - close(rpipe[1]); - - /* Run the display until the client sends a `stop_display`, then - * send a resume message but don't actually look at new messages */ - display_run(d); - display_post_resume_events(d); - wl_display_flush_clients(d->wl_display); - - /* Wait until all noop requests have been sent (read returns 1), or - * until client process aborts (read returns 0) */ - do { - ret = read(rpipe[0], &tmp, sizeof(tmp)); - } while (ret == -1 && errno == EINTR); - assert(ret != -1); - close(rpipe[0]); - - /* For a clean shutdown */ - display_run(d); - - display_destroy(d); -} - -static void -registry_global_remove_before_handle_global(void *data, - struct wl_registry *registry, - uint32_t id, const char *intf, - uint32_t ver) -{ - uint32_t *id_ptr = data; - - if (strcmp(intf, wl_seat_interface.name) == 0) { - assert(*id_ptr == 0); - *id_ptr = id; - } -} - -static void -registry_global_remove_before_handle_global_remove(void *data, - struct wl_registry *registry, - uint32_t id) -{ - uint32_t *id_ptr = data; - - if (*id_ptr == id) { - *id_ptr = 0; - } -} - -/* This listener expects a uint32_t user data pointer, sets it to the wl_seat - * global ID when receiving a "global" event, and sets it to zero when receiving - * a "global_remove" event. */ -static const struct wl_registry_listener global_remove_before_registry_listener = { - registry_global_remove_before_handle_global, - registry_global_remove_before_handle_global_remove, -}; - -static void -global_remove_before_client(void) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - uint32_t global_id = 0, saved_global_id; - struct wl_seat *seat; - int ret; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, - &global_remove_before_registry_listener, - &global_id); - - ret = wl_display_roundtrip(c->wl_display); - assert(ret >= 0); - assert(global_id != 0); - saved_global_id = global_id; - - /* Wait for the compositor to remove the global */ - assert(stop_display(c, 1) >= 0); - - /* Check binding still works after the global has been removed. Also - * check we get the global_remove event. */ - seat = wl_registry_bind(registry, saved_global_id, &wl_seat_interface, 1); - ret = wl_display_roundtrip(c->wl_display); - assert(ret >= 0); - assert(global_id == 0); - - wl_seat_destroy(seat); - wl_registry_destroy(registry); - - client_disconnect(c); -} - -static void -registry_global_remove_after_handle_global(void *data, - struct wl_registry *registry, - uint32_t id, const char *intf, - uint32_t ver) -{ - /* Make sure the global isn't advertised anymore after being removed */ - assert(strcmp(intf, wl_seat_interface.name) != 0); -} - -static const struct wl_registry_listener global_remove_after_registry_listener = { - registry_global_remove_after_handle_global, - NULL, -}; - -static void -global_remove_after_client(void) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - uint32_t global_id = 0; - int ret; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, - &global_remove_after_registry_listener, - &global_id); - - ret = wl_display_roundtrip(c->wl_display); - assert(ret >= 0); - - wl_registry_destroy(registry); - - client_disconnect(c); -} - -TEST(global_remove) -{ - struct display *d; - struct wl_global *global; - - d = display_create(); - - global = wl_global_create(d->wl_display, &wl_seat_interface, - 1, d, bind_seat); - - /* Create a client before removing the global */ - client_create_noarg(d, global_remove_before_client); - - display_run(d); - - wl_global_remove(global); - - /* Create another client after removing the global */ - client_create_noarg(d, global_remove_after_client); - - display_resume(d); - - wl_global_destroy(global); - - display_destroy(d); -} - -static void -registry_ack_global_remove_handle_global_remove(void *data, - struct wl_registry *registry, - uint32_t id) -{ - struct client *client = data; - - wl_fixes_ack_global_remove(client->wl_fixes, registry, id); -} - -static struct wl_registry_listener registry_ack_global_remove_listener = { - .global = registry_handle_global_noop, - .global_remove = registry_ack_global_remove_handle_global_remove, -}; - -static void -ack_global_remove_client(void *data) -{ - struct client *c = client_connect(); - struct wl_registry *registry; - struct wl_registry_listener *registry_listener = data; - int ret; - - registry = wl_display_get_registry(c->wl_display); - wl_registry_add_listener(registry, - registry_listener, - c); - - ret = wl_display_roundtrip(c->wl_display); - assert(ret >= 0); - - /* yield the control back to the compositor so it can remove - * the global */ - assert(stop_display(c, 1) >= 0); - - /* check if there are any global_remove events */ - ret = wl_display_roundtrip(c->wl_display); - assert(ret >= 0); - - /* yield the control back to the compositor so it can check - * whether the global is withdrawn */ - assert(stop_display(c, 1) >= 0); - - wl_registry_destroy(registry); - - client_disconnect(c); -} - -static void -mark_global_withdrawn(struct wl_global *global) -{ - bool *withdrawn = wl_global_get_user_data(global); - - *withdrawn = true; -} - -TEST(ack_global_remove) -{ - struct display *d; - struct wl_global *seat; - struct wl_global *fixes; - bool withdrawn = false; - - d = display_create(); - - fixes = wl_global_create(d->wl_display, &wl_fixes_interface, - 2, NULL, bind_fixes); - - seat = wl_global_create(d->wl_display, &wl_seat_interface, - 1, &withdrawn, NULL); - - wl_global_set_withdrawn_listener(seat, mark_global_withdrawn); - - client_create(d, ack_global_remove_client, - ®istry_ack_global_remove_listener); - - display_run(d); - assert(!withdrawn); - - wl_global_remove(seat); - - /* the global will be marked as withdrawn after the client - * acknowledges the wl_registry.global_remove event */ - display_resume(d); - assert(withdrawn); - - /* the global will be still marked as withdrawn even after - * the client disconnects */ - display_resume(d); - assert(withdrawn); - - wl_global_destroy(seat); - wl_global_destroy(fixes); - - display_destroy(d); -} - -static struct wl_registry_listener registry_no_ack_global_remove_listener = { - .global = registry_handle_global_noop, - .global_remove = registry_handle_global_remove_noop, -}; - -TEST(no_ack_global_remove) -{ - struct display *d; - struct wl_global *seat; - struct wl_global *fixes; - bool withdrawn = false; - - d = display_create(); - - fixes = wl_global_create(d->wl_display, &wl_fixes_interface, - 2, NULL, bind_fixes); - - seat = wl_global_create(d->wl_display, &wl_seat_interface, - 1, &withdrawn, NULL); - - wl_global_set_withdrawn_listener(seat, mark_global_withdrawn); - - client_create(d, ack_global_remove_client, - ®istry_no_ack_global_remove_listener); - - display_run(d); - assert(!withdrawn); - - wl_global_remove(seat); - - /* if the client does not ack the wl_registry.global_remove event, - * the global will not be marked as withdrawn */ - display_resume(d); - assert(!withdrawn); - - /* when the client disconnects, the wl_registry.global_remove will - * be implicitly acknowledged and the global can be destroyed then */ - display_resume(d); - assert(withdrawn); - - wl_global_destroy(seat); - wl_global_destroy(fixes); - - display_destroy(d); -} - -TEST(global_remove_without_clients) -{ - struct display *d; - struct wl_global *global; - bool withdrawn = false; - - d = display_create(); - - global = wl_global_create(d->wl_display, &wl_seat_interface, - 1, &withdrawn, NULL); - - wl_global_set_withdrawn_listener(global, mark_global_withdrawn); - - /* if there are no clients at all, the global can be destroyed - * immediately */ - wl_global_remove(global); - assert(withdrawn); - - wl_global_destroy(global); - - display_destroy(d); -} - -static void -dispatch_single_read_events(struct wl_display *d) -{ - if (wl_display_prepare_read(d) < 0) { - return; - } - - int ret = 0; - do { - ret = wl_display_flush(d); - } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); - assert(ret >= 0); - - struct pollfd pfd[1]; - pfd[0].fd = wl_display_get_fd(d); - pfd[0].events = POLLIN; - - do { - ret = poll(pfd, 1, -1); - } while (ret < 0 && errno == EINTR); - assert(ret > 0); - - wl_display_read_events(d); -} - -static void -dispatch_single_client(void) -{ - struct client *c = client_connect(); - - assert(wl_display_dispatch_pending_single(c->wl_display) == 0); - - struct wl_registry *registry = wl_display_get_registry(c->wl_display); - - dispatch_single_read_events(c->wl_display); - - // [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1) - assert(wl_display_dispatch_pending_single(c->wl_display) == 1); - - dispatch_single_read_events(c->wl_display); - - // [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1) - assert(wl_display_dispatch_pending_single(c->wl_display) == 1); - - // No more events - assert(wl_display_dispatch_pending_single(c->wl_display) == 0); - - wl_registry_destroy(registry); - - client_disconnect(c); -} - -TEST(dispatch_single) -{ - struct display *d = display_create(); - - struct wl_global *global = wl_global_create(d->wl_display, - &wl_seat_interface, - 1, d, bind_seat); - - client_create_noarg(d, dispatch_single_client); - - display_run(d); - - wl_global_destroy(global); - - display_destroy(d); -} - -static void -terminate_display(void *arg) -{ - struct wl_display *wl_display = arg; - wl_display_terminate(wl_display); -} - -TEST(no_source_terminate) -{ - struct display *d; - struct wl_event_loop *loop; - - d = display_create(); - loop = wl_display_get_event_loop(d->wl_display); - - wl_event_loop_add_idle(loop, terminate_display, d->wl_display); - - display_run(d); - display_destroy(d); -} diff --git a/tests/enum-validator-test.c b/tests/enum-validator-test.c deleted file mode 100644 index 8fb05b43..00000000 --- a/tests/enum-validator-test.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include "data/small-server-core.h" - -int -main(int argc, char *argv[]) { - assert(intf_A_foo_is_valid(INTF_A_FOO_FIRST, 1)); - assert(intf_A_foo_is_valid(INTF_A_FOO_FIRST, 2)); - - assert(!intf_A_foo_is_valid(INTF_A_FOO_THIRD, 1)); - assert(intf_A_foo_is_valid(INTF_A_FOO_THIRD, 2)); - - assert(intf_A_foo_is_valid(INTF_A_FOO_NEGATIVE, 2)); - - assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST, 1)); - assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST, 2)); - assert(intf_A_bar_is_valid(INTF_A_BAR_SECOND, 1)); - assert(intf_A_bar_is_valid(INTF_A_BAR_SECOND, 2)); - assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_SECOND, 1)); - assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_SECOND, 2)); - - assert(!intf_A_bar_is_valid(INTF_A_BAR_THIRD, 1)); - assert(!intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_THIRD, 1)); - assert(intf_A_bar_is_valid(INTF_A_BAR_THIRD, 2)); - assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_THIRD, 2)); - - assert(!intf_A_bar_is_valid(0xFF, 1)); - assert(!intf_A_bar_is_valid(0xFF, 2)); -} diff --git a/tests/event-loop-test.c b/tests/event-loop-test.c index be15a34e..1a45db1f 100644 --- a/tests/event-loop-test.c +++ b/tests/event-loop-test.c @@ -2,35 +2,29 @@ * Copyright © 2012 Intel Corporation * Copyright © 2012 Jason Ekstrand * - * 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: + * 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 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. + * 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. */ -#define _GNU_SOURCE #include -#include #include #include #include -#include #include #include "wayland-private.h" @@ -169,22 +163,10 @@ TEST(event_loop_signal) signal_callback, &got_it); assert(source); - assert(wl_event_loop_dispatch(loop, 0) == 0); + wl_event_loop_dispatch(loop, 0); assert(!got_it); - assert(kill(getpid(), SIGUSR1) == 0); - /* - * On Linux the signal will be immediately visible in the epoll_wait() - * call. However, on FreeBSD we may need a small delay between kill() - * call and the signal being visible to the kevent() call. This - * sometimes happens when the signal processing and kevent processing - * runs on different CPUs, so becomes more likely when the system is - * under load (e.g. running all tests in parallel). - * See https://github.com/jiixyj/epoll-shim/pull/32 - * Passing 1ms as the timeout appears to avoid this race condition in - * all cases tested so far, but to be safe we use 1000ms which should - * be enough time even on a really slow (or emulated) system. - */ - assert(wl_event_loop_dispatch(loop, 1000) == 0); + kill(getpid(), SIGUSR1); + wl_event_loop_dispatch(loop, 0); assert(got_it == 1); wl_event_source_remove(source); @@ -212,12 +194,8 @@ TEST(event_loop_multiple_same_signals) /* Try it more times */ for (i = 0; i < 5; ++i) { calls_no = 0; - assert(kill(getpid(), SIGUSR1) == 0); - /* - * We need a non-zero timeout here to allow the test to pass - * on non-Linux systems (see comment in event_loop_signal). - */ - assert(wl_event_loop_dispatch(loop, 1000) == 0); + kill(getpid(), SIGUSR1); + assert(wl_event_loop_dispatch(loop, 0) == 0); assert(calls_no == 2); } @@ -225,12 +203,8 @@ TEST(event_loop_multiple_same_signals) /* Try it again with one source */ calls_no = 0; - assert(kill(getpid(), SIGUSR1) == 0); - /* - * We need a non-zero timeout here to allow the test to pass - * on non-Linux systems (see comment in event_loop_signal). - */ - assert(wl_event_loop_dispatch(loop, 1000) == 0); + kill(getpid(), SIGUSR1); + assert(wl_event_loop_dispatch(loop, 0) == 0); assert(calls_no == 1); wl_event_source_remove(s2); @@ -238,6 +212,34 @@ TEST(event_loop_multiple_same_signals) wl_event_loop_destroy(loop); } +static int +timer_callback(void *data) +{ + int *got_it = data; + + ++(*got_it); + + return 1; +} + +TEST(event_loop_timer) +{ + struct wl_event_loop *loop = wl_event_loop_create(); + struct wl_event_source *source; + int got_it = 0; + + source = wl_event_loop_add_timer(loop, timer_callback, &got_it); + assert(source); + wl_event_source_timer_update(source, 10); + wl_event_loop_dispatch(loop, 0); + assert(!got_it); + wl_event_loop_dispatch(loop, 20); + assert(got_it == 1); + + wl_event_source_remove(source); + wl_event_loop_destroy(loop); +} + #define MSEC_TO_USEC(msec) ((msec) * 1000) struct timer_update_context { @@ -324,138 +326,6 @@ TEST(event_loop_timer_updates) wl_event_loop_destroy(loop); } -struct timer_order_data { - struct wl_event_source *source; - int *last_number; - int number; -}; - -static int -timer_order_callback(void *data) -{ - struct timer_order_data *tod = data; - - /* Check that the timers have the correct sequence */ - assert(tod->number == *tod->last_number + 2); - *tod->last_number = tod->number; - return 0; -} - -TEST(event_loop_timer_order) -{ - struct wl_event_loop *loop = wl_event_loop_create(); - struct timer_order_data order[20]; - int i, j; - int last = -1; - - /* Configure a set of timers so that only timers 1, 3, 5, ..., 19 - * (in that order) will be dispatched when the event loop is run */ - - for (i = 0; i < 20; i++) { - order[i].number = i; - order[i].last_number = &last; - order[i].source = - wl_event_loop_add_timer(loop, timer_order_callback, - &order[i]); - assert(order[i].source); - assert(wl_event_source_timer_update(order[i].source, 10) == 0); - } - - for (i = 0; i < 20; i++) { - /* Permute the order in which timers are updated, so as to - * more exhaustively test the underlying priority queue code */ - j = ((i + 3) * 17) % 20; - assert(wl_event_source_timer_update(order[j].source, j) == 0); - } - for (i = 0; i < 20; i += 2) { - assert(wl_event_source_timer_update(order[i].source, 0) == 0); - } - - /* Wait until all timers are due */ - usleep(MSEC_TO_USEC(21)); - wl_event_loop_dispatch(loop, 0); - assert(last == 19); - - for (i = 0; i < 20; i++) { - wl_event_source_remove(order[i].source); - } - wl_event_loop_destroy(loop); -} - -struct timer_cancel_context { - struct wl_event_source *timers[4]; - struct timer_cancel_context *back_refs[4]; - int order[4]; - int called, first; -}; - -static int -timer_cancel_callback(void *data) { - struct timer_cancel_context **context_ref = data; - struct timer_cancel_context *context = *context_ref; - int i = (int)(context_ref - context->back_refs); - - context->called++; - context->order[i] = context->called; - - if (context->called == 1) { - context->first = i; - /* Removing a timer always prevents its callback from - * being called ... */ - wl_event_source_remove(context->timers[(i + 1) % 4]); - /* ... but disarming or rescheduling a timer does not, - * (in the case where the modified timers had already expired - * as of when `wl_event_loop_dispatch` was called.) */ - assert(wl_event_source_timer_update(context->timers[(i + 2) % 4], - 0) == 0); - assert(wl_event_source_timer_update(context->timers[(i + 3) % 4], - 2000000000) == 0); - } - - return 0; -} - -TEST(event_loop_timer_cancellation) -{ - struct wl_event_loop *loop = wl_event_loop_create(); - struct timer_cancel_context context; - int i; - - memset(&context, 0, sizeof(context)); - - /* Test that when multiple timers are dispatched in a single call - * of `wl_event_loop_dispatch`, that having some timers run code - * to modify the other timers only actually prevents the other timers - * from running their callbacks when the those timers are removed, not - * when they are disarmed or rescheduled. */ - - for (i = 0; i < 4; i++) { - context.back_refs[i] = &context; - context.timers[i] = - wl_event_loop_add_timer(loop, timer_cancel_callback, - &context.back_refs[i]); - assert(context.timers[i]); - - assert(wl_event_source_timer_update(context.timers[i], 1) == 0); - } - - usleep(MSEC_TO_USEC(2)); - assert(wl_event_loop_dispatch(loop, 0) == 0); - - /* Tracking which timer was first makes this test independent of the - * actual timer dispatch order, which is not guaranteed by the docs */ - assert(context.order[context.first] == 1); - assert(context.order[(context.first + 1) % 4] == 0); - assert(context.order[(context.first + 2) % 4] > 1); - assert(context.order[(context.first + 3) % 4] > 1); - - wl_event_source_remove(context.timers[context.first]); - wl_event_source_remove(context.timers[(context.first + 2) % 4]); - wl_event_source_remove(context.timers[(context.first + 3) % 4]); - - wl_event_loop_destroy(loop); -} - struct event_loop_destroy_listener { struct wl_listener listener; int done; @@ -465,7 +335,7 @@ static void event_loop_destroy_notify(struct wl_listener *l, void *data) { struct event_loop_destroy_listener *listener = - wl_container_of(l, listener, listener); + container_of(l, struct event_loop_destroy_listener, listener); listener->done = 1; } diff --git a/tests/exec-fd-leak-checker.c b/tests/exec-fd-leak-checker.c index 5f3b3958..66209ad5 100644 --- a/tests/exec-fd-leak-checker.c +++ b/tests/exec-fd-leak-checker.c @@ -1,26 +1,23 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 @@ -37,7 +34,7 @@ parse_count(const char *str, int *value) long v; errno = 0; - v = strtol(str, &end, 10); + v = strtol(str, &end, 0); if ((errno == ERANGE && (v == LONG_MAX || v == LONG_MIN)) || (errno != 0 && v == 0) || (end == str) || diff --git a/tests/fixed-benchmark.c b/tests/fixed-benchmark.c new file mode 100644 index 00000000..07190637 --- /dev/null +++ b/tests/fixed-benchmark.c @@ -0,0 +1,104 @@ +/* + * Copyright © 2012 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 +#include +#include +#include +#include +#include "wayland-private.h" + +volatile double global_d; + +static void +noop_conversion(void) +{ + wl_fixed_t f; + union { + int64_t i; + double d; + } u; + + for (f = 0; f < INT32_MAX; f++) { + u.i = f; + global_d = u.d; + } +} + +static void +magic_conversion(void) +{ + wl_fixed_t f; + + for (f = 0; f < INT32_MAX; f++) + global_d = wl_fixed_to_double(f); +} + +static void +mul_conversion(void) +{ + wl_fixed_t f; + + /* This will get optimized into multiplication by 1/256 */ + for (f = 0; f < INT32_MAX; f++) + global_d = f / 256.0; +} + +double factor = 256.0; + +static void +div_conversion(void) +{ + wl_fixed_t f; + + for (f = 0; f < INT32_MAX; f++) + global_d = f / factor; +} + +static void +benchmark(const char *s, void (*f)(void)) +{ + struct timespec start, stop, elapsed; + + clock_gettime(CLOCK_MONOTONIC, &start); + f(); + clock_gettime(CLOCK_MONOTONIC, &stop); + + elapsed.tv_sec = stop.tv_sec - start.tv_sec; + elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec; + if (elapsed.tv_nsec < 0) { + elapsed.tv_nsec += 1000000000; + elapsed.tv_sec--; + } + printf("benchmarked %s:\t%ld.%09lds\n", + s, elapsed.tv_sec, elapsed.tv_nsec); +} + +int main(int argc, char *argv[]) +{ + benchmark("noop", noop_conversion); + benchmark("magic", magic_conversion); + benchmark("div", div_conversion); + benchmark("mul", mul_conversion); + + return 0; +} diff --git a/tests/fixed-test.c b/tests/fixed-test.c index 0b587978..739a3b1b 100644 --- a/tests/fixed-test.c +++ b/tests/fixed-test.c @@ -1,29 +1,25 @@ /* * Copyright © 2012 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: + * 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 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. + * 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. */ -#define _GNU_SOURCE #include #include #include diff --git a/tests/headers-protocol-core-test.c b/tests/headers-protocol-core-test.c deleted file mode 100644 index 5c2baf36..00000000 --- a/tests/headers-protocol-core-test.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2015 Giulio Camuffo - * - * 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 "wayland-client-protocol-core.h" -#include "wayland-server-protocol-core.h" - -#ifndef WAYLAND_CLIENT_CORE_H -#error including wayland-client-protocol-core.h did not include wayland-client-core.h! -#endif -#ifndef WAYLAND_SERVER_CORE_H -#error including wayland-server-protocol-core.h did not include wayland-server-core.h! -#endif - -#ifdef WAYLAND_CLIENT_H -#error including wayland-client-protocol-core.h included wayland-client.h! -#endif -#ifdef WAYLAND_SERVER_H -#error including wayland-server-protocol-core.h included wayland-server.h! -#endif diff --git a/tests/headers-protocol-test.c b/tests/headers-protocol-test.c deleted file mode 100644 index 87952f7e..00000000 --- a/tests/headers-protocol-test.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2015 Giulio Camuffo - * - * 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 "wayland-client-protocol.h" -#include "wayland-server-protocol.h" - -#ifndef WAYLAND_CLIENT_H -#error including wayland-client-protocol.h did not include wayland-client.h! -#endif -#ifndef WAYLAND_SERVER_H -#error including wayland-server-protocol.h did not include wayland-server.h! -#endif diff --git a/tests/headers-test.c b/tests/headers-test.c deleted file mode 100644 index 51856f82..00000000 --- a/tests/headers-test.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © 2015 Giulio Camuffo - * - * 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 "wayland-client-core.h" -#include "wayland-server-core.h" - -#ifdef WL_DISPLAY_SYNC -#error including wayland-client-core.h imported protocol symbols! -#endif -#ifdef WL_DISPLAY_ERROR -#error including wayland-server-core.h imported protocol symbols! -#endif - -#ifdef WAYLAND_CLIENT_H -#error including wayland-client-core.h included the non-core header! -#endif -#ifdef WAYLAND_SERVER_H -#error including wayland-server-core.h included the non-core header! -#endif - -#include "wayland-client.h" -#include "wayland-server.h" - -#ifndef WL_DISPLAY_SYNC -#error including wayland-client.h did not import protocol symbols! -#endif -#ifndef WL_DISPLAY_ERROR -#error including wayland-server.h did not import protocol symbols! -#endif - -int main(int argc, char **argv) { return 0; } diff --git a/tests/interface-test.c b/tests/interface-test.c deleted file mode 100644 index 5290bb65..00000000 --- a/tests/interface-test.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright © 2016 Yong Bakos - * - * 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 - -#include "wayland-client.h" -#include "wayland-private.h" -#include "test-runner.h" - -TEST(interface_equal) -{ - const struct wl_interface fake = { - "fake", 1, 0, NULL, 0, NULL - }; - const struct wl_interface fake_registry = { - "wl_registry", 1, 0, NULL, 0, NULL - }; - const struct wl_interface copy = wl_registry_interface; - - assert(&wl_registry_interface != ©); - - assert(wl_interface_equal(&wl_registry_interface, - &wl_registry_interface)); - assert(wl_interface_equal(&wl_registry_interface, ©)); - assert(wl_interface_equal(&wl_registry_interface, - &fake_registry)); - assert(!wl_interface_equal(&wl_registry_interface, &fake)); -} diff --git a/tests/list-test.c b/tests/list-test.c index 07526181..6058fe3b 100644 --- a/tests/list-test.c +++ b/tests/list-test.c @@ -1,26 +1,23 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 @@ -57,19 +54,6 @@ TEST(list_insert) assert(e.link.prev == &list); } -TEST(list_length) -{ - struct wl_list list; - struct element e; - - wl_list_init(&list); - assert(wl_list_length(&list) == 0); - wl_list_insert(&list, &e.link); - assert(wl_list_length(&list) == 1); - wl_list_remove(&e.link); - assert(wl_list_length(&list) == 0); -} - TEST(list_iterator) { struct wl_list list; @@ -119,7 +103,7 @@ validate_list(struct wl_list *list, int *reference, int length) return 0; i++; } - + if (i != length) return 0; diff --git a/tests/map-test.c b/tests/map-test.c index 03568ea7..3df374c8 100644 --- a/tests/map-test.c +++ b/tests/map-test.c @@ -1,31 +1,27 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 #include -#include #include #include "wayland-private.h" #include "test-runner.h" @@ -119,19 +115,3 @@ TEST(map_flags) wl_map_release(&map); } - -static enum wl_iterator_result never_run(void *element, void *data, uint32_t flags) -{ - assert(0); -} - -TEST(map_iter_empty) -{ - struct wl_map map; - - wl_map_init(&map, WL_MAP_SERVER_SIDE); - - wl_map_for_each(&map, never_run, NULL); - - wl_map_release(&map); -} diff --git a/tests/meson.build b/tests/meson.build deleted file mode 100644 index 6ada5202..00000000 --- a/tests/meson.build +++ /dev/null @@ -1,214 +0,0 @@ -if not get_option('libraries') - error('-Dtests=true requires -Dlibraries=true') -endif - -test_runner = static_library( - 'test-runner', - sources: [ - 'test-runner.c', - 'test-helpers.c', - 'test-compositor.c' - ], - include_directories: [ root_inc, src_inc ], - dependencies: [ - cc.find_library('dl', required: false), - dependency('threads'), - epoll_dep, - ffi_dep, - wayland_util_dep, - wayland_private_dep, - wayland_client_dep, - wayland_server_dep - ] -) - -test_runner_dep = declare_dependency( - link_with: test_runner, - include_directories: [ src_inc ], - dependencies: [ - dependency('threads'), - cc.find_library('dl', required: false) - ] -) - -tests_protocol_xml = files('../protocol/tests.xml') - -tests_server_protocol_h = custom_target( - 'test server protocol header', - command: [ wayland_scanner_for_build, '-s', 'server-header', '@INPUT@', '@OUTPUT@' ], - input: tests_protocol_xml, - output: 'tests-server-protocol.h' -) - -tests_client_protocol_c = custom_target( - 'test client protocol header', - command: [ wayland_scanner_for_build, '-s', 'client-header', '@INPUT@', '@OUTPUT@' ], - input: tests_protocol_xml, - output: 'tests-client-protocol.h' -) - -tests_protocol_c = custom_target( - 'test protocol source', - command: [ wayland_scanner_for_build, '-s', 'public-code', '@INPUT@', '@OUTPUT@' ], - input: tests_protocol_xml, - output: 'tests-protocol.c' -) - -exec_fd_leak_checker = executable( - 'exec-fd-leak-checker', - 'exec-fd-leak-checker.c', - dependencies: test_runner_dep -) - -if add_languages('cpp', native: false) - test( - 'cpp-compile-test', - executable( - 'cpp-compile-test', - 'cpp-compile-test.cpp', - wayland_server_protocol_h, - include_directories: src_inc - ) - ) -endif - -sed_path = find_program('sed').full_path() - -if get_option('scanner') - scanner_test_env = [ - 'TEST_DATA_DIR=@0@/data'.format(meson.current_source_dir()), - 'TEST_OUTPUT_DIR=@0@/output'.format(meson.current_build_dir()), - 'SED=@0@'.format(sed_path), - 'WAYLAND_SCANNER=@0@'.format(wayland_scanner.full_path()), - ] - - test( - 'scanner-test', - find_program('scanner-test.sh'), - env: scanner_test_env, - ) - - run_target( - 'gen-scanner-test', - command: find_program('scanner-test-gen.sh'), - env: scanner_test_env, - ) -endif - -tests = { - 'array-test': {}, - 'client-test': { - 'extra_sources': [ wayland_server_protocol_h ], - }, - 'display-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - tests_server_protocol_h, - tests_client_protocol_c, - tests_protocol_c, - ], - }, - 'connection-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'event-loop-test': { - 'extra_sources': [ wayland_server_protocol_h ], - }, - 'fixed-test': {}, - 'interface-test': { - 'extra_sources': [ wayland_client_protocol_h ], - }, - 'list-test': {}, - 'map-test': {}, - 'sanity-test' : { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - 'runtime_deps': [ exec_fd_leak_checker ], - }, - 'socket-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'queue-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'signal-test': { - 'extra_sources': [ wayland_server_protocol_h ], - }, - 'newsignal-test': { - 'extra_sources': [ - # wayland-server.c is needed here to access wl_priv_* functions - files('../src/wayland-server.c'), - wayland_server_protocol_h, - ], - }, - 'resources-test': { - 'extra_sources': [ wayland_server_protocol_h ], - }, - 'message-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'compositor-introspection-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'protocol-logger-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'headers-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - 'headers-protocol-test.c', - wayland_client_protocol_core_h, - wayland_server_protocol_core_h, - 'headers-protocol-core-test.c', - ], - }, - 'os-wrappers-test': { - 'runtime_deps': [ exec_fd_leak_checker ], - }, - 'proxy-test': { - 'extra_sources': [ - wayland_client_protocol_h, - wayland_server_protocol_h, - ], - }, - 'enum-validator-test': {}, -} - -foreach test_name, test_extras : tests - test_extra_sources = test_extras.get('extra_sources', []) - test_runtime_deps = test_extras.get('runtime_deps', []) - test_sources = [ test_name + '.c' ] + test_extra_sources - test_deps = [test_runner_dep, epoll_dep] - bin = executable(test_name, test_sources, dependencies: test_deps) - test( - test_name, - bin, - depends: test_runtime_deps, - env: [ - 'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()), - 'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()), - ], - ) -endforeach diff --git a/tests/message-test.c b/tests/message-test.c index 86f387ab..b5b00a46 100644 --- a/tests/message-test.c +++ b/tests/message-test.c @@ -1,26 +1,23 @@ /* * Copyright © 2014 Jonas Ådahl * - * 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: + * 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 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. + * 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 @@ -51,40 +48,3 @@ TEST(message_version) messages[i].expected_version); } } - -TEST(message_count_arrays) -{ - unsigned int i; - struct wl_message fake_messages[] = { - { "empty", "", NULL }, - { "non_present", "iufsonh", NULL }, - { "leading", "aiufsonh", NULL}, - { "trailing", "iufsonha", NULL }, - { "middle", "iufasonh", NULL }, - { "multiple", "aaiufaasonhaa", NULL }, - { "leading_version", "2aaiufaasonhaa", NULL }, - { "among_nullables", "iufsa?oa?sah", NULL }, - { "all_mixed", "2aiufas?oa?sa", NULL }, - }; - const struct { - const struct wl_message *message; - int expected_array_count; - } messages[] = { - { &wl_pointer_interface.events[WL_POINTER_ENTER], 0 }, - { &wl_keyboard_interface.events[WL_KEYBOARD_ENTER], 1 }, - { &fake_messages[0], 0 }, - { &fake_messages[1], 0 }, - { &fake_messages[2], 1 }, - { &fake_messages[3], 1 }, - { &fake_messages[4], 1 }, - { &fake_messages[5], 6 }, - { &fake_messages[6], 6 }, - { &fake_messages[7], 3 }, - { &fake_messages[8], 4 }, - }; - - for (i = 0; i < ARRAY_LENGTH(messages); ++i) { - assert(wl_message_count_arrays(messages[i].message) == - messages[i].expected_array_count); - } -} diff --git a/tests/newsignal-test.c b/tests/newsignal-test.c deleted file mode 100644 index 051e10e8..00000000 --- a/tests/newsignal-test.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright © 2013 Marek Chalupa - * - * 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 - -#include "test-runner.h" -#include "wayland-server-private.h" - -static void -signal_notify(struct wl_listener *listener, void *data) -{ - /* only increase counter*/ - ++(*((int *) data)); -} - -TEST(signal_init) -{ - struct wl_priv_signal signal; - - wl_priv_signal_init(&signal); - - /* Test if listeners' list is initialized */ - assert(&signal.listener_list == signal.listener_list.next - && "Maybe wl_priv_signal implementation changed?"); - assert(signal.listener_list.next == signal.listener_list.prev - && "Maybe wl_priv_signal implementation changed?"); -} - -TEST(signal_add_get) -{ - struct wl_priv_signal signal; - - /* we just need different values of notify */ - struct wl_listener l1 = {.notify = (wl_notify_func_t) 0x1}; - struct wl_listener l2 = {.notify = (wl_notify_func_t) 0x2}; - struct wl_listener l3 = {.notify = (wl_notify_func_t) 0x3}; - /* one real, why not */ - struct wl_listener l4 = {.notify = signal_notify}; - - wl_priv_signal_init(&signal); - - wl_priv_signal_add(&signal, &l1); - wl_priv_signal_add(&signal, &l2); - wl_priv_signal_add(&signal, &l3); - wl_priv_signal_add(&signal, &l4); - - assert(wl_priv_signal_get(&signal, signal_notify) == &l4); - assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3); - assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2); - assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1); - - /* get should not be destructive */ - assert(wl_priv_signal_get(&signal, signal_notify) == &l4); - assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3); - assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2); - assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1); -} - -TEST(signal_emit_to_one_listener) -{ - int count = 0; - int counter; - - struct wl_priv_signal signal; - struct wl_listener l1 = {.notify = signal_notify}; - - wl_priv_signal_init(&signal); - wl_priv_signal_add(&signal, &l1); - - for (counter = 0; counter < 100; counter++) - wl_priv_signal_emit(&signal, &count); - - assert(counter == count); -} - -TEST(signal_emit_to_more_listeners) -{ - int count = 0; - int counter; - - struct wl_priv_signal signal; - struct wl_listener l1 = {.notify = signal_notify}; - struct wl_listener l2 = {.notify = signal_notify}; - struct wl_listener l3 = {.notify = signal_notify}; - - wl_priv_signal_init(&signal); - wl_priv_signal_add(&signal, &l1); - wl_priv_signal_add(&signal, &l2); - wl_priv_signal_add(&signal, &l3); - - for (counter = 0; counter < 100; counter++) - wl_priv_signal_emit(&signal, &count); - - assert(3 * counter == count); -} - -struct signal -{ - struct wl_priv_signal signal; - struct wl_listener l1, l2, l3; - int count; - struct wl_listener *current; -}; - -static void notify_remove(struct wl_listener *l, void *data) -{ - struct signal *sig = data; - wl_list_remove(&sig->current->link); - wl_list_init(&sig->current->link); - sig->count++; -} - -#define INIT \ - wl_priv_signal_init(&signal.signal); \ - wl_list_init(&signal.l1.link); \ - wl_list_init(&signal.l2.link); \ - wl_list_init(&signal.l3.link); -#define CHECK_EMIT(expected) \ - signal.count = 0; \ - wl_priv_signal_emit(&signal.signal, &signal); \ - assert(signal.count == expected); - -TEST(signal_remove_listener) -{ - test_set_timeout(4); - - struct signal signal; - - signal.l1.notify = notify_remove; - signal.l2.notify = notify_remove; - signal.l3.notify = notify_remove; - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - - signal.current = &signal.l1; - CHECK_EMIT(1) - CHECK_EMIT(0) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - - CHECK_EMIT(2) - CHECK_EMIT(1) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - - signal.current = &signal.l2; - CHECK_EMIT(1) - CHECK_EMIT(1) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - wl_priv_signal_add(&signal.signal, &signal.l3); - - signal.current = &signal.l1; - CHECK_EMIT(3) - CHECK_EMIT(2) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - wl_priv_signal_add(&signal.signal, &signal.l3); - - signal.current = &signal.l2; - CHECK_EMIT(2) - CHECK_EMIT(2) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - wl_priv_signal_add(&signal.signal, &signal.l3); - - signal.current = &signal.l3; - CHECK_EMIT(2) - CHECK_EMIT(2) -} - -static void notify_readd(struct wl_listener *l, void *data) -{ - struct signal *signal = data; - if (signal->current) { - wl_list_remove(&signal->current->link); - wl_list_init(&signal->current->link); - wl_priv_signal_add(&signal->signal, signal->current); - } - signal->count++; -} - -static void notify_empty(struct wl_listener *l, void *data) -{ - struct signal *signal = data; - signal->count++; -} - -TEST(signal_readd_listener) -{ - /* Readding a listener is supported, that is it doesn't trigger an - * infinite loop or other weird things, but if in a listener you - * re-add another listener, that will not be fired in the current - * signal emission. */ - - test_set_timeout(4); - - struct signal signal; - - signal.l1.notify = notify_readd; - signal.l2.notify = notify_readd; - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - - signal.current = &signal.l1; - CHECK_EMIT(1) - CHECK_EMIT(1) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - - signal.current = &signal.l2; - CHECK_EMIT(1) - signal.current = NULL; - CHECK_EMIT(2) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l2); - - signal.current = &signal.l1; - CHECK_EMIT(1) - /* l2 was added before l1, so l2 is fired first, which by readding l1 - * removes it from the current list that is being fired, so 1 is correct */ - CHECK_EMIT(1) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - - signal.l1.notify = notify_empty; - signal.current = &signal.l2; - CHECK_EMIT(2) - CHECK_EMIT(2) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - - signal.l1.notify = notify_empty; - signal.current = &signal.l1; - CHECK_EMIT(2) - /* same as before, by readding l1 in the first emit, it now is fired - * after l2, so on the second emit it is not fired at all. */ - CHECK_EMIT(1) -} - -static void notify_addandget(struct wl_listener *l, void *data) -{ - struct signal *signal = data; - wl_list_remove(&signal->current->link); - wl_list_init(&signal->current->link); - wl_priv_signal_add(&signal->signal, signal->current); - - assert(wl_priv_signal_get(&signal->signal, signal->current->notify) != NULL); - - signal->count++; -} - -static void notify_get(struct wl_listener *l, void *data) -{ - struct signal *signal = data; - assert(wl_priv_signal_get(&signal->signal, signal->current->notify) == signal->current); - signal->count++; -} - -TEST(signal_get_listener) -{ - test_set_timeout(4); - - struct signal signal; - - signal.l1.notify = notify_addandget; - signal.l2.notify = notify_get; - - INIT - wl_priv_signal_add(&signal.signal, &signal.l1); - - signal.current = &signal.l2; - CHECK_EMIT(1) - - INIT - wl_priv_signal_add(&signal.signal, &signal.l2); - - signal.current = &signal.l2; - CHECK_EMIT(1) - - INIT - signal.l1.notify = notify_get; - signal.l2.notify = notify_empty; - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - - CHECK_EMIT(2) - - INIT - signal.l1.notify = notify_empty; - signal.l2.notify = notify_get; - wl_priv_signal_add(&signal.signal, &signal.l1); - wl_priv_signal_add(&signal.signal, &signal.l2); - - signal.current = &signal.l1; - CHECK_EMIT(2) -} diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 061d29e6..e5cdac44 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -2,38 +2,34 @@ * Copyright © 2012 Collabora, Ltd. * Copyright © 2012 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: + * 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 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. + * 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" #define _GNU_SOURCE #include -#include #include #include #include #include #include +#include #include #include #include @@ -44,20 +40,32 @@ #include "test-runner.h" #include "wayland-os.h" -extern int (*wl_socket)(int domain, int type, int protocol); -extern int (*wl_fcntl)(int fildes, int cmd, ...); -extern ssize_t (*wl_recvmsg)(int socket, struct msghdr *message, int flags); -extern int (*wl_epoll_create1)(int flags); - static int fall_back; -static int wrapped_calls_socket = 0; -static int wrapped_calls_fcntl = 0; -static int wrapped_calls_recvmsg = 0; -static int wrapped_calls_epoll_create1 = 0; +static int (*real_socket)(int, int, int); +static int wrapped_calls_socket; -static int -socket_wrapper(int domain, int type, int protocol) +static int (*real_fcntl)(int, int, ...); +static int wrapped_calls_fcntl; + +static ssize_t (*real_recvmsg)(int, struct msghdr *, int); +static int wrapped_calls_recvmsg; + +static int (*real_epoll_create1)(int); +static int wrapped_calls_epoll_create1; + +static void +init_fallbacks(int do_fallbacks) +{ + fall_back = do_fallbacks; + real_socket = dlsym(RTLD_NEXT, "socket"); + real_fcntl = dlsym(RTLD_NEXT, "fcntl"); + real_recvmsg = dlsym(RTLD_NEXT, "recvmsg"); + real_epoll_create1 = dlsym(RTLD_NEXT, "epoll_create1"); +} + +__attribute__ ((visibility("default"))) int +socket(int domain, int type, int protocol) { wrapped_calls_socket++; @@ -66,15 +74,14 @@ socket_wrapper(int domain, int type, int protocol) return -1; } - return socket(domain, type, protocol); + return real_socket(domain, type, protocol); } -static int -fcntl_wrapper(int fd, int cmd, ...) +__attribute__ ((visibility("default"))) int +fcntl(int fd, int cmd, ...) { va_list ap; - int arg; - int has_arg; + void *arg; wrapped_calls_fcntl++; @@ -82,31 +89,16 @@ fcntl_wrapper(int fd, int cmd, ...) errno = EINVAL; return -1; } - switch (cmd) { - case F_DUPFD_CLOEXEC: - case F_DUPFD: - case F_SETFD: - va_start(ap, cmd); - arg = va_arg(ap, int); - has_arg = 1; - va_end(ap); - break; - case F_GETFD: - has_arg = 0; - break; - default: - fprintf(stderr, "Unexpected fctnl cmd %d\n", cmd); - abort(); - } - if (has_arg) { - return fcntl(fd, cmd, arg); - } - return fcntl(fd, cmd); + va_start(ap, cmd); + arg = va_arg(ap, void*); + va_end(ap); + + return real_fcntl(fd, cmd, arg); } -static ssize_t -recvmsg_wrapper(int sockfd, struct msghdr *msg, int flags) +__attribute__ ((visibility("default"))) ssize_t +recvmsg(int sockfd, struct msghdr *msg, int flags) { wrapped_calls_recvmsg++; @@ -115,11 +107,11 @@ recvmsg_wrapper(int sockfd, struct msghdr *msg, int flags) return -1; } - return recvmsg(sockfd, msg, flags); + return real_recvmsg(sockfd, msg, flags); } -static int -epoll_create1_wrapper(int flags) +__attribute__ ((visibility("default"))) int +epoll_create1(int flags) { wrapped_calls_epoll_create1++; @@ -129,17 +121,7 @@ epoll_create1_wrapper(int flags) return -1; } - return epoll_create1(flags); -} - -static void -init_fallbacks(int do_fallbacks) -{ - fall_back = do_fallbacks; - wl_fcntl = fcntl_wrapper; - wl_socket = socket_wrapper; - wl_recvmsg = recvmsg_wrapper; - wl_epoll_create1 = epoll_create1_wrapper; + return real_epoll_create1(flags); } static void @@ -235,17 +217,15 @@ setup_marshal_data(struct marshal_data *data) assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); - data->read_connection = wl_connection_create(data->s[0], - WL_BUFFER_DEFAULT_MAX_SIZE); + data->read_connection = wl_connection_create(data->s[0]); assert(data->read_connection); - data->write_connection = wl_connection_create(data->s[1], - WL_BUFFER_DEFAULT_MAX_SIZE); + data->write_connection = wl_connection_create(data->s[1]); assert(data->write_connection); } static void -marshal_demarshal(struct marshal_data *data, +marshal_demarshal(struct marshal_data *data, void (*func)(void), int size, const char *format, ...) { struct wl_closure *closure; @@ -323,13 +303,7 @@ do_os_wrappers_recvmsg_cloexec(int n) struct marshal_data data; data.nr_fds_begin = count_open_fds(); -#if HAVE_BROKEN_MSG_CMSG_CLOEXEC - /* We call the fallback directly on FreeBSD versions with a broken - * MSG_CMSG_CLOEXEC, so we don't call the local recvmsg() wrapper. */ - data.wrapped_calls = 0; -#else data.wrapped_calls = n; -#endif setup_marshal_data(&data); data.nr_fds_conn = count_open_fds(); diff --git a/tests/protocol-logger-test.c b/tests/protocol-logger-test.c deleted file mode 100644 index a0ebd22a..00000000 --- a/tests/protocol-logger-test.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com - * - * 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 -#include -#include -#include -#include -#include -#include - -#include "wayland-client.h" -#include "wayland-server.h" -#include "test-runner.h" - -/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */ -static const char * -require_xdg_runtime_dir(void) -{ - char *val = getenv("XDG_RUNTIME_DIR"); - assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test"); - - return val; -} - -struct compositor { - struct wl_display *display; - struct wl_event_loop *loop; - int message; - struct wl_client *client; -}; - -struct message { - enum wl_protocol_logger_type type; - const char *class; - int opcode; - const char *message_name; - int args_count; -} messages[] = { - { - .type = WL_PROTOCOL_LOGGER_REQUEST, - .class = "wl_display", - .opcode = 0, - .message_name = "sync", - .args_count = 1, - }, - { - .type = WL_PROTOCOL_LOGGER_EVENT, - .class = "wl_callback", - .opcode = 0, - .message_name = "done", - .args_count = 1, - }, - { - .type = WL_PROTOCOL_LOGGER_EVENT, - .class = "wl_display", - .opcode = 1, - .message_name = "delete_id", - .args_count = 1, - }, -}; - -static void -logger_func(void *user_data, enum wl_protocol_logger_type type, - const struct wl_protocol_logger_message *message) -{ - struct compositor *c = user_data; - struct message *msg = &messages[c->message++]; - - assert(msg->type == type); - assert(strcmp(msg->class, wl_resource_get_class(message->resource)) == 0); - assert(msg->opcode == message->message_opcode); - assert(strcmp(msg->message_name, message->message->name) == 0); - assert(msg->args_count == message->arguments_count); - - c->client = wl_resource_get_client(message->resource); -} - -static void -callback_done(void *data, struct wl_callback *cb, uint32_t time) -{ - wl_callback_destroy(cb); -} - -static const struct wl_callback_listener callback_listener = { - callback_done, -}; - -TEST(logger) -{ - test_set_timeout(1); - - const char *socket; - struct compositor compositor = { 0 }; - struct { - struct wl_display *display; - struct wl_callback *cb; - } client; - struct wl_protocol_logger *logger; - - require_xdg_runtime_dir(); - - compositor.display = wl_display_create(); - compositor.loop = wl_display_get_event_loop(compositor.display); - socket = wl_display_add_socket_auto(compositor.display); - - logger = wl_display_add_protocol_logger(compositor.display, - logger_func, &compositor); - - client.display = wl_display_connect(socket); - client.cb = wl_display_sync(client.display); - wl_callback_add_listener(client.cb, &callback_listener, NULL); - wl_display_flush(client.display); - - while (compositor.message < 3) { - wl_event_loop_dispatch(compositor.loop, -1); - wl_display_flush_clients(compositor.display); - } - - wl_display_dispatch(client.display); - wl_display_disconnect(client.display); - - wl_client_destroy(compositor.client); - wl_protocol_logger_destroy(logger); - wl_display_destroy(compositor.display); -} diff --git a/tests/proxy-test.c b/tests/proxy-test.c deleted file mode 100644 index 2a8f4254..00000000 --- a/tests/proxy-test.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * - * 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 -#include - -#include "wayland-server.h" -#include "wayland-client.h" -#include "test-runner.h" - -static struct { - struct wl_display *display; - struct wl_event_loop *loop; - int sync_count; -} server; - -static struct { - struct wl_display *display; - struct wl_callback *callback_a; - struct wl_callback *callback_b; - int callback_count; -} client; - -static const char *tag_a = "tag"; -static const char *tag_b = "tag"; - -static void -callback_done(void *data, struct wl_callback *cb, uint32_t time) -{ - const char * const *expected_tag; - const char * const *tag; - - if (cb == client.callback_a) - expected_tag = &tag_a; - else if (cb == client.callback_b) - expected_tag = &tag_b; - else - assert(!"unexpected callback"); - - tag = wl_proxy_get_tag((struct wl_proxy *) cb); - - assert(tag == expected_tag); - assert(strcmp(*tag, "tag") == 0); - - wl_callback_destroy(cb); - - client.callback_count++; -} - -static const struct wl_callback_listener callback_listener = { - callback_done, -}; - -static void -logger_func(void *user_data, - enum wl_protocol_logger_type type, - const struct wl_protocol_logger_message *message) -{ - if (type != WL_PROTOCOL_LOGGER_REQUEST) - return; - - assert(strcmp(wl_resource_get_class(message->resource), - "wl_display") == 0); - assert(strcmp(message->message->name, "sync") == 0); - - server.sync_count++; -} - -TEST(proxy_tag) -{ - const char *socket; - struct wl_protocol_logger *logger; - - assert(&tag_a != &tag_b); - - server.display = wl_display_create(); - assert(server.display); - server.loop = wl_display_get_event_loop(server.display); - assert(server.loop); - socket = wl_display_add_socket_auto(server.display); - assert(socket); - logger = wl_display_add_protocol_logger(server.display, - logger_func, NULL); - assert(logger); - - client.display = wl_display_connect(socket); - assert(client.display); - - client.callback_a = wl_display_sync(client.display); - wl_callback_add_listener(client.callback_a, &callback_listener, NULL); - wl_proxy_set_tag((struct wl_proxy *) client.callback_a, - &tag_a); - - client.callback_b = wl_display_sync(client.display); - wl_callback_add_listener(client.callback_b, &callback_listener, NULL); - wl_proxy_set_tag((struct wl_proxy *) client.callback_b, - &tag_b); - - assert(wl_proxy_get_display((struct wl_proxy *) client.callback_b) == client.display); - - wl_display_flush(client.display); - - while (server.sync_count < 2) { - wl_event_loop_dispatch(server.loop, -1); - wl_display_flush_clients(server.display); - } - - wl_display_dispatch(client.display); - - assert(client.callback_count == 2); - - wl_protocol_logger_destroy(logger); - wl_display_disconnect(client.display); - wl_event_loop_dispatch(server.loop, 100); - - wl_display_destroy(server.display); -} diff --git a/tests/queue-test.c b/tests/queue-test.c index 2b2d9ad4..96f21005 100644 --- a/tests/queue-test.c +++ b/tests/queue-test.c @@ -1,46 +1,37 @@ /* * Copyright © 2012 Jonas Ådahl * - * 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: + * 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 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. + * 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. */ -#define _GNU_SOURCE /* For memrchr */ #include -#include #include #include -#include #include -#include #include #include #include -#include #include "wayland-client.h" #include "wayland-server.h" #include "test-runner.h" #include "test-compositor.h" -#include "../src/timespec-util.h" #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) @@ -75,7 +66,7 @@ client_test_proxy_destroy(void) assert(registry != NULL); wl_registry_add_listener(registry, ®istry_listener, &counter); - assert(wl_display_roundtrip(display) != -1); + wl_display_roundtrip(display); assert(counter == 1); @@ -210,480 +201,13 @@ client_test_queue_roundtrip(void) wl_display_disconnect(display); } -static void -client_test_queue_proxy_wrapper(void) -{ - struct wl_event_queue *queue; - struct wl_display *display; - struct wl_display *display_wrapper; - struct wl_callback *callback; - bool done = false; - - /* - * For an illustration of what usage would normally fail without using - * proxy wrappers, see the `client_test_queue_set_queue_race' test case. - */ - - display = wl_display_connect(NULL); - assert(display); - - /* Pretend we are in a separate thread where a thread-local queue is - * used. */ - queue = wl_display_create_queue(display); - assert(queue); - - display_wrapper = wl_proxy_create_wrapper(display); - assert(display_wrapper); - wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); - callback = wl_display_sync(display_wrapper); - wl_proxy_wrapper_destroy(display_wrapper); - assert(callback != NULL); - - /* Pretend we are now another thread and dispatch the dispatch the main - * queue while also knowing our callback is read and queued. */ - wl_display_roundtrip(display); - - /* Make sure that the pretend-to-be main thread didn't dispatch our - * callback, behind our back. */ - wl_callback_add_listener(callback, &sync_listener_roundtrip, &done); - wl_display_flush(display); - - assert(!done); - - /* Make sure that we eventually end up dispatching our callback. */ - while (!done) - assert(wl_display_dispatch_queue(display, queue) != -1); - - wl_callback_destroy(callback); - wl_event_queue_destroy(queue); - - wl_display_disconnect(display); -} - -static void -client_test_queue_set_queue_race(void) -{ - struct wl_event_queue *queue; - struct wl_display *display; - struct wl_callback *callback; - bool done = false; - - /* - * This test illustrates the multi threading scenario which would fail - * without doing what is done in the `client_test_queue_proxy_wrapper' - * test. - */ - - display = wl_display_connect(NULL); - assert(display); - - /* Pretend we are in a separate thread where a thread-local queue is - * used. */ - queue = wl_display_create_queue(display); - assert(queue); - - callback = wl_display_sync(display); - assert(callback != NULL); - - /* Pretend we are now another thread and dispatch the dispatch the main - * queue while also knowing our callback is read, queued on the wrong - * queue, and dispatched. */ - wl_display_roundtrip(display); - - /* Pretend we are back in the separate thread, and continue with setting - * up our callback. */ - wl_callback_add_listener(callback, &sync_listener_roundtrip, &done); - wl_proxy_set_queue((struct wl_proxy *) callback, queue); - - /* Roundtrip our separate thread queue to make sure any events are - * dispatched. */ - wl_display_roundtrip_queue(display, queue); - - /* Verify that the callback has indeed been dropped. */ - assert(!done); - - wl_callback_destroy(callback); - wl_event_queue_destroy(queue); - - wl_display_disconnect(display); -} - -static char * -maybe_map_file(int fd, size_t *len) -{ - char *data; - - *len = lseek(fd, 0, SEEK_END); - data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0); - - return data; -} - -static char * -map_file(int fd, size_t *len) -{ - char *data; - - data = maybe_map_file(fd, len); - assert(data != MAP_FAILED && "Failed to mmap file"); - - return data; -} - -static char * -last_line_of(char *s) -{ - size_t len = strlen(s); - char *last; - - last = memrchr(s, '\n', len); - /* If we found a newline at end of string, find the previous one. */ - if (last && last[1] == 0) - last = memrchr(s, '\n', len - 1); - /* If we have a newline, the last line starts after the newline. - * Otherwise, the whole string is the last line. */ - if (last) - last += 1; - else - last = s; - - return last; -} - -static void -client_test_queue_destroy_with_attached_proxies(void) -{ - struct wl_event_queue *queue; - struct wl_display *display; - struct wl_display *display_wrapper; - struct wl_callback *callback; - char *log; - size_t log_len; - char callback_name[24]; - int ret; - - display = wl_display_connect(NULL); - assert(display); - - /* Pretend we are in a separate thread where a thread-local queue is - * used. */ - queue = wl_display_create_queue(display); - assert(queue); - - /* Create a sync dispatching events on the thread-local queue. */ - display_wrapper = wl_proxy_create_wrapper(display); - assert(display_wrapper); - wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); - callback = wl_display_sync(display_wrapper); - wl_proxy_wrapper_destroy(display_wrapper); - assert(callback != NULL); - - /* Destroy the queue before the attached object. */ - wl_event_queue_destroy(queue); - - /* Check that the log contains some information about the attached - * wl_callback proxy. */ - log = map_file(client_log_fd, &log_len); - ret = snprintf(callback_name, sizeof(callback_name), "wl_callback#%u", - wl_proxy_get_id((struct wl_proxy *) callback)); - assert(ret > 0 && ret < (int)sizeof(callback_name) && - "callback name creation failed (possibly truncated)"); - assert(strstr(last_line_of(log), callback_name)); - munmap(log, log_len); - - wl_callback_destroy(callback); - - wl_display_disconnect(display); -} - -static void -client_test_queue_proxy_event_to_destroyed_queue(void) -{ - struct wl_event_queue *queue; - struct wl_display *display; - struct wl_display *display_wrapper; - struct wl_callback *callback; - - display = wl_display_connect(NULL); - assert(display); - - /* Pretend we are in a separate thread where a thread-local queue is - * used. */ - queue = wl_display_create_queue(display); - assert(queue); - - /* Create a sync dispatching events on the thread-local queue. */ - display_wrapper = wl_proxy_create_wrapper(display); - assert(display_wrapper); - wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); - callback = wl_display_sync(display_wrapper); - wl_proxy_wrapper_destroy(display_wrapper); - assert(callback != NULL); - wl_display_flush(display); - - /* Destroy the queue before the attached object. */ - wl_event_queue_destroy(queue); - - /* During this roundtrip we should receive the done event on 'callback', - * try to queue it to the destroyed queue, and abort. */ - wl_display_roundtrip(display); - - wl_callback_destroy(callback); - - wl_display_disconnect(display); -} - -static void -client_test_queue_destroy_default_with_attached_proxies(void) -{ - struct wl_display *display; - struct wl_callback *callback; - char *log; - size_t log_len; - char callback_name[24]; - int ret; - - display = wl_display_connect(NULL); - assert(display); - - /* Create a sync dispatching events on the default queue. */ - callback = wl_display_sync(display); - assert(callback != NULL); - - /* Destroy the default queue (by disconnecting) before the attached - * object. */ - wl_display_disconnect(display); - - /* Check that the log does not contain any warning about the attached - * wl_callback proxy. */ - log = maybe_map_file(client_log_fd, &log_len); - ret = snprintf(callback_name, sizeof(callback_name), "wl_callback#%u", - wl_proxy_get_id((struct wl_proxy *) callback)); - assert(ret > 0 && ret < (int)sizeof(callback_name) && - "callback name creation failed (possibly truncated)"); - assert(log == MAP_FAILED || strstr(log, callback_name) == NULL); - if (log != MAP_FAILED) - munmap(log, log_len); - - /* HACK: Directly free the memory of the wl_callback proxy to appease - * ASan. We would normally use wl_callback_destroy(), but since we have - * destroyed the associated wl_display, using this function would lead - * to memory errors. */ - free(callback); -} - -static void -check_queue_name(struct wl_proxy *proxy, const char *name) -{ - struct wl_event_queue *queue; - const char *queue_name; - - queue = wl_proxy_get_queue(proxy); - queue_name = wl_event_queue_get_name(queue); - if (!name) - assert(!queue_name); - else - assert(strcmp(queue_name, name) == 0); -} - -static struct wl_callback * -roundtrip_named_queue_nonblock(struct wl_display *display, - struct wl_event_queue *queue, - const char *name) -{ - struct wl_callback *callback; - struct wl_display *wrapped_display = NULL; - - if (queue) { - wrapped_display = wl_proxy_create_wrapper(display); - assert(wrapped_display); - wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue); - check_queue_name((struct wl_proxy *) wrapped_display, name); - - callback = wl_display_sync(wrapped_display); - } else - callback = wl_display_sync(display); - - check_queue_name((struct wl_proxy *) callback, name); - - if (wrapped_display) - wl_proxy_wrapper_destroy(wrapped_display); - - assert(callback != NULL); - - return callback; -} - -static void -client_test_queue_names(void) -{ - struct wl_event_queue *queue1, *queue2, *queue3; - struct wl_display *display; - struct wl_callback *callback1, *callback2, *callback3, *callback4; - struct wl_event_queue *default_queue; - char *log; - size_t log_len; - const char *default_queue_name; - - display = wl_display_connect(NULL); - assert(display); - - default_queue = wl_proxy_get_queue((struct wl_proxy *) display); - default_queue_name = wl_event_queue_get_name(default_queue); - assert(strcmp(default_queue_name, "Default Queue") == 0); - - /* Create some event queues both with and without names. */ - queue1 = wl_display_create_queue_with_name(display, "First"); - assert(queue1); - - queue2 = wl_display_create_queue_with_name(display, "Second"); - assert(queue2); - - queue3 = wl_display_create_queue(display); - assert(queue3); - - /* Create some requests and ensure their queues have the expected - * names. - */ - callback1 = roundtrip_named_queue_nonblock(display, queue1, "First"); - callback2 = roundtrip_named_queue_nonblock(display, queue2, "Second"); - callback3 = roundtrip_named_queue_nonblock(display, queue3, NULL); - callback4 = roundtrip_named_queue_nonblock(display, NULL, "Default Queue"); - - /* Destroy one queue with proxies still attached so we can verify - * that the queue name is in the log message. */ - wl_event_queue_destroy(queue2); - log = map_file(client_log_fd, &log_len); - assert(strstr(log, "Second")); - - /* There's no reason for the First queue name to be present. */ - assert(!strstr(log, "First")); - - munmap(log, log_len); - - wl_callback_destroy(callback1); - wl_callback_destroy(callback2); - wl_callback_destroy(callback3); - wl_callback_destroy(callback4); - - wl_event_queue_destroy(queue1); - wl_event_queue_destroy(queue3); - - wl_display_disconnect(display); -} - -static void -dispatch_timeout_sync_callback(void *data, struct wl_callback *callback, - uint32_t serial) -{ - bool *done = data; - - *done = true; - wl_callback_destroy(callback); -} - -static const struct wl_callback_listener dispatch_timeout_sync_listener = { - dispatch_timeout_sync_callback -}; - -static void -client_test_queue_dispatch_simple(void) -{ - struct wl_display *display; - struct timespec timeout; - struct wl_callback *callback; - bool done = false; - int ret = 0; - - display = wl_display_connect(NULL); - assert(display); - - callback = wl_display_sync(display); - assert(callback != NULL); - wl_callback_add_listener(callback, &dispatch_timeout_sync_listener, &done); - - timespec_from_msec(&timeout, 1000); - - while (!done) { - ret = wl_display_dispatch_timeout(display, &timeout); - assert(ret > 0); - } - - wl_display_disconnect(display); - - exit(0); -} - -static void -client_test_queue_dispatch_timeout(void) -{ - struct wl_display *display; - struct timespec timeout; - int ret = 0; - - display = wl_display_connect(NULL); - assert(display); - - timespec_from_msec(&timeout, 100); - - ret = wl_display_dispatch_timeout(display, &timeout); - assert(ret == 0); - - wl_display_disconnect(display); - - exit(0); -} - -/* Try to use a proxy with a destroyed queue as a factory for - * another proxy (either normal or wrapper). This should succeed - * although the new proxy may not be useful until a queue is attached. - * The following code is safe to perform in the context of the test, since - * we are not flushing the display write buffer, neither explicitly - * (wl_display_flush()) nor implicitly (we don't place enough data to - * fill the display buffer and cause an auto-flush). */ -static void -client_test_queue_destroy_then_use_proxy_as_factory(void) -{ - struct wl_display *display; - struct wl_event_queue *queue; - struct wl_registry *registry, *registry_wrapper; - struct wl_proxy *proxy; - - display = wl_display_connect(NULL); - assert(display); - - /* Create registry with a queue that's immediately destroyed. */ - queue = wl_display_create_queue(display); - assert(queue); - registry = wl_display_get_registry(display); - assert(registry); - wl_proxy_set_queue((struct wl_proxy *) registry, queue); - wl_event_queue_destroy(queue); - - /* Scenario 1: Create a proxy using the registry (never flushed, - * so details don't matter). */ - proxy = wl_registry_bind(registry, 1000, &wl_output_interface, 1); - assert(proxy); - - /* Scenario 2: Create a wrapper proxy using the registry. */ - registry_wrapper = wl_proxy_create_wrapper(registry); - assert(registry_wrapper); - - wl_proxy_wrapper_destroy((struct wl_proxy *) registry_wrapper); - wl_proxy_destroy(proxy); - wl_registry_destroy(registry); - wl_display_disconnect(display); - - exit(0); -} - static void dummy_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { } -TEST(queue_proxy_destroy) +TEST(queue) { struct display *d; const struct wl_interface *dummy_interfaces[] = { @@ -701,152 +225,13 @@ TEST(queue_proxy_destroy) dummy_interfaces[i]->version, NULL, dummy_bind); - test_set_timeout(2); + client_create(d, client_test_proxy_destroy); + display_run(d); - client_create_noarg(d, client_test_proxy_destroy); - display_run(d); - - display_destroy(d); -} - -TEST(queue_multiple_queues) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_multiple_queues); - display_run(d); - - display_destroy(d); -} - -TEST(queue_roundtrip) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_roundtrip); - display_run(d); - - display_destroy(d); -} - -TEST(queue_set_queue_proxy_wrapper) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_proxy_wrapper); - display_run(d); - - display_destroy(d); -} - -TEST(queue_set_queue_race) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_set_queue_race); - display_run(d); - - display_destroy(d); -} - -TEST(queue_destroy_with_attached_proxies) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_destroy_with_attached_proxies); - display_run(d); - - display_destroy(d); -} - -TEST(queue_proxy_event_to_destroyed_queue) -{ - struct display *d = display_create(); - struct client_info *ci; - char *client_log; - size_t client_log_len; - - test_set_timeout(2); - - ci = client_create_noarg(d, client_test_queue_proxy_event_to_destroyed_queue); - display_run(d); - - /* Check that the final line in the log mentions the expected reason - * for the abort. */ - client_log = map_file(ci->log_fd, &client_log_len); - assert(!strcmp(last_line_of(client_log), - "Tried to add event to destroyed queue\n")); - munmap(client_log, client_log_len); - - /* Check that the client aborted. */ - display_destroy_expect_signal(d, SIGABRT); -} - -TEST(queue_destroy_default_with_attached_proxies) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_destroy_default_with_attached_proxies); - display_run(d); - - display_destroy(d); -} - -TEST(queue_names) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_names); - display_run(d); - - display_destroy(d); -} - -TEST(queue_dispatch_simple) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_dispatch_simple); - display_run(d); - - display_destroy(d); -} - -TEST(queue_dispatch_timeout) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_dispatch_timeout); - display_run(d); - - display_destroy(d); -} - -TEST(queue_destroy_then_use_proxy_as_factory) -{ - struct display *d = display_create(); - - test_set_timeout(2); - - client_create_noarg(d, client_test_queue_destroy_then_use_proxy_as_factory); + client_create(d, client_test_multiple_queues); + display_run(d); + + client_create(d, client_test_queue_roundtrip); display_run(d); display_destroy(d); diff --git a/tests/resources-test.c b/tests/resources-test.c index 92707297..a6ce3ae1 100644 --- a/tests/resources-test.c +++ b/tests/resources-test.c @@ -1,32 +1,28 @@ /* * Copyright © 2013 Marek Chalupa * - * 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: + * 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 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. + * 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 #include #include -#include #include "wayland-server.h" #include "test-runner.h" @@ -46,7 +42,7 @@ TEST(create_resource_tst) client = wl_client_create(display, s[0]); assert(client); - res = wl_resource_create(client, &wl_seat_interface, 4, 0); + res = wl_resource_create(client, &wl_display_interface, 4, 0); assert(res); /* setters/getters */ @@ -84,17 +80,6 @@ destroy_notify(struct wl_listener *l, void *data) { assert(l && data); notify_called = 1; - - /* In real code it's common to free the structure holding the - * listener at this point, but not to remove it from the list. - * - * That's fine since this is a destruction notification and - * it's the last time this signal can fire. We set these - * to NULL so we can check them later to ensure no write after - * "free" occurred. - */ - l->link.prev = NULL; - l->link.next = NULL; } TEST(destroy_res_tst) @@ -117,7 +102,7 @@ TEST(destroy_res_tst) client = wl_client_create(display, s[0]); assert(client); - res = wl_resource_create(client, &wl_seat_interface, 4, 0); + res = wl_resource_create(client, &wl_display_interface, 4, 0); assert(res); wl_resource_set_implementation(res, NULL, &destroyed, res_destroy_func); wl_resource_add_destroy_listener(res, &destroy_listener); @@ -130,10 +115,8 @@ TEST(destroy_res_tst) assert(destroyed); assert(notify_called); /* check if signal was emitted */ assert(wl_client_get_object(client, id) == NULL); - assert(destroy_listener.link.prev == NULL); - assert(destroy_listener.link.next == NULL); - res = wl_resource_create(client, &wl_seat_interface, 2, 0); + res = wl_resource_create(client, &wl_display_interface, 2, 0); assert(res); destroyed = 0; notify_called = 0; @@ -144,8 +127,6 @@ TEST(destroy_res_tst) wl_client_destroy(client); assert(destroyed); assert(notify_called); - assert(destroy_listener.link.prev == NULL); - assert(destroy_listener.link.next == NULL); wl_display_destroy(display); close(s[1]); @@ -165,13 +146,13 @@ TEST(create_resource_with_same_id) client = wl_client_create(display, s[0]); assert(client); - res = wl_resource_create(client, &wl_seat_interface, 2, 0); + res = wl_resource_create(client, &wl_display_interface, 2, 0); assert(res); id = wl_resource_get_id(res); assert(wl_client_get_object(client, id) == res); /* this one should replace the old one */ - res2 = wl_resource_create(client, &wl_seat_interface, 1, id); + res2 = wl_resource_create(client, &wl_display_interface, 1, id); assert(res2 != NULL); assert(wl_client_get_object(client, id) == res2); @@ -182,84 +163,3 @@ TEST(create_resource_with_same_id) wl_display_destroy(display); close(s[1]); } - -static void -display_destroy_notify(struct wl_listener *l, void *data) -{ - l->link.prev = l->link.next = NULL; -} - -TEST(free_without_remove) -{ - struct wl_display *display; - struct wl_listener a, b; - - display = wl_display_create(); - a.notify = display_destroy_notify; - b.notify = display_destroy_notify; - - wl_display_add_destroy_listener(display, &a); - wl_display_add_destroy_listener(display, &b); - - wl_display_destroy(display); - - assert(a.link.next == a.link.prev && a.link.next == NULL); - assert(b.link.next == b.link.prev && b.link.next == NULL); -} - -static enum wl_iterator_result -client_resource_check(struct wl_resource* resource, void* data) -{ - /* Ensure there is no iteration over already freed resources. */ - assert(!wl_resource_get_user_data(resource)); - return WL_ITERATOR_CONTINUE; -} - -static void -resource_destroy_notify(struct wl_listener *l, void *data) -{ - struct wl_resource* resource = data; - struct wl_client* client = resource->client; - - wl_client_for_each_resource(client, client_resource_check, NULL); - - /* Set user data to flag the resource has been deleted. The resource should - * not be accessible from this point forward. */ - wl_resource_set_user_data(resource, client); -} - -TEST(resource_destroy_iteration) -{ - struct wl_display *display; - struct wl_client *client; - struct wl_resource *resource1; - struct wl_resource *resource2; - int s[2]; - - struct wl_listener destroy_listener1 = { - .notify = &resource_destroy_notify - }; - struct wl_listener destroy_listener2 = { - .notify = &resource_destroy_notify - }; - - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); - display = wl_display_create(); - assert(display); - client = wl_client_create(display, s[0]); - assert(client); - resource1 = wl_resource_create(client, &wl_callback_interface, 1, 0); - resource2 = wl_resource_create(client, &wl_callback_interface, 1, 0); - assert(resource1); - assert(resource2); - - wl_resource_add_destroy_listener(resource1, &destroy_listener1); - wl_resource_add_destroy_listener(resource2, &destroy_listener2); - - wl_client_destroy(client); - - close(s[0]); - close(s[1]); - - wl_display_destroy(display); -} diff --git a/tests/sanity-test.c b/tests/sanity-test.c index e614cfb3..46f4f85f 100644 --- a/tests/sanity-test.c +++ b/tests/sanity-test.c @@ -1,43 +1,35 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 #include -#include #include -#include #include #include #include "test-runner.h" #include "wayland-util.h" -#include "wayland-private.h" -#include "test-compositor.h" - -extern int fd_leak_check_enabled; +extern int leak_check_enabled; TEST(empty) { @@ -55,16 +47,9 @@ FAIL_TEST(exit_failure) FAIL_TEST(fail_abort) { - test_disable_coredumps(); abort(); } -FAIL_TEST(fail_wl_abort) -{ - test_disable_coredumps(); - wl_abort("Abort the program\n"); -} - FAIL_TEST(fail_kill) { kill(getpid(), SIGTERM); @@ -72,30 +57,50 @@ FAIL_TEST(fail_kill) FAIL_TEST(fail_segv) { - char * volatile *null = 0; - - test_disable_coredumps(); - *null = "Goodbye, world"; + * (char **) 0 = "Goodbye, world"; } FAIL_TEST(sanity_assert) { - test_disable_coredumps(); /* must fail */ assert(0); } +FAIL_TEST(sanity_malloc_direct) +{ + void *p; + + assert(leak_check_enabled); + + p = malloc(10); /* memory leak */ + assert(p); /* assert that we got memory, also prevents + * the malloc from getting optimized away. */ + free(NULL); /* NULL must not be counted */ +} + +FAIL_TEST(sanity_malloc_indirect) +{ + struct wl_array array; + + assert(leak_check_enabled); + + wl_array_init(&array); + + /* call into library that calls malloc */ + wl_array_add(&array, 14); + + /* not freeing array, must leak */ +} + FAIL_TEST(sanity_fd_leak) { int fd[2]; - assert(fd_leak_check_enabled); + assert(leak_check_enabled); /* leak 2 file descriptors */ if (pipe(fd) < 0) exit(EXIT_SUCCESS); /* failed to fail */ - - test_disable_coredumps(); } FAIL_TEST(sanity_fd_leak_exec) @@ -107,7 +112,6 @@ FAIL_TEST(sanity_fd_leak_exec) if (pipe(fd) < 0) exit(EXIT_SUCCESS); /* failed to fail */ - test_disable_coredumps(); exec_fd_leak_check(nr_fds); } @@ -121,191 +125,3 @@ TEST(sanity_fd_exec) exec_fd_leak_check(nr_fds + 2); } - -static void -sanity_fd_no_leak(void) -{ - int fd[2]; - - assert(fd_leak_check_enabled); - - /* leak 2 file descriptors */ - if (pipe(fd) < 0) - exit(EXIT_SUCCESS); /* failed to fail */ - - close(fd[0]); - close(fd[1]); -} - -static void -sanity_client_no_leak(void) -{ - struct wl_display *display = wl_display_connect(NULL); - assert(display); - - wl_display_disconnect(display); -} - -TEST(tc_client_no_fd_leaks) -{ - struct display *d = display_create(); - - /* Client which does not consume the WAYLAND_DISPLAY socket. */ - client_create_noarg(d, sanity_fd_no_leak); - display_run(d); - - /* Client which does consume the WAYLAND_DISPLAY socket. */ - client_create_noarg(d, sanity_client_no_leak); - display_run(d); - - display_destroy(d); -} - -FAIL_TEST(tc_client_fd_leaks) -{ - struct display *d = display_create(); - - client_create_noarg(d, sanity_fd_leak); - display_run(d); - - test_disable_coredumps(); - display_destroy(d); -} - -FAIL_TEST(tc_client_fd_leaks_exec) -{ - struct display *d = display_create(); - - client_create_noarg(d, sanity_fd_leak_exec); - display_run(d); - - test_disable_coredumps(); - display_destroy(d); -} - -static char * -map_file(int fd, size_t *len) -{ - char *data; - - *len = lseek(fd, 0, SEEK_END); - data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0); - assert(data != MAP_FAILED && "Failed to mmap file"); - - return data; -} - -static void -sanity_client_log(void) -{ - char *log; - size_t log_len; - char *wayland_socket = strdup(getenv("WAYLAND_SOCKET")); - char *xdg_runtime_dir = strdup(getenv("XDG_RUNTIME_DIR")); - - unsetenv("WAYLAND_SOCKET"); - unsetenv("XDG_RUNTIME_DIR"); - - /* Try to connect to the default wayland display, which should fail since - * we have neither WAYLAND_SOCKET nor XDG_RUNTIME_DIR. */ - assert(!wl_display_connect(NULL)); - - /* Check that the client log contains some mention of XDG_RUNTIME_DIR. */ - log = map_file(client_log_fd, &log_len); - assert(strstr(log, "XDG_RUNTIME_DIR")); - munmap(log, log_len); - - /* Reset the environment variables we unset for the test. The test harness - * leak checker cares about the value of WAYLAND_SOCKET during teardown for - * correct fd accounting. */ - setenv("XDG_RUNTIME_DIR", xdg_runtime_dir, 0); - setenv("WAYLAND_SOCKET", wayland_socket, 0); - free(xdg_runtime_dir); - free(wayland_socket); -} - -TEST(tc_client_log) -{ - struct display *d = display_create(); - struct client_info *ci; - char *log; - size_t log_len; - - ci = client_create_noarg(d, sanity_client_log); - display_run(d); - - /* Check that the client log contains some mention of XDG_RUNTIME_DIR. */ - log = map_file(ci->log_fd, &log_len); - assert(strstr(log, "XDG_RUNTIME_DIR")); - munmap(log, log_len); - - display_destroy(d); -} - -FAIL_TEST(timeout_tst) -{ - test_set_timeout(1); - test_disable_coredumps(); - /* test should reach timeout */ - test_sleep(2); -} - -TEST(timeout2_tst) -{ - /* the test should end before reaching timeout, - * thus it should pass */ - test_set_timeout(1); - /* 200 000 microsec = 0.2 sec */ - test_usleep(200000); -} - -FAIL_TEST(timeout_reset_tst) -{ - test_set_timeout(5); - test_set_timeout(10); - test_set_timeout(1); - - test_disable_coredumps(); - /* test should fail on timeout */ - test_sleep(2); -} - -TEST(timeout_turnoff) -{ - test_set_timeout(1); - test_set_timeout(0); - - test_usleep(2); -} - -/* test timeouts with test-compositor */ -FAIL_TEST(tc_timeout_tst) -{ - struct display *d = display_create(); - client_create_noarg(d, timeout_tst); - display_run(d); - test_disable_coredumps(); - display_destroy(d); -} - -FAIL_TEST(tc_timeout2_tst) -{ - struct display *d = display_create(); - client_create_noarg(d, timeout_reset_tst); - display_run(d); - test_disable_coredumps(); - display_destroy(d); -} - -TEST(tc_timeout3_tst) -{ - struct display *d = display_create(); - - client_create_noarg(d, timeout2_tst); - display_run(d); - - client_create_noarg(d, timeout_turnoff); - display_run(d); - - display_destroy(d); -} diff --git a/tests/scanner-test-gen.sh b/tests/scanner-test-gen.sh deleted file mode 100755 index b9c9294d..00000000 --- a/tests/scanner-test-gen.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -eu - -generate() { - "$WAYLAND_SCANNER" $1 < "$TEST_DATA_DIR/$2" > "$TEST_DATA_DIR/$3" - "$SED" -i -e 's/Generated by wayland-scanner [0-9.]*/SCANNER TEST/' \ - "$TEST_DATA_DIR/$3" -} - -generate "code" "example.xml" "example-code.c" -generate "client-header" "example.xml" "example-client.h" -generate "server-header" "example.xml" "example-server.h" -generate "enum-header" "example.xml" "example-enum.h" - -generate "code" "small.xml" "small-code.c" -generate "client-header" "small.xml" "small-client.h" -generate "server-header" "small.xml" "small-server.h" - -generate "-c code" "small.xml" "small-code-core.c" -generate "-c client-header" "small.xml" "small-client-core.h" -generate "-c server-header" "small.xml" "small-server-core.h" - -generate "private-code" "small.xml" "small-private-code.c" - -generate "code" "empty.xml" "empty-code.c" -generate "client-header" "empty.xml" "empty-client.h" -generate "server-header" "empty.xml" "empty-server.h" diff --git a/tests/scanner-test.sh b/tests/scanner-test.sh deleted file mode 100755 index d4cd19ba..00000000 --- a/tests/scanner-test.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh - -echo "srcdir: $srcdir" -echo "scanner: $WAYLAND_SCANNER" -echo "test_data_dir: $TEST_DATA_DIR" -echo "test_output_dir: $TEST_OUTPUT_DIR" -echo "pwd: $PWD" -echo "sed: $SED" - -RETCODE=0 - -hard_fail() { - echo "$@" "ERROR" - exit 99 -} - -fail() { - echo "$@" "FAIL" - RETCODE=1 -} - -mkdir -p "$TEST_OUTPUT_DIR" || hard_fail "setup" - -generate_and_compare() { - echo - echo "Testing $1 generation: $2 -> $3" - - "$WAYLAND_SCANNER" $1 < "$TEST_DATA_DIR/$2" > "$TEST_OUTPUT_DIR/$3" || \ - hard_fail "$2 -> $3" - - "$SED" -i -e 's/Generated by wayland-scanner [0-9.]*/SCANNER TEST/' \ - "$TEST_OUTPUT_DIR/$3" || hard_fail "$2 -> $3" - - diff -q "$TEST_DATA_DIR/$3" "$TEST_OUTPUT_DIR/$3" && \ - echo "$2 -> $3 PASS" || \ - fail "$2 -> $3" -} - -verify_error() { - echo - echo "Checking that reading $1 gives an error on line $3" - - [ -f "$TEST_DATA_DIR/$1" ] || hard_fail "$1 not present" - - # Confirm failure error code - "$WAYLAND_SCANNER" server-header < "$TEST_DATA_DIR/$1" >/dev/null 2>"$TEST_OUTPUT_DIR/$2" && \ - fail "$1 return code check" - - # Verify that an error is produced at the correct line - grep -q ":$3: error:" "$TEST_OUTPUT_DIR/$2" && echo "$1 PASS" || fail "$1 line number check" -} - -generate_and_compare "code" "example.xml" "example-code.c" -generate_and_compare "client-header" "example.xml" "example-client.h" -generate_and_compare "server-header" "example.xml" "example-server.h" -generate_and_compare "enum-header" "example.xml" "example-enum.h" - -generate_and_compare "code" "small.xml" "small-code.c" -generate_and_compare "client-header" "small.xml" "small-client.h" -generate_and_compare "server-header" "small.xml" "small-server.h" - -generate_and_compare "-c code" "small.xml" "small-code-core.c" -generate_and_compare "-c client-header" "small.xml" "small-client-core.h" -generate_and_compare "-c server-header" "small.xml" "small-server-core.h" - -# The existing "code" must produce result identical to "public-code" -generate_and_compare "code" "small.xml" "small-code.c" -generate_and_compare "public-code" "small.xml" "small-code.c" -generate_and_compare "private-code" "small.xml" "small-private-code.c" - -generate_and_compare "code" "empty.xml" "empty-code.c" -generate_and_compare "client-header" "empty.xml" "empty-client.h" -generate_and_compare "server-header" "empty.xml" "empty-server.h" - -verify_error "bad-identifier-arg.xml" "bad-identifier-arg.log" 7 -verify_error "bad-identifier-entry.xml" "bad-identifier-entry.log" 8 -verify_error "bad-identifier-enum.xml" "bad-identifier-enum.log" 6 -verify_error "bad-identifier-event.xml" "bad-identifier-event.log" 6 -verify_error "bad-identifier-interface.xml" "bad-identifier-interface.log" 3 -verify_error "bad-identifier-protocol.xml" "bad-identifier-protocol.log" 2 -verify_error "bad-identifier-request.xml" "bad-identifier-request.log" 6 - -exit $RETCODE diff --git a/tests/signal-test.c b/tests/signal-test.c index f7e1bd6f..db83abc2 100644 --- a/tests/signal-test.c +++ b/tests/signal-test.c @@ -1,26 +1,23 @@ /* * Copyright © 2013 Marek Chalupa * - * 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: + * 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 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. + * 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 @@ -115,44 +112,3 @@ TEST(signal_emit_to_more_listeners) assert(3 * counter == count); } - -struct signal_emit_mutable_data { - int count; - struct wl_listener *remove_listener; -}; - -static void -signal_notify_mutable(struct wl_listener *listener, void *data) -{ - struct signal_emit_mutable_data *test_data = data; - test_data->count++; -} - -static void -signal_notify_and_remove_mutable(struct wl_listener *listener, void *data) -{ - struct signal_emit_mutable_data *test_data = data; - signal_notify_mutable(listener, test_data); - wl_list_remove(&test_data->remove_listener->link); -} - -TEST(signal_emit_mutable) -{ - struct signal_emit_mutable_data data = {0}; - - /* l2 will remove l3 before l3 is notified */ - struct wl_signal signal; - struct wl_listener l1 = {.notify = signal_notify_mutable}; - struct wl_listener l2 = {.notify = signal_notify_and_remove_mutable}; - struct wl_listener l3 = {.notify = signal_notify_mutable}; - - wl_signal_init(&signal); - wl_signal_add(&signal, &l1); - wl_signal_add(&signal, &l2); - wl_signal_add(&signal, &l3); - - data.remove_listener = &l3; - wl_signal_emit_mutable(&signal, &data); - - assert(data.count == 2); -} diff --git a/tests/socket-test.c b/tests/socket-test.c index 78743dc3..4a2272c5 100644 --- a/tests/socket-test.c +++ b/tests/socket-test.c @@ -1,24 +1,21 @@ /* - * 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: + * 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 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. + * 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 @@ -26,23 +23,18 @@ #include #include #include -#include -#include -#include #include #include #include "wayland-client.h" -#include "wayland-os.h" #include "wayland-server.h" #include "test-runner.h" /* Paths longer than what the .sun_path array can contain must be rejected. - * This is a hard limitation of assigning a name to AF_UNIX/AF_LOCAL sockets. - * See `man 7 unix`. - */ + This is a hard limitation of assigning a name to AF_UNIX/AF_LOCAL sockets. + See `man 7 unix`. */ -static struct sockaddr_un example_sockaddr_un; +static const struct sockaddr_un example_sockaddr_un; #define TOO_LONG (1 + sizeof example_sockaddr_un.sun_path) @@ -51,7 +43,8 @@ static const char * require_xdg_runtime_dir(void) { char *val = getenv("XDG_RUNTIME_DIR"); - assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test"); + if (!val) + assert(0 && "set $XDG_RUNTIME_DIR to run this test"); return val; } @@ -69,11 +62,6 @@ TEST(socket_path_overflow_client_connect) d = wl_display_connect(path); assert(d == NULL); assert(errno == ENAMETOOLONG); - - /* This is useless, but prevents a warning about example_sockaddr_un - * being discarded from the compilation unit. */ - strcpy(example_sockaddr_un.sun_path, "happy now clang?"); - assert(example_sockaddr_un.sun_path[0] != '\0'); } TEST(socket_path_overflow_server_create) @@ -115,11 +103,11 @@ TEST(add_existing_socket) ret = wl_display_add_socket(d, name); assert(ret == 0); - /* this one should fail */ + /* this on should fail */ ret = wl_display_add_socket(d, name); assert(ret < 0); - /* the original socket should still exist. + /* the original socket should still exists, * this was a bug introduced in e2c0d47b0c77f18cd90e9c6eabb358c4d89681c8 */ len = snprintf(path, sizeof example_sockaddr_un.sun_path, "%s/%s", xdg_runtime_dir, name); @@ -128,7 +116,7 @@ TEST(add_existing_socket) assert(access(path, F_OK) != -1); - /* the original socket should still exist */ + /* still should exists the original socket */ ret = wl_display_add_socket(d, name); assert(ret < 0); @@ -137,9 +125,7 @@ TEST(add_existing_socket) TEST(add_socket_auto) { - /* the number of auto sockets is currently 32, - * set in wayland-server.c. - */ + /* the number of auto sockets is currently 32 */ const int MAX_SOCKETS = 32; char path[sizeof example_sockaddr_un.sun_path]; @@ -163,7 +149,7 @@ TEST(add_socket_auto) assert(len < sizeof example_sockaddr_un.sun_path && "Bug in test. Path too long"); - /* was the socket created correctly? */ + /* was the socket? */ assert(access(path, F_OK) != -1); /* is the name sequential? */ @@ -182,108 +168,3 @@ TEST(add_socket_auto) wl_display_destroy(d); } - -struct client_create_listener { - struct wl_listener listener; - struct wl_display *display; -}; - -struct client_destroy_listener { - struct wl_listener listener; - struct wl_display *display; -}; - -static void -client_destroy_notify(struct wl_listener *l, void *data) -{ - struct client_destroy_listener *listener = - wl_container_of(l, listener, listener); - wl_display_terminate(listener->display); - free(listener); -} - -static void -client_create_notify(struct wl_listener *l, void *data) -{ - struct wl_client *client = data; - struct client_create_listener *listener = - wl_container_of(l, listener, listener); - struct client_destroy_listener *destroy_listener = (struct client_destroy_listener *)malloc(sizeof *destroy_listener); - assert(destroy_listener != NULL); - destroy_listener->display = listener->display; - destroy_listener->listener.notify = client_destroy_notify; - wl_client_add_destroy_listener(client, &destroy_listener->listener); -} - -TEST(absolute_socket_path) -{ - struct wl_display *display; - struct client_create_listener client_create_listener; - struct sockaddr_un addr; - int fd; - socklen_t size; - const char *xdg_runtime_dir; - size_t len; - int ret; - pid_t pid; - - /* It's a little weird that this test about absolute socket paths - * uses XDG_RUNTIME_DIR, but that's the only location guaranteed - * by test-runner to be both writable and unique. This isn't - * really a problem; we'll just take care that the leaf-level - * filename used for the socket isn't anything that would - * accidentally be generated by a default usage of wl_display_connect(). */ - xdg_runtime_dir = require_xdg_runtime_dir(); - memset(&addr, 0, sizeof addr); - len = snprintf(addr.sun_path, sizeof addr.sun_path, - "%s/%s", xdg_runtime_dir, "wayland-absolute-0"); - assert(len < sizeof addr.sun_path - && "Bug in test. Path too long"); - - /* The path must not exist prior to binding. */ - assert(access(addr.sun_path, F_OK) == -1); - - size = offsetof (struct sockaddr_un, sun_path) + strlen(addr.sun_path); - addr.sun_family = AF_LOCAL; - fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0); - assert(fd >= 0 ); - ret = bind(fd, (struct sockaddr *) &addr, size); - assert(ret >= 0); - ret = listen(fd, 128); - assert(ret >= 0); - - /* Start server display. Be careful (by avoiding wl_display_add_socket_auto() - * to offer only the absolutely qualified socket made above. */ - display = wl_display_create(); - assert(display != NULL); - client_create_listener.listener.notify = client_create_notify; - client_create_listener.display = display; - wl_display_add_client_created_listener(display, &client_create_listener.listener); - ret = wl_display_add_socket_fd(display, fd); - assert(ret == 0); - - /* Execute client that connects to the absolutely qualified server socket path. */ - pid = fork(); - assert(pid != -1); - - if (pid == 0) { - ret = setenv("WAYLAND_DISPLAY", addr.sun_path, 1); - assert(ret == 0); - struct wl_display *client_display = wl_display_connect(NULL); - assert(client_display != NULL); - ret = wl_display_roundtrip(client_display); - assert(ret != -1); - wl_display_disconnect(client_display); - exit(0); - assert(false); - } - - wl_display_run(display); - ret = waitpid(pid, NULL, 0); - assert(ret == pid); - - wl_display_destroy(display); - - ret = unlink(addr.sun_path); - assert(ret == 0); -} diff --git a/tests/test-compositor.c b/tests/test-compositor.c index c45d3f17..3248e2d5 100644 --- a/tests/test-compositor.c +++ b/tests/test-compositor.c @@ -1,26 +1,23 @@ /* * Copyright (c) 2014 Red Hat, Inc. * - * 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: + * 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 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. + * 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 @@ -28,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -37,18 +33,14 @@ #define WL_HIDE_DEPRECATED -#include "test-runner.h" #include "test-compositor.h" -int client_log_fd = -1; - /* --- Protocol --- */ struct test_compositor; static const struct wl_message tc_requests[] = { /* this request serves as a barrier for synchronizing*/ - { "stop_display", "u", NULL }, - { "noop", "", NULL }, + { "stop_display", "u", NULL } }; static const struct wl_message tc_events[] = { @@ -57,7 +49,7 @@ static const struct wl_message tc_events[] = { const struct wl_interface test_compositor_interface = { "test", 1, - 2, tc_requests, + 1, tc_requests, 1, tc_events }; @@ -65,8 +57,6 @@ struct test_compositor_interface { void (*stop_display)(struct wl_client *client, struct wl_resource *resource, uint32_t num); - void (*noop)(struct wl_client *client, - struct wl_resource *resource); }; struct test_compositor_listener { @@ -75,15 +65,14 @@ struct test_compositor_listener { }; enum { - STOP_DISPLAY = 0, - TEST_NOOP = 1 + STOP_DISPLAY = 0 }; enum { DISPLAY_RESUMED = 0 }; -/* Since tests can run parallelly, we need unique socket names +/* Since tests can run parallely, we need unique socket names * for each test, otherwise the test can fail on wl_display_add_socket. */ static const char * get_socket_name(void) @@ -92,34 +81,41 @@ get_socket_name(void) static char retval[64]; gettimeofday(&tv, NULL); - snprintf(retval, sizeof retval, "wayland-test-%d-%lld%lld", - (int) getpid(), (long long int) tv.tv_sec, (long long int) tv.tv_usec); + snprintf(retval, sizeof retval, "wayland-test-%d-%ld%ld", + getpid(), tv.tv_sec, tv.tv_usec); return retval; } +/** + * Check client's state and terminate display when all clients exited + */ static void -handle_client_destroy(void *data) +client_destroyed(struct wl_listener *listener, void *data) { - struct client_info *ci = data; struct display *d; - int status; + struct client_info *ci; + siginfo_t status; + ci = wl_container_of(listener, ci, destroy_listener); d = ci->display; - assert(waitpid(ci->pid, &status, 0) != -1); + assert(waitid(P_PID, ci->pid, &status, WEXITED) != -1); - if (WIFSIGNALED(status)) { + switch (status.si_code) { + case CLD_KILLED: + case CLD_DUMPED: fprintf(stderr, "Client '%s' was killed by signal %d\n", - ci->name, WTERMSIG(status)); - ci->kill_code = WTERMSIG(status); - - } else if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != EXIT_SUCCESS) + ci->name, status.si_status); + ci->exit_code = status.si_status; + break; + case CLD_EXITED: + if (status.si_status != EXIT_SUCCESS) fprintf(stderr, "Client '%s' exited with code %d\n", - ci->name, WEXITSTATUS(status)); + ci->name, status.si_status); - ci->exit_code = WEXITSTATUS(status); + ci->exit_code = status.si_status; + break; } ++d->clients_terminated_no; @@ -132,46 +128,13 @@ handle_client_destroy(void *data) * clients. In the case that the test would go through * the clients list manually, zero out the wl_client as a sign * that the client is not running anymore */ -} - -/** - * Check client's state and terminate display when all clients exited - */ -static void -client_destroyed(struct wl_listener *listener, void *data) -{ - struct client_info *ci; - struct display *d; - struct wl_event_loop *loop; - - /* Wait for client in an idle handler to avoid blocking the actual - * client destruction (fd close etc. */ - ci = wl_container_of(listener, ci, destroy_listener); - d = ci->display; - loop = wl_display_get_event_loop(d->wl_display); - wl_event_loop_add_idle(loop, handle_client_destroy, ci); - ci->wl_client = NULL; } static void -client_log_handler(const char *fmt, va_list arg) -{ - va_list arg_copy; - - va_copy(arg_copy, arg); - vdprintf(client_log_fd, fmt, arg_copy); - va_end(arg_copy); - - vfprintf(stderr, fmt, arg); -} - -static void -run_client(void (*client_main)(void *data), void *data, - int wayland_sock, int client_pipe, int log_fd) +run_client(void (*client_main)(void), int wayland_sock, int client_pipe) { char s[8]; - int cur_fds; int can_continue = 0; /* Wait until display signals that client can continue */ @@ -184,41 +147,12 @@ run_client(void (*client_main)(void *data), void *data, snprintf(s, sizeof s, "%d", wayland_sock); setenv("WAYLAND_SOCKET", s, 0); - /* Capture the log to the specified file descriptor. */ - client_log_fd = log_fd; - wl_log_set_handler_client(client_log_handler); - - cur_fds = count_open_fds(); - - client_main(data); - - /* Clients using wl_display_connect() will end up closing the socket - * passed in through the WAYLAND_SOCKET environment variable. When - * doing this, it clears the environment variable, so if it's been - * unset, then we assume the client consumed the file descriptor and - * do not count it towards leak checking. */ - if (!getenv("WAYLAND_SOCKET")) - cur_fds--; - - check_fd_leaks(cur_fds); -} - -static int -create_log_fd(void) -{ - char logname[] = "/tmp/wayland-tests-log-XXXXXX"; - int log_fd = mkstemp(logname); - - if (log_fd >= 0) - unlink(logname); - - return log_fd; + client_main(); } static struct client_info * display_create_client(struct display *d, - void (*client_main)(void *data), - void *data, + void (*client_main)(void), const char *name) { int pipe_cli[2]; @@ -226,15 +160,11 @@ display_create_client(struct display *d, pid_t pid; int can_continue = 0; struct client_info *cl; - int log_fd; assert(pipe(pipe_cli) == 0 && "Failed creating pipe"); assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_wayl) == 0 && "Failed creating socket pair"); - log_fd = create_log_fd(); - assert(log_fd >= 0 && "Failed to create log fd"); - pid = fork(); assert(pid != -1 && "Fork failed"); @@ -242,11 +172,10 @@ display_create_client(struct display *d, close(sock_wayl[1]); close(pipe_cli[1]); - run_client(client_main, data, sock_wayl[0], pipe_cli[0], log_fd); + run_client(client_main, sock_wayl[0], pipe_cli[0]); close(sock_wayl[0]); close(pipe_cli[0]); - close(log_fd); exit(0); } @@ -263,7 +192,6 @@ display_create_client(struct display *d, cl->name = name; cl->pid = pid; cl->pipe = pipe_cli[1]; - cl->log_fd = log_fd; cl->destroy_listener.notify = &client_destroyed; cl->wl_client = wl_client_create(d->wl_display, sock_wayl[1]); @@ -285,14 +213,11 @@ display_create_client(struct display *d, } struct client_info * -client_create_with_name(struct display *d, - void (*client_main)(void *data), void *data, +client_create_with_name(struct display *d, void (*client_main)(void), const char *name) { int can_continue = 1; - struct client_info *cl = display_create_client(d, - client_main, data, - name); + struct client_info *cl = display_create_client(d, client_main, name); /* let the show begin! */ assert(write(cl->pipe, &can_continue, sizeof(int)) == sizeof(int)); @@ -331,16 +256,8 @@ handle_stop_display(struct wl_client *client, wl_display_terminate(d->wl_display); } -static void -handle_noop(struct wl_client *client, struct wl_resource *resource) -{ - (void)client; - (void)resource; -} - static const struct test_compositor_interface tc_implementation = { - handle_stop_display, - handle_noop, + handle_stop_display }; static void @@ -362,6 +279,7 @@ struct display * display_create(void) { struct display *d = NULL; + struct wl_global *g; const char *socket_name; int stat = 0; @@ -382,10 +300,9 @@ display_create(void) wl_list_init(&d->waiting_for_resume); d->wfr_num = 0; - d->test_global = wl_global_create(d->wl_display, - &test_compositor_interface, - 1, d, tc_bind); - assert(d->test_global && "Creating test global failed"); + g = wl_global_create(d->wl_display, &test_compositor_interface, + 1, d, tc_bind); + assert(g && "Creating test global failed"); return d; } @@ -399,7 +316,7 @@ display_run(struct display *d) } void -display_post_resume_events(struct display *d) +display_resume(struct display *d) { struct wfr *wfr, *next; @@ -413,19 +330,12 @@ display_post_resume_events(struct display *d) assert(wl_list_empty(&d->waiting_for_resume)); d->wfr_num = 0; -} -void -display_resume(struct display *d) -{ - display_post_resume_events(d); wl_display_run(d->wl_display); } -/* If signum is 0, expect a successful client exit, otherwise - * expect the client to have been killed by that signal. */ void -display_destroy_expect_signal(struct display *d, int signum) +display_destroy(struct display *d) { struct client_info *cl, *next; int failed = 0; @@ -436,25 +346,15 @@ display_destroy_expect_signal(struct display *d, int signum) wl_list_for_each_safe(cl, next, &d->clients, link) { assert(cl->wl_client == NULL); - if (signum != 0 && cl->kill_code != signum) { - ++failed; - fprintf(stderr, - "Client '%s' failed, expecting signal %d, " - "got %d\n", - cl->name, signum, cl->kill_code); - } - else if (signum == 0 && - (cl->kill_code != 0 || cl->exit_code != 0)) { + if (cl->exit_code != 0) { ++failed; fprintf(stderr, "Client '%s' failed\n", cl->name); } close(cl->pipe); - close(cl->log_fd); free(cl); } - wl_global_destroy(d->test_global); wl_display_destroy(d->wl_display); free(d); @@ -464,12 +364,6 @@ display_destroy_expect_signal(struct display *d, int signum) } } -void -display_destroy(struct display *d) -{ - display_destroy_expect_signal(d, 0); -} - /* * --- Client helper functions --- */ @@ -491,15 +385,14 @@ registry_handle_globals(void *data, struct wl_registry *registry, { struct client *c = data; - if (strcmp(intf, "test") == 0) { - c->tc = wl_registry_bind(registry, id, &test_compositor_interface, ver); - assert(c->tc && "Failed binding to registry"); + if (strcmp(intf, "test") != 0) + return; - wl_proxy_add_listener((struct wl_proxy *) c->tc, - (void *) &tc_listener, c); - } else if (strcmp(intf, wl_fixes_interface.name) == 0) { - c->wl_fixes = wl_registry_bind(registry, id, &wl_fixes_interface, 2); - } + c->tc = wl_registry_bind(registry, id, &test_compositor_interface, ver); + assert(c->tc && "Failed binding to registry"); + + wl_proxy_add_listener((struct wl_proxy *) c->tc, + (void *) &tc_listener, c); } static const struct wl_registry_listener registry_listener = @@ -508,7 +401,7 @@ static const struct wl_registry_listener registry_listener = NULL }; -struct client *client_connect(void) +struct client *client_connect() { struct wl_registry *reg; struct client *c = calloc(1, sizeof *c); @@ -518,16 +411,13 @@ struct client *client_connect(void) assert(c->wl_display && "Failed connecting to display"); /* create test_compositor proxy. Do it with temporary - * registry so that client can define its own listener later */ + * registry so that client can define it's own listener later */ reg = wl_display_get_registry(c->wl_display); assert(reg); wl_registry_add_listener(reg, ®istry_listener, c); wl_display_roundtrip(c->wl_display); assert(c->tc); - if (c->wl_fixes) { - wl_fixes_destroy_registry(c->wl_fixes, reg); - } wl_registry_destroy(reg); return c; @@ -560,17 +450,12 @@ client_disconnect(struct client *c) /* check for errors */ check_error(c->wl_display); - if (c->wl_fixes) { - wl_fixes_destroy(c->wl_fixes); - } - wl_proxy_destroy((struct wl_proxy *) c->tc); wl_display_disconnect(c->wl_display); - free(c); } /* num is number of clients that requests to stop display. - * Display is stopped after it receives num STOP_DISPLAY requests */ + * Display is stopped after it recieve num STOP_DISPLAY requests */ int stop_display(struct client *c, int num) { @@ -585,9 +470,3 @@ stop_display(struct client *c, int num) return n; } - -void -noop_request(struct client *c) -{ - wl_proxy_marshal((struct wl_proxy *) c->tc, TEST_NOOP); -} diff --git a/tests/test-compositor.h b/tests/test-compositor.h index 4d94f3fb..c41b17b8 100644 --- a/tests/test-compositor.h +++ b/tests/test-compositor.h @@ -1,31 +1,26 @@ /* * Copyright (c) 2014 Red Hat, Inc. * - * 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: + * 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 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. + * 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 #include -#include #include "wayland-server.h" #include "wayland-client.h" @@ -40,16 +35,13 @@ struct client_info { int pipe; pid_t pid; int exit_code; - int kill_code; struct wl_list link; void *data; /* for arbitrary use */ - int log_fd; }; struct display { struct wl_display *wl_display; - struct wl_global *test_global; struct wl_list clients; uint32_t clients_no; @@ -66,16 +58,14 @@ struct display { * filled. */ struct client { struct wl_display *wl_display; - struct wl_fixes *wl_fixes; struct test_compositor *tc; - atomic_bool display_stopped; + int display_stopped; }; struct client *client_connect(void); void client_disconnect(struct client *); int stop_display(struct client *, int); -void noop_request(struct client *); /** * Usual workflow: @@ -85,51 +75,23 @@ void noop_request(struct client *); * wl_global_create(d->wl_display, ...); * ... other setups ... * - * client_create(d, client_main, data); - * client_create(d, client_main2, data); + * client_create(d, client_main); + * client_create(d, client_main2); * * display_run(d); * display_destroy(d); */ struct display *display_create(void); void display_destroy(struct display *d); -void display_destroy_expect_signal(struct display *d, int signum); void display_run(struct display *d); -/* This function posts the display_resumed event to all waiting clients, - * so that after flushing events the clients will stop waiting and continue. - * - * (Calling `display_run` after this function will resume the display loop.) - */ -void display_post_resume_events(struct display *d); /* After n clients called stop_display(..., n), the display * is stopped and can process the code after display_run(). - * - * This function posts the display_resumed event to the waiting - * clients, so that the clients will stop waiting and continue; - * it then reruns the display. */ + * This function rerun the display again and send display_resumed + * event to waiting clients, so the clients will stop waiting and continue */ void display_resume(struct display *d); -/* The file descriptor containing the client log. This is only valid in the - * test client processes. */ -extern int client_log_fd; - struct client_info *client_create_with_name(struct display *d, - void (*client_main)(void *data), - void *data, + void (*client_main)(void), const char *name); -#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c)) -static inline void noarg_cb(void *data) -{ - void (*cb)(void) = data; - cb(); -} -static inline struct client_info *client_create_with_name_noarg(struct display *d, - void (*client_main)(void), - const char *name) -{ - return client_create_with_name(d, noarg_cb, client_main, name); -} - -#define client_create_noarg(d, c) \ - client_create_with_name_noarg((d), (c), (#c)) +#define client_create(d, c) client_create_with_name((d), (c), (#c)) diff --git a/tests/test-helpers.c b/tests/test-helpers.c index 1af813bb..4761b09e 100644 --- a/tests/test-helpers.c +++ b/tests/test-helpers.c @@ -1,94 +1,33 @@ /* * Copyright © 2012 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: + * 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 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. + * 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 #include #include #include -#include #include -#include -#include -#include - -#ifdef HAVE_SYS_PRCTL_H -#include -#endif #include "test-runner.h" -#if defined(__FreeBSD__) -#include - -/* - * On FreeBSD, get file descriptor information using sysctl() since that does - * not depend on a mounted fdescfs (which provides /dev/fd/N for N > 2). - */ -int -count_open_fds(void) -{ - int error; - int nfds; - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_NFDS, 0 }; - size_t len; - - len = sizeof(nfds); - error = sysctl(mib, 4, &nfds, &len, NULL, 0); - assert(error == 0 && "sysctl KERN_PROC_NFDS failed."); - return nfds; -} -#elif defined(__OpenBSD__) -#include - -/* - * On OpenBSD, get file descriptor information using sysctl() - */ -int -count_open_fds(void) -{ - int error; - int mib[6]; - size_t size; - - mib[0] = CTL_KERN; - mib[1] = KERN_FILE; - mib[2] = KERN_FILE_BYPID; - mib[3] = getpid(); - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - /* find the size required to store all the entries */ - error = sysctl(mib, 6, NULL, &size, NULL, 0); - assert(error != -1 && "sysctl KERN_FILE_BYPID failed."); - - /* return the current number of entries */ - return size / sizeof(struct kinfo_file); -} -#else int count_open_fds(void) { @@ -96,12 +35,8 @@ count_open_fds(void) struct dirent *ent; int count = 0; - /* - * Using /dev/fd instead of /proc/self/fd should allow this code to - * work on non-Linux operating systems. - */ - dir = opendir("/dev/fd"); - assert(dir && "opening /dev/fd failed."); + dir = opendir("/proc/self/fd"); + assert(dir && "opening /proc/self/fd failed."); errno = 0; while ((ent = readdir(dir))) { @@ -110,82 +45,20 @@ count_open_fds(void) continue; count++; } - assert(errno == 0 && "reading /dev/fd failed."); + assert(errno == 0 && "reading /proc/self/fd failed."); closedir(dir); return count; } -#endif void exec_fd_leak_check(int nr_expected_fds) { - const char *exe = "exec-fd-leak-checker"; + const char *exe = "./exec-fd-leak-checker"; char number[16] = { 0 }; - const char *test_build_dir = getenv("TEST_BUILD_DIR"); - char exe_path[256] = { 0 }; - - if (test_build_dir == NULL || test_build_dir[0] == 0) { - test_build_dir = "."; - } - - snprintf(exe_path, sizeof exe_path - 1, "%s/%s", test_build_dir, exe); snprintf(number, sizeof number - 1, "%d", nr_expected_fds); - execl(exe_path, exe, number, (char *)NULL); + execl(exe, exe, number, (char *)NULL); assert(0 && "execing fd leak checker failed"); } - -#define USEC_TO_NSEC(n) (1000 * (n)) - -/* our implementation of usleep and sleep functions that are safe to use with - * timeouts (timeouts are implemented using alarm(), so it is not safe use - * usleep and sleep. See man pages of these functions) - */ -void -test_usleep(useconds_t usec) -{ - struct timespec ts = { - .tv_sec = 0, - .tv_nsec = USEC_TO_NSEC(usec) - }; - - assert(nanosleep(&ts, NULL) == 0); -} - -/* we must write the whole function instead of - * wrapping test_usleep, because useconds_t may not - * be able to contain such a big number of microseconds */ -void -test_sleep(unsigned int sec) -{ - struct timespec ts = { - .tv_sec = sec, - .tv_nsec = 0 - }; - - assert(nanosleep(&ts, NULL) == 0); -} - -/** Try to disable coredumps - * - * Useful for tests that crash on purpose, to avoid creating a core file - * or launching an application crash handler service or cluttering coredumpctl. - * - * NOTE: Calling this may make the process undebuggable. - */ -void -test_disable_coredumps(void) -{ - struct rlimit r; - - if (getrlimit(RLIMIT_CORE, &r) == 0) { - r.rlim_cur = 0; - setrlimit(RLIMIT_CORE, &r); - } - -#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) - prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); -#endif -} diff --git a/tests/test-runner.c b/tests/test-runner.c index 9a50d1dd..8f3d5d37 100644 --- a/tests/test-runner.c +++ b/tests/test-runner.c @@ -1,28 +1,24 @@ /* * Copyright © 2012 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: + * 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 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. + * 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" #define _GNU_SOURCE @@ -31,40 +27,56 @@ #include #include #include -#include #include #include #include #include -#include -#include -#include -#ifdef HAVE_SYS_PROCCTL_H -#include -#elif defined(HAVE_SYS_PRCTL_H) -#include -#ifndef PR_SET_PTRACER -# define PR_SET_PTRACER 0x59616d61 -#endif -#endif - #include "test-runner.h" -/* when set to 1, check if tests are not leaking opened files. - * It is turned on by default. It can be turned off by - * WAYLAND_TEST_NO_LEAK_CHECK environment variable. */ -int fd_leak_check_enabled; +static int num_alloc; +static void* (*sys_malloc)(size_t); +static void (*sys_free)(void*); +static void* (*sys_realloc)(void*, size_t); +static void* (*sys_calloc)(size_t, size_t); -/* when this var is set to 0, every call to test_set_timeout() is - * suppressed - handy when debugging the test. Can be set by - * WAYLAND_TEST_NO_TIMEOUTS environment variable. */ -static int timeouts_enabled = 1; - -/* set to one if the output goes to the terminal */ -static int is_atty = 0; +int leak_check_enabled; extern const struct test __start_test_section, __stop_test_section; +__attribute__ ((visibility("default"))) void * +malloc(size_t size) +{ + num_alloc++; + return sys_malloc(size); +} + +__attribute__ ((visibility("default"))) void +free(void* mem) +{ + if (mem != NULL) + num_alloc--; + sys_free(mem); +} + +__attribute__ ((visibility("default"))) void * +realloc(void* mem, size_t size) +{ + if (mem == NULL) + num_alloc++; + return sys_realloc(mem, size); +} + +__attribute__ ((visibility("default"))) void * +calloc(size_t nmemb, size_t size) +{ + if (sys_calloc == NULL) + return NULL; + + num_alloc++; + + return sys_calloc(nmemb, size); +} + static const struct test * find_test(const char *name) { @@ -95,245 +107,46 @@ usage(const char *name, int status) exit(status); } -void -test_set_timeout(unsigned int to) -{ - int re; - - if (!timeouts_enabled) { - fprintf(stderr, "Timeouts suppressed.\n"); - return; - } - - re = alarm(to); - fprintf(stderr, "Timeout was %sset", re ? "re-" : ""); - - if (to != 0) - fprintf(stderr, " to %d second%s from now.\n", - to, to > 1 ? "s" : ""); - else - fprintf(stderr, " off.\n"); -} - -static void -sigalrm_handler(int signum) -{ - fprintf(stderr, "Test timed out.\n"); - abort(); -} - -void -check_fd_leaks(int supposed_fds) -{ - int num_fds; - - if (fd_leak_check_enabled) { - num_fds = count_open_fds(); - if (supposed_fds != num_fds) { - fprintf(stderr, "fd leak detected in test. " - "Opened %d files, unclosed %d\n", num_fds, - num_fds - supposed_fds); - abort(); - } - } else { - fprintf(stderr, "FD leak checks disabled\n"); - } -} - static void run_test(const struct test *t) { - int cur_fds; - struct sigaction sa; + int cur_alloc = num_alloc; + int cur_fds, num_fds; - if (timeouts_enabled) { - sa.sa_handler = sigalrm_handler; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - assert(sigaction(SIGALRM, &sa, NULL) == 0); - } - - //cur_alloc = get_current_alloc_num(); cur_fds = count_open_fds(); - t->run(); - - /* turn off timeout (if any) after test completion */ - if (timeouts_enabled) - alarm(0); - - check_fd_leaks(cur_fds); - - exit(EXIT_SUCCESS); -} - -#ifndef PATH_MAX -#define PATH_MAX 256 -#endif - -static void -set_xdg_runtime_dir(void) -{ - char xdg_runtime_dir[PATH_MAX]; - const char *xrd_env; - - xrd_env = getenv("XDG_RUNTIME_DIR"); - /* if XDG_RUNTIME_DIR is not set in environ, fallback to /tmp */ - assert((snprintf(xdg_runtime_dir, PATH_MAX, "%s/wayland-tests-XXXXXX", - (xrd_env && xrd_env[0] == '/') ? xrd_env : "/tmp") < PATH_MAX) - && "test error: XDG_RUNTIME_DIR too long"); - - assert(mkdtemp(xdg_runtime_dir) && "test error: mkdtemp failed"); - if (mkdir(xdg_runtime_dir, 0700) == -1) - if (errno != EEXIST) { - perror("Creating XDG_RUNTIME_DIR"); + if (leak_check_enabled) { + if (cur_alloc != num_alloc) { + fprintf(stderr, "Memory leak detected in test. " + "Allocated %d blocks, unfreed %d\n", num_alloc, + num_alloc - cur_alloc); abort(); } - - if (setenv("XDG_RUNTIME_DIR", xdg_runtime_dir, 1) == -1) { - perror("Setting XDG_RUNTIME_DIR"); - abort(); - } -} - -static void -rmdir_xdg_runtime_dir(void) -{ - const char *xrd_env = getenv("XDG_RUNTIME_DIR"); - assert(xrd_env && xrd_env[0] == '/' && "No XDG_RUNTIME_DIR set"); - - /* rmdir may fail if some test didn't do clean up */ - if (rmdir(xrd_env) == -1) - perror("Cleaning XDG_RUNTIME_DIR"); -} - -#define RED "\033[31m" -#define GREEN "\033[32m" - -static void -stderr_set_color(const char *color) -{ - /* use colors only when the output is connected to - * the terminal */ - if (is_atty) - fprintf(stderr, "%s", color); -} - -static void -stderr_reset_color(void) -{ - if (is_atty) - fprintf(stderr, "\033[0m"); -} - -/* this function is taken from libinput/test/litest.c - * (rev 028513a0a723e97941c39) - * - * Returns: 1 if a debugger is confirmed present; 0 if no debugger is - * present or if it can't be determined. - */ -#if defined(HAVE_SYS_PROCCTL_H) && defined(PROC_TRACE_STATUS) -static int -is_debugger_attached(void) -{ - int rc; - int status; - rc = procctl(P_PID, getpid(), PROC_TRACE_STATUS, &status); - if (rc == -1) { - perror("procctl"); - return 0; - } - /* -1=tracing disabled, 0=no debugger attached, >0=pid of debugger. */ - return status > 0; -} -#elif defined(HAVE_SYS_PRCTL_H) -static int -is_debugger_attached(void) -{ - int status; - int rc; - pid_t pid; - int pipefd[2]; - - if (pipe(pipefd) == -1) { - perror("pipe"); - return 0; - } - - pid = fork(); - if (pid == -1) { - perror("fork"); - close(pipefd[0]); - close(pipefd[1]); - return 0; - } else if (pid == 0) { - char buf; - pid_t ppid = getppid(); - - /* Wait until parent is ready */ - close(pipefd[1]); /* Close unused write end */ - read(pipefd[0], &buf, 1); - close(pipefd[0]); - if (buf == '-') - _exit(1); - if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) != 0) - _exit(1); - if (!waitpid(-1, NULL, 0)) - _exit(1); - ptrace(PTRACE_CONT, NULL, NULL); - ptrace(PTRACE_DETACH, ppid, NULL, NULL); - _exit(0); - } else { - close(pipefd[0]); - - /* Enable child to ptrace the parent process */ - rc = prctl(PR_SET_PTRACER, pid); - if (rc != 0 && errno != EINVAL) { - /* An error prevents us from telling if a debugger is attached. - * Instead of propagating the error, assume no debugger present. - * But note the error to the log as a clue for troubleshooting. - * Then flag the error state to the client by sending '-'. - */ - perror("prctl"); - write(pipefd[1], "-", 1); - } else { - /* Signal to client that parent is ready by passing '+' */ - write(pipefd[1], "+", 1); + num_fds = count_open_fds(); + if (cur_fds != num_fds) { + fprintf(stderr, "fd leak detected in test. " + "Opened %d files, unclosed %d\n", num_fds, + num_fds - cur_fds); + abort(); } - close(pipefd[1]); - - waitpid(pid, &status, 0); - rc = WEXITSTATUS(status); } - - return rc; + exit(EXIT_SUCCESS); } -#else -static int -is_debugger_attached(void) -{ - /* 0=debugger can't be determined */ - return 0; -} -#endif int main(int argc, char *argv[]) { const struct test *t; pid_t pid; int total, pass; - int info; + siginfo_t info; - if (isatty(fileno(stderr))) - is_atty = 1; + /* Load system malloc, free, and realloc */ + sys_calloc = dlsym(RTLD_NEXT, "calloc"); + sys_realloc = dlsym(RTLD_NEXT, "realloc"); + sys_malloc = dlsym(RTLD_NEXT, "malloc"); + sys_free = dlsym(RTLD_NEXT, "free"); - if (is_debugger_attached()) { - fd_leak_check_enabled = 0; - timeouts_enabled = 0; - } else { - fd_leak_check_enabled = !getenv("WAYLAND_TEST_NO_LEAK_CHECK"); - timeouts_enabled = !getenv("WAYLAND_TEST_NO_TIMEOUTS"); - } + leak_check_enabled = !getenv("NO_ASSERT_LEAK_CHECK"); if (argc == 2 && strcmp(argv[1], "--help") == 0) usage(argv[0], EXIT_SUCCESS); @@ -345,16 +158,9 @@ int main(int argc, char *argv[]) usage(argv[0], EXIT_FAILURE); } - set_xdg_runtime_dir(); - /* run_test calls exit() */ - assert(atexit(rmdir_xdg_runtime_dir) == 0); - run_test(t); } - /* set our own XDG_RUNTIME_DIR */ - set_xdg_runtime_dir(); - pass = 0; for (t = &__start_test_section; t < &__stop_test_section; t++) { int success = 0; @@ -365,52 +171,37 @@ int main(int argc, char *argv[]) if (pid == 0) run_test(t); /* never returns */ - if (waitpid(pid, &info, 0) == -1) { - stderr_set_color(RED); - fprintf(stderr, "waitpid failed: %s\n", - strerror(errno)); - stderr_reset_color(); - + if (waitid(P_ALL, 0, &info, WEXITED)) { + fprintf(stderr, "waitid failed: %m\n"); abort(); } - if (WIFEXITED(info)) { - if (WEXITSTATUS(info) == EXIT_SUCCESS) - success = !t->must_fail; - else - success = t->must_fail; - - stderr_set_color(success ? GREEN : RED); - fprintf(stderr, "test \"%s\":\texit status %d", - t->name, WEXITSTATUS(info)); - - } else if (WIFSIGNALED(info)) { - if (t->must_fail) + fprintf(stderr, "test \"%s\":\t", t->name); + switch (info.si_code) { + case CLD_EXITED: + fprintf(stderr, "exit status %d", info.si_status); + if (info.si_status == EXIT_SUCCESS) success = 1; - - stderr_set_color(success ? GREEN : RED); - fprintf(stderr, "test \"%s\":\tsignal %d", - t->name, WTERMSIG(info)); + break; + case CLD_KILLED: + case CLD_DUMPED: + fprintf(stderr, "signal %d", info.si_status); + break; } + if (t->must_fail) + success = !success; + if (success) { pass++; fprintf(stderr, ", pass.\n"); } else fprintf(stderr, ", fail.\n"); - - stderr_reset_color(); - - /* print separator line */ - fprintf(stderr, "----------------------------------------\n"); } total = &__stop_test_section - &__start_test_section; fprintf(stderr, "%d tests, %d pass, %d fail\n", total, pass, total - pass); - /* cleaning */ - rmdir_xdg_runtime_dir(); - return pass == total ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test-runner.h b/tests/test-runner.h index d0734009..707504cc 100644 --- a/tests/test-runner.h +++ b/tests/test-runner.h @@ -1,27 +1,3 @@ -/* - * Copyright © 2012 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. - */ #ifndef _TEST_RUNNER_H_ #define _TEST_RUNNER_H_ @@ -29,32 +5,30 @@ #error "Tests must not be built with NDEBUG defined, they rely on assert()." #endif -#include - struct test { const char *name; void (*run)(void); int must_fail; } __attribute__ ((aligned (16))); -#define TEST(name) \ - static void name(void); \ - \ - const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ - #name, name, 0 \ - }; \ - \ +#define TEST(name) \ + static void name(void); \ + \ + const struct test test##name \ + __attribute__ ((section ("test_section"))) = { \ + #name, name, 0 \ + }; \ + \ static void name(void) -#define FAIL_TEST(name) \ - static void name(void); \ - \ - const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ - #name, name, 1 \ - }; \ - \ +#define FAIL_TEST(name) \ + static void name(void); \ + \ + const struct test test##name \ + __attribute__ ((section ("test_section"))) = { \ + #name, name, 1 \ + }; \ + \ static void name(void) int @@ -63,33 +37,4 @@ count_open_fds(void); void exec_fd_leak_check(int nr_expected_fds); /* never returns */ -void -check_fd_leaks(int supposed_fds); - -/* - * set/reset the timeout in seconds. The timeout starts - * at the point of invoking this function - */ -void -test_set_timeout(unsigned int); - -/* test-runner uses alarm() and SIGALRM, so we can not - * use usleep and sleep functions in tests (see 'man usleep' - * or 'man sleep', respectively). Following functions are safe - * to use in tests */ -void -test_usleep(useconds_t); - -void -test_sleep(unsigned int); - -void -test_disable_coredumps(void); - -#define DISABLE_LEAK_CHECKS \ - do { \ - extern int fd_leak_check_enabled; \ - fd_leak_check_enabled = 0; \ - } while (0); - #endif diff --git a/wayland-scanner.m4 b/wayland-scanner.m4 index 2b222e8b..4e4222ad 100644 --- a/wayland-scanner.m4 +++ b/wayland-scanner.m4 @@ -1,7 +1,7 @@ AC_DEFUN([WAYLAND_SCANNER_RULES], [ PKG_PROG_PKG_CONFIG - PKG_CHECK_MODULES([WAYLAND_SCANNER], [wayland-scanner >= 1.14.0]) + PKG_CHECK_MODULES([WAYLAND_SCANNER], [wayland-scanner]) wayland_scanner=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner` AC_SUBST([wayland_scanner]) diff --git a/wayland-scanner.mk b/wayland-scanner.mk index c174e6bd..0a72062b 100644 --- a/wayland-scanner.mk +++ b/wayland-scanner.mk @@ -1,8 +1,8 @@ %-protocol.c : $(wayland_protocoldir)/%.xml - $(AM_V_GEN)$(wayland_scanner) code $< $@ + $(AM_V_GEN)$(wayland_scanner) code < $< > $@ %-server-protocol.h : $(wayland_protocoldir)/%.xml - $(AM_V_GEN)$(wayland_scanner) server-header $< $@ + $(AM_V_GEN)$(wayland_scanner) server-header < $< > $@ %-client-protocol.h : $(wayland_protocoldir)/%.xml - $(AM_V_GEN)$(wayland_scanner) client-header $< $@ + $(AM_V_GEN)$(wayland_scanner) client-header < $< > $@