Initial commit
This commit is contained in:
commit
71617d4b14
|
@ -0,0 +1,9 @@
|
||||||
|
# Build files
|
||||||
|
/build
|
||||||
|
|
||||||
|
# Qt Creator files
|
||||||
|
/CMakeLists.txt.user*
|
||||||
|
/wdmtg.config
|
||||||
|
/wdmtg.files
|
||||||
|
/wdmtg.creator*
|
||||||
|
/wdmtg.includes
|
|
@ -0,0 +1,84 @@
|
||||||
|
project (wdmtg C)
|
||||||
|
cmake_minimum_required (VERSION 2.8.12)
|
||||||
|
|
||||||
|
# Vala really sucks at producing good C code
|
||||||
|
if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC)
|
||||||
|
set (CMAKE_C_FLAGS_RELEASE
|
||||||
|
"${CMAKE_C_FLAGS_RELEASE} -Wno-ignored-qualifiers -Wno-incompatible-pointer-types")
|
||||||
|
endif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC)
|
||||||
|
|
||||||
|
# Options
|
||||||
|
option (OPTION_NOINSTALL "Only for developers; work without installing" OFF)
|
||||||
|
|
||||||
|
# Version
|
||||||
|
set (project_VERSION "0.1.0")
|
||||||
|
|
||||||
|
# Set some variables
|
||||||
|
if (OPTION_NOINSTALL)
|
||||||
|
set (project_SHARE_DIR ${PROJECT_SOURCE_DIR}/share)
|
||||||
|
elseif (WIN32)
|
||||||
|
set (project_SHARE_DIR ../share)
|
||||||
|
set (project_INSTALL_SHARE_DIR share)
|
||||||
|
else (OPTION_NOINSTALL)
|
||||||
|
set (project_SHARE_DIR ${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME})
|
||||||
|
set (project_INSTALL_SHARE_DIR share/${PROJECT_NAME})
|
||||||
|
endif (OPTION_NOINSTALL)
|
||||||
|
|
||||||
|
# Gather package information
|
||||||
|
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
find_package (Vala 0.12 REQUIRED)
|
||||||
|
find_package (PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules (dependencies REQUIRED gtk+-3.0 sqlite3 x11 xext xextproto)
|
||||||
|
|
||||||
|
# Precompile Vala sources
|
||||||
|
include (ValaPrecompile)
|
||||||
|
|
||||||
|
set (HEADER_PATH "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.h")
|
||||||
|
set (CONFIG_PATH "${PROJECT_BINARY_DIR}/config.vala")
|
||||||
|
configure_file (${PROJECT_SOURCE_DIR}/config.vala.in ${CONFIG_PATH})
|
||||||
|
|
||||||
|
# I'm not sure what this was about, look at slovnik-gui for more comments
|
||||||
|
set (SYMBOLS_PATH "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.def")
|
||||||
|
|
||||||
|
vala_init (${PROJECT_NAME}
|
||||||
|
PACKAGES gmodule-2.0 gio-2.0 gtk+-3.0 gee-0.8 sqlite3 x11
|
||||||
|
CUSTOM_VAPIS ${PROJECT_SOURCE_DIR}/xsync.vapi)
|
||||||
|
vala_add (${PROJECT_NAME} ${CONFIG_PATH})
|
||||||
|
vala_add (${PROJECT_NAME} ${PROJECT_NAME}.vala DEPENDS config)
|
||||||
|
|
||||||
|
vala_finish (${PROJECT_NAME}
|
||||||
|
SOURCES project_VALA_SOURCES
|
||||||
|
OUTPUTS project_VALA_C
|
||||||
|
GENERATE_HEADER ${HEADER_PATH}
|
||||||
|
GENERATE_SYMBOLS ${SYMBOLS_PATH})
|
||||||
|
|
||||||
|
# Include Vala sources as header files, so they appear in the IDE
|
||||||
|
# but CMake doesn't try to compile them directly
|
||||||
|
set_source_files_properties (${project_VALA_SOURCES}
|
||||||
|
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||||
|
set (project_SOURCES ${project_VALA_SOURCES} ${project_VALA_C} ${SYMBOLS_PATH})
|
||||||
|
|
||||||
|
# Build the executable and install it
|
||||||
|
include_directories (${dependencies_INCLUDE_DIRS})
|
||||||
|
link_directories (${dependencies_LIBRARY_DIRS})
|
||||||
|
add_executable (${PROJECT_NAME} ${project_SOURCES})
|
||||||
|
target_link_libraries (${PROJECT_NAME} ${dependencies_LIBRARIES})
|
||||||
|
|
||||||
|
install (TARGETS ${PROJECT_NAME} DESTINATION bin)
|
||||||
|
|
||||||
|
# CPack
|
||||||
|
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Activity tracker")
|
||||||
|
set (CPACK_PACKAGE_VENDOR "Přemysl Janouch")
|
||||||
|
set (CPACK_PACKAGE_CONTACT "Přemysl Janouch <p.janouch@gmail.com>")
|
||||||
|
set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||||
|
set (CPACK_PACKAGE_VERSION ${project_VERSION})
|
||||||
|
set (CPACK_GENERATOR "TGZ;ZIP")
|
||||||
|
set (CPACK_PACKAGE_FILE_NAME
|
||||||
|
"${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
set (CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
|
||||||
|
set (CPACK_SOURCE_IGNORE_FILES "/build;/\\\\.git")
|
||||||
|
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
|
||||||
|
include (CPack)
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
Copyright (c) 2016, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
SPECIAL, DIRECT, 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.
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
wdmtg
|
||||||
|
=====
|
||||||
|
|
||||||
|
'wdmtg' (Where Did My Time Go) is an automatic activity tracker for X11.
|
||||||
|
It tracks the current window title and whether the user seems to be idle.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
Currently it's still under development, stuck in a proof-of-concept phase.
|
||||||
|
|
||||||
|
Packages
|
||||||
|
--------
|
||||||
|
Regular releases are sporadic. git master should be stable enough. You can get
|
||||||
|
a package with the latest development version from Archlinux's AUR, or from
|
||||||
|
openSUSE Build Service for the rest of mainstream distributions. Consult the
|
||||||
|
list of repositories and their respective links at:
|
||||||
|
|
||||||
|
https://build.opensuse.org/project/repositories/home:pjanouch:git
|
||||||
|
|
||||||
|
Building and Running
|
||||||
|
--------------------
|
||||||
|
Build dependencies: CMake, pkg-config, Vala >= 0.12 +
|
||||||
|
Runtime dependencies: gtk+-3.0, sqlite3, x11, xextproto, xext
|
||||||
|
|
||||||
|
$ git clone --recursive https://github.com/pjanouch/wdmtg.git
|
||||||
|
$ mkdir wdmtg/build
|
||||||
|
$ cd wdmtg/build
|
||||||
|
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug
|
||||||
|
$ make
|
||||||
|
|
||||||
|
To install the application, you can do either the usual:
|
||||||
|
|
||||||
|
# make install
|
||||||
|
|
||||||
|
Or you can try telling CMake to make a package for you. For Debian it is:
|
||||||
|
|
||||||
|
$ cpack -G DEB
|
||||||
|
# dpkg -i wdmtg-*.deb
|
||||||
|
|
||||||
|
Contributing and Support
|
||||||
|
------------------------
|
||||||
|
Use this project's GitHub to report any bugs, request features, or submit pull
|
||||||
|
requests. If you want to discuss this project, or maybe just hang out with
|
||||||
|
the developer, feel free to join me at irc://irc.janouch.name, channel #dev.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
'wdmtg' is written by Přemysl Janouch <p.janouch@gmail.com>.
|
||||||
|
|
||||||
|
You may use the software under the terms of the ISC license, the text of which
|
||||||
|
is included within the package, or, at your option, you may relicense the work
|
||||||
|
under the MIT or the Modified BSD License, as listed at the following site:
|
||||||
|
|
||||||
|
http://www.gnu.org/licenses/license-list.html
|
|
@ -0,0 +1,47 @@
|
||||||
|
# - Find Vala
|
||||||
|
# This module looks for valac.
|
||||||
|
# This module defines the following values:
|
||||||
|
# VALA_FOUND
|
||||||
|
# VALA_COMPILER
|
||||||
|
# VALA_VERSION
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright Přemysl Janouch 2011
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
# OF SUCH DAMAGE.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
find_program (VALA_COMPILER "valac")
|
||||||
|
|
||||||
|
if (VALA_COMPILER)
|
||||||
|
execute_process (COMMAND ${VALA_COMPILER} --version
|
||||||
|
OUTPUT_VARIABLE VALA_VERSION)
|
||||||
|
string (REGEX MATCH "[.0-9]+" VALA_VERSION "${VALA_VERSION}")
|
||||||
|
endif (VALA_COMPILER)
|
||||||
|
|
||||||
|
include (FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS (Vala
|
||||||
|
REQUIRED_VARS VALA_COMPILER
|
||||||
|
VERSION_VAR VALA_VERSION)
|
||||||
|
|
||||||
|
mark_as_advanced (VALA_COMPILER VALA_VERSION)
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
# - Precompilation of Vala/Genie source files into C sources
|
||||||
|
# Makes use of the parallel build ability introduced in Vala 0.11. Derived
|
||||||
|
# from a similar module by Jakob Westhoff and the original GNU Make rules.
|
||||||
|
# Might be a bit oversimplified.
|
||||||
|
#
|
||||||
|
# This module defines three functions. The first one:
|
||||||
|
#
|
||||||
|
# vala_init (id
|
||||||
|
# [DIRECTORY dir] - Output directory (binary dir by default)
|
||||||
|
# [PACKAGES package...] - Package dependencies
|
||||||
|
# [OPTIONS option...] - Extra valac options
|
||||||
|
# [CUSTOM_VAPIS file...]) - Custom vapi files to include in the build
|
||||||
|
#
|
||||||
|
# initializes a single precompilation unit using the given arguments.
|
||||||
|
# You can put files into it via the following function:
|
||||||
|
#
|
||||||
|
# vala_add (id source.vala
|
||||||
|
# [DEPENDS source...]) - Vala/Genie source or .vapi dependencies
|
||||||
|
#
|
||||||
|
# Finally retrieve paths for generated C files by calling:
|
||||||
|
#
|
||||||
|
# vala_finish (id
|
||||||
|
# [SOURCES sources_var] - Input Vala/Genie sources
|
||||||
|
# [OUTPUTS outputs_var] - Output C sources
|
||||||
|
# [GENERATE_HEADER id.h - Generate id.h and id_internal.h
|
||||||
|
# [GENERATE_VAPI id.vapi] - Generate a vapi file
|
||||||
|
# [GENERATE_SYMBOLS id.def]]) - Generate a list of public symbols
|
||||||
|
#
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright Přemysl Janouch 2011
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
# OF SUCH DAMAGE.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
find_package (Vala 0.11 REQUIRED)
|
||||||
|
include (CMakeParseArguments)
|
||||||
|
|
||||||
|
function (vala_init id)
|
||||||
|
set (_multi_value PACKAGES OPTIONS CUSTOM_VAPIS)
|
||||||
|
cmake_parse_arguments (arg "" "DIRECTORY" "${_multi_value}" ${ARGN})
|
||||||
|
|
||||||
|
if (arg_DIRECTORY)
|
||||||
|
set (directory ${arg_DIRECTORY})
|
||||||
|
if (NOT IS_DIRECTORY ${directory})
|
||||||
|
file (MAKE_DIRECTORY ${directory})
|
||||||
|
endif (NOT IS_DIRECTORY ${directory})
|
||||||
|
else (arg_DIRECTORY)
|
||||||
|
set (directory ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
endif (arg_DIRECTORY)
|
||||||
|
|
||||||
|
set (pkg_opts)
|
||||||
|
foreach (pkg ${arg_PACKAGES})
|
||||||
|
list (APPEND pkg_opts "--pkg=${pkg}")
|
||||||
|
endforeach (pkg)
|
||||||
|
|
||||||
|
set (VALA_${id}_DIR "${directory}" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_ARGS ${pkg_opts} ${arg_OPTIONS}
|
||||||
|
${arg_CUSTOM_VAPIS} PARENT_SCOPE)
|
||||||
|
|
||||||
|
set (VALA_${id}_SOURCES "" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_OUTPUTS "" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_FAST_VAPI_FILES "" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_FAST_VAPI_ARGS "" PARENT_SCOPE)
|
||||||
|
endfunction (vala_init)
|
||||||
|
|
||||||
|
function (vala_add id file)
|
||||||
|
cmake_parse_arguments (arg "" "" "DEPENDS" ${ARGN})
|
||||||
|
|
||||||
|
if (NOT IS_ABSOLUTE "${file}")
|
||||||
|
set (file "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
|
||||||
|
endif (NOT IS_ABSOLUTE "${file}")
|
||||||
|
|
||||||
|
get_filename_component (output_name "${file}" NAME)
|
||||||
|
get_filename_component (output_base "${file}" NAME_WE)
|
||||||
|
set (output_base "${VALA_${id}_DIR}/${output_base}")
|
||||||
|
|
||||||
|
# XXX: It would be best to have it working without touching the vapi
|
||||||
|
# but it appears this cannot be done in CMake.
|
||||||
|
add_custom_command (OUTPUT "${output_base}.vapi"
|
||||||
|
COMMAND ${VALA_COMPILER} "${file}" "--fast-vapi=${output_base}.vapi"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E touch "${output_base}.vapi"
|
||||||
|
DEPENDS "${file}"
|
||||||
|
COMMENT "Generating a fast vapi for ${output_name}" VERBATIM)
|
||||||
|
|
||||||
|
set (vapi_opts)
|
||||||
|
set (vapi_depends)
|
||||||
|
foreach (vapi ${arg_DEPENDS})
|
||||||
|
if (NOT IS_ABSOLUTE "${vapi}")
|
||||||
|
set (vapi "${VALA_${id}_DIR}/${vapi}.vapi")
|
||||||
|
endif (NOT IS_ABSOLUTE "${vapi}")
|
||||||
|
|
||||||
|
list (APPEND vapi_opts "--use-fast-vapi=${vapi}")
|
||||||
|
list (APPEND vapi_depends "${vapi}")
|
||||||
|
endforeach (vapi)
|
||||||
|
|
||||||
|
add_custom_command (OUTPUT "${output_base}.c"
|
||||||
|
COMMAND ${VALA_COMPILER} "${file}" -C ${vapi_opts} ${VALA_${id}_ARGS}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E touch "${output_base}.c"
|
||||||
|
DEPENDS "${file}" ${vapi_depends}
|
||||||
|
WORKING_DIRECTORY "${VALA_${id}_DIR}"
|
||||||
|
COMMENT "Precompiling ${output_name}" VERBATIM)
|
||||||
|
|
||||||
|
set (VALA_${id}_SOURCES ${VALA_${id}_SOURCES}
|
||||||
|
"${file}" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_OUTPUTS ${VALA_${id}_OUTPUTS}
|
||||||
|
"${output_base}.c" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_FAST_VAPI_FILES ${VALA_${id}_FAST_VAPI_FILES}
|
||||||
|
"${output_base}.vapi" PARENT_SCOPE)
|
||||||
|
set (VALA_${id}_FAST_VAPI_ARGS ${VALA_${id}_FAST_VAPI_ARGS}
|
||||||
|
"--use-fast-vapi=${output_base}.vapi" PARENT_SCOPE)
|
||||||
|
endfunction (vala_add)
|
||||||
|
|
||||||
|
function (vala_finish id)
|
||||||
|
set (_one_value SOURCES OUTPUTS
|
||||||
|
GENERATE_VAPI GENERATE_HEADER GENERATE_SYMBOLS)
|
||||||
|
cmake_parse_arguments (arg "" "${_one_value}" "" ${ARGN})
|
||||||
|
|
||||||
|
if (arg_SOURCES)
|
||||||
|
set (${arg_SOURCES} ${VALA_${id}_SOURCES} PARENT_SCOPE)
|
||||||
|
endif (arg_SOURCES)
|
||||||
|
|
||||||
|
if (arg_OUTPUTS)
|
||||||
|
set (${arg_OUTPUTS} ${VALA_${id}_OUTPUTS} PARENT_SCOPE)
|
||||||
|
endif (arg_OUTPUTS)
|
||||||
|
|
||||||
|
set (outputs)
|
||||||
|
set (export_args)
|
||||||
|
|
||||||
|
if (arg_GENERATE_VAPI)
|
||||||
|
if (NOT IS_ABSOLUTE "${arg_GENERATE_VAPI}")
|
||||||
|
set (arg_GENERATE_VAPI
|
||||||
|
"${VALA_${id}_DIR}/${arg_GENERATE_VAPI}")
|
||||||
|
endif (NOT IS_ABSOLUTE "${arg_GENERATE_VAPI}")
|
||||||
|
|
||||||
|
list (APPEND outputs "${arg_GENERATE_VAPI}")
|
||||||
|
list (APPEND export_args "--internal-vapi=${arg_GENERATE_VAPI}")
|
||||||
|
|
||||||
|
if (NOT arg_GENERATE_HEADER)
|
||||||
|
message (FATAL_ERROR "Header generation required for vapi")
|
||||||
|
endif (NOT arg_GENERATE_HEADER)
|
||||||
|
endif (arg_GENERATE_VAPI)
|
||||||
|
|
||||||
|
if (arg_GENERATE_SYMBOLS)
|
||||||
|
if (NOT IS_ABSOLUTE "${arg_GENERATE_SYMBOLS}")
|
||||||
|
set (arg_GENERATE_SYMBOLS
|
||||||
|
"${VALA_${id}_DIR}/${arg_GENERATE_SYMBOLS}")
|
||||||
|
endif (NOT IS_ABSOLUTE "${arg_GENERATE_SYMBOLS}")
|
||||||
|
|
||||||
|
list (APPEND outputs "${arg_GENERATE_SYMBOLS}")
|
||||||
|
list (APPEND export_args "--symbols=${arg_GENERATE_SYMBOLS}")
|
||||||
|
|
||||||
|
if (NOT arg_GENERATE_HEADER)
|
||||||
|
message (FATAL_ERROR "Header generation required for symbols")
|
||||||
|
endif (NOT arg_GENERATE_HEADER)
|
||||||
|
endif (arg_GENERATE_SYMBOLS)
|
||||||
|
|
||||||
|
if (arg_GENERATE_HEADER)
|
||||||
|
if (NOT IS_ABSOLUTE "${arg_GENERATE_HEADER}")
|
||||||
|
set (arg_GENERATE_HEADER
|
||||||
|
"${VALA_${id}_DIR}/${arg_GENERATE_HEADER}")
|
||||||
|
endif (NOT IS_ABSOLUTE "${arg_GENERATE_HEADER}")
|
||||||
|
|
||||||
|
get_filename_component (header_path "${arg_GENERATE_HEADER}" PATH)
|
||||||
|
get_filename_component (header_name "${arg_GENERATE_HEADER}" NAME_WE)
|
||||||
|
set (header_base "${header_path}/${header_name}")
|
||||||
|
get_filename_component (header_ext "${arg_GENERATE_HEADER}" EXT)
|
||||||
|
|
||||||
|
list (APPEND outputs
|
||||||
|
"${header_base}${header_ext}"
|
||||||
|
"${header_base}_internal${header_ext}")
|
||||||
|
list (APPEND export_args
|
||||||
|
"--header=${header_base}${header_ext}"
|
||||||
|
"--internal-header=${header_base}_internal${header_ext}")
|
||||||
|
endif (arg_GENERATE_HEADER)
|
||||||
|
|
||||||
|
if (outputs)
|
||||||
|
add_custom_command (OUTPUT ${outputs}
|
||||||
|
COMMAND ${VALA_COMPILER} -C ${VALA_${id}_ARGS}
|
||||||
|
${export_args} ${VALA_${id}_FAST_VAPI_ARGS}
|
||||||
|
DEPENDS ${VALA_${id}_FAST_VAPI_FILES}
|
||||||
|
COMMENT "Generating vapi/headers/symbols" VERBATIM)
|
||||||
|
endif (outputs)
|
||||||
|
endfunction (vala_finish id)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
[CCode (cprefix = "", lower_case_cprefix = "")]
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
public const string PROJECT_NAME = "${CMAKE_PROJECT_NAME}";
|
||||||
|
public const string PROJECT_VERSION = "${project_VERSION_MAJOR}.${project_VERSION_MINOR}.${project_VERSION_PATCH}";
|
||||||
|
public const string SHARE_DIR = "@project_SHARE_DIR@";
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
//
|
||||||
|
// wdmtg.vala: activity tracker
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
// SPECIAL, DIRECT, 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.
|
||||||
|
//
|
||||||
|
// vim: set sw=2 ts=2 sts=2 et tw=80:
|
||||||
|
// modules: x11 xsync config
|
||||||
|
// vapidirs: . ../build build
|
||||||
|
|
||||||
|
namespace Wdmtg {
|
||||||
|
|
||||||
|
// --- Utilities ---------------------------------------------------------------
|
||||||
|
|
||||||
|
void exit_fatal (string format, ...) {
|
||||||
|
stderr.vprintf ("fatal: " + format + "\n", va_list ());
|
||||||
|
Process.exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] get_xdg_config_dirs () {
|
||||||
|
string[] paths = { Environment.get_user_config_dir () };
|
||||||
|
foreach (var system_path in Environment.get_system_config_dirs ())
|
||||||
|
paths += system_path;
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Globals -----------------------------------------------------------------
|
||||||
|
|
||||||
|
X.Display dpy; ///< X display handle
|
||||||
|
|
||||||
|
X.ID idle_counter; ///< XSync IDLETIME counter
|
||||||
|
X.Sync.Value idle_timeout; ///< User idle timeout
|
||||||
|
|
||||||
|
X.ID idle_alarm_inactive; ///< User is inactive
|
||||||
|
X.ID idle_alarm_active; ///< User is active
|
||||||
|
|
||||||
|
X.Atom net_active_window; ///< _NET_ACTIVE_WINDOW atom
|
||||||
|
X.Atom net_wm_name; ///< _NET_WM_NAME atom
|
||||||
|
|
||||||
|
string? current_title; ///< Current window title
|
||||||
|
X.Window current_window; ///< Current window
|
||||||
|
|
||||||
|
// --- X helpers ---------------------------------------------------------------
|
||||||
|
|
||||||
|
X.ID get_counter (string name) {
|
||||||
|
int n_counters = 0;
|
||||||
|
var counters = X.Sync.list_system_counters (dpy, out n_counters);
|
||||||
|
X.ID counter = X.None;
|
||||||
|
while (n_counters-- > 0) {
|
||||||
|
if (counters[n_counters].name == name)
|
||||||
|
counter = counters[n_counters].counter;
|
||||||
|
}
|
||||||
|
X.Sync.free_system_counter_list (counters);
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? x_text_property_to_utf8 (ref X.TextProperty prop) {
|
||||||
|
X.Atom utf8_string = dpy.intern_atom ("UTF8_STRING", true);
|
||||||
|
if (prop.encoding == utf8_string)
|
||||||
|
return (string) prop.value;
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
uint8 **list = null;
|
||||||
|
if (X.mb_text_property_to_text_list (dpy, ref prop, out list, out n)
|
||||||
|
>= X.Success && n > 0 && null != list[0]) {
|
||||||
|
var result = ((string) list[0]).locale_to_utf8 (-1, null, null);
|
||||||
|
X.free_string_list (list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? x_text_property (X.Window window, X.Atom atom) {
|
||||||
|
X.TextProperty name;
|
||||||
|
X.get_text_property (dpy, window, out name, atom);
|
||||||
|
if (null == name.@value)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string? result = x_text_property_to_utf8 (ref name);
|
||||||
|
X.free (name.@value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- X error handling --------------------------------------------------------
|
||||||
|
|
||||||
|
X.ErrorHandler default_x_error_handler;
|
||||||
|
|
||||||
|
int on_x_error (X.Display dpy, X.ErrorEvent *ee) {
|
||||||
|
// This just is going to happen since those windows aren't ours
|
||||||
|
if (ee.error_code == X.ErrorCode.BAD_WINDOW)
|
||||||
|
return 0;
|
||||||
|
return default_x_error_handler (dpy, ee);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Application -------------------------------------------------------------
|
||||||
|
|
||||||
|
string x_window_title (X.Window window) {
|
||||||
|
string? title;
|
||||||
|
if (null == (title = x_text_property (window, net_wm_name))
|
||||||
|
&& null == (title = x_text_property (window, X.XA_WM_NAME)))
|
||||||
|
title = "broken";
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_window_title (string? new_title) {
|
||||||
|
bool changed = (null == current_title) != (null == new_title)
|
||||||
|
|| current_title != new_title;
|
||||||
|
current_title = new_title;
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_current_window () {
|
||||||
|
var root = dpy.default_root_window ();
|
||||||
|
X.Atom dummy_type; int dummy_format; ulong nitems, dummy_bytes;
|
||||||
|
void *p = null;
|
||||||
|
if (dpy.get_window_property (root, net_active_window,
|
||||||
|
0, 1, false, X.XA_WINDOW, out dummy_type, out dummy_format,
|
||||||
|
out nitems, out dummy_bytes, out p) != X.Success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string? new_title = null;
|
||||||
|
if (0 != nitems) {
|
||||||
|
X.Window active_window = *(X.Window *) p;
|
||||||
|
X.free (p);
|
||||||
|
|
||||||
|
if (current_window != active_window && X.None != current_window)
|
||||||
|
dpy.select_input (current_window, 0);
|
||||||
|
dpy.select_input (active_window, X.EventMask.PropertyChangeMask);
|
||||||
|
new_title = x_window_title (active_window);
|
||||||
|
current_window = active_window;
|
||||||
|
}
|
||||||
|
if (update_window_title (new_title))
|
||||||
|
stdout.printf ("Window changed: %s\n",
|
||||||
|
null != current_title ? current_title : "(none)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_x_property_notify (X.PropertyEvent *xproperty) {
|
||||||
|
// This is from the EWMH specification, set by the window manager
|
||||||
|
if (xproperty.atom == net_active_window)
|
||||||
|
update_current_window ();
|
||||||
|
else if (xproperty.window == current_window
|
||||||
|
&& xproperty.atom == net_wm_name) {
|
||||||
|
if (update_window_title (x_window_title (current_window)))
|
||||||
|
stdout.printf ("Title changed: %s\n", current_title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_idle_alarm
|
||||||
|
(ref X.ID alarm, X.Sync.TestType test, X.Sync.Value @value) {
|
||||||
|
X.Sync.AlarmAttributes attr = {};
|
||||||
|
attr.trigger.counter = idle_counter;
|
||||||
|
attr.trigger.test_type = test;
|
||||||
|
attr.trigger.wait_value = @value;
|
||||||
|
X.Sync.int_to_value (out attr.delta, 0);
|
||||||
|
|
||||||
|
X.Sync.CA flags = X.Sync.CA.Counter | X.Sync.CA.TestType
|
||||||
|
| X.Sync.CA.Value | X.Sync.CA.Delta;
|
||||||
|
if (X.None != alarm)
|
||||||
|
X.Sync.change_alarm (dpy, alarm, flags, ref attr);
|
||||||
|
else
|
||||||
|
alarm = X.Sync.create_alarm (dpy, flags, ref attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_x_alarm_notify (X.Sync.AlarmNotifyEvent *xalarm) {
|
||||||
|
if (xalarm.alarm == idle_alarm_inactive) {
|
||||||
|
stdout.printf ("User is inactive\n");
|
||||||
|
|
||||||
|
X.Sync.Value one, minus_one;
|
||||||
|
X.Sync.int_to_value (out one, 1);
|
||||||
|
|
||||||
|
int overflow;
|
||||||
|
X.Sync.value_subtract
|
||||||
|
(out minus_one, xalarm.counter_value, one, out overflow);
|
||||||
|
|
||||||
|
// Set an alarm for IDLETIME <= current_idletime - 1
|
||||||
|
set_idle_alarm (ref idle_alarm_active,
|
||||||
|
X.Sync.TestType.NegativeComparison, minus_one);
|
||||||
|
} else if (xalarm.alarm == idle_alarm_inactive) {
|
||||||
|
stdout.printf ("User is active\n");
|
||||||
|
set_idle_alarm (ref idle_alarm_inactive,
|
||||||
|
X.Sync.TestType.PositiveComparison, idle_timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool show_version;
|
||||||
|
const OptionEntry[] options = {
|
||||||
|
{ "version", 'V', OptionFlags.IN_MAIN, OptionArg.NONE, ref show_version,
|
||||||
|
"output version information and exit" },
|
||||||
|
{ null }
|
||||||
|
};
|
||||||
|
|
||||||
|
public int main (string[] args) {
|
||||||
|
if (null == Intl.setlocale (GLib.LocaleCategory.CTYPE))
|
||||||
|
exit_fatal ("cannot set locale");
|
||||||
|
if (0 == X.supports_locale ())
|
||||||
|
exit_fatal ("locale not supported by Xlib");
|
||||||
|
|
||||||
|
try {
|
||||||
|
var ctx = new OptionContext (" - activity tracker");
|
||||||
|
ctx.set_help_enabled (true);
|
||||||
|
ctx.add_main_entries (options, null);
|
||||||
|
ctx.parse (ref args);
|
||||||
|
} catch (OptionError e) {
|
||||||
|
exit_fatal ("option parsing failed: %s", e.message);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (show_version) {
|
||||||
|
stdout.printf (Config.PROJECT_NAME + " " + Config.PROJECT_VERSION + "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X.init_threads ();
|
||||||
|
if (null == (dpy = new X.Display ()))
|
||||||
|
exit_fatal ("cannot open display");
|
||||||
|
|
||||||
|
net_active_window = dpy.intern_atom ("_NET_ACTIVE_WINDOW", true);
|
||||||
|
net_wm_name = dpy.intern_atom ("_NET_WM_NAME", true);
|
||||||
|
|
||||||
|
// TODO: it is possible to employ a fallback mechanism via XScreenSaver
|
||||||
|
// by polling the XScreenSaverInfo::idle field, see
|
||||||
|
// https://www.x.org/releases/X11R7.5/doc/man/man3/Xss.3.html
|
||||||
|
|
||||||
|
int sync_base, dummy;
|
||||||
|
if (0 == X.Sync.query_extension (dpy, out sync_base, out dummy)
|
||||||
|
|| 0 == X.Sync.initialize (dpy, out dummy, out dummy))
|
||||||
|
exit_fatal ("cannot initialize XSync");
|
||||||
|
|
||||||
|
// The idle counter is not guaranteed to exist, only SERVERTIME is
|
||||||
|
if (X.None == (idle_counter = get_counter ("IDLETIME")))
|
||||||
|
exit_fatal ("idle counter is missing");
|
||||||
|
|
||||||
|
var root = dpy.default_root_window ();
|
||||||
|
dpy.select_input (root, X.EventMask.PropertyChangeMask);
|
||||||
|
X.sync (dpy, false);
|
||||||
|
default_x_error_handler = X.set_error_handler (on_x_error);
|
||||||
|
|
||||||
|
int timeout = 600; // 10 minutes by default
|
||||||
|
try {
|
||||||
|
var kf = new KeyFile ();
|
||||||
|
kf.load_from_dirs (Config.PROJECT_NAME + Path.DIR_SEPARATOR_S
|
||||||
|
+ Config.PROJECT_NAME + ".conf", get_xdg_config_dirs (), null, 0);
|
||||||
|
|
||||||
|
var n = kf.get_uint64 ("Settings", "idle_timeout");
|
||||||
|
if (0 != n && n <= int.MAX / 1000)
|
||||||
|
timeout = (int) n;
|
||||||
|
} catch (Error e) {
|
||||||
|
// Ignore errors this far, keeping the defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
X.Sync.int_to_value (out idle_timeout, timeout * 1000);
|
||||||
|
update_current_window ();
|
||||||
|
set_idle_alarm (ref idle_alarm_inactive,
|
||||||
|
X.Sync.TestType.PositiveComparison, idle_timeout);
|
||||||
|
|
||||||
|
var loop = new MainLoop ();
|
||||||
|
var channel = new IOChannel.unix_new (dpy.connection_number ());
|
||||||
|
channel.add_watch (IOCondition.IN, (source, condition) => {
|
||||||
|
if (0 == (condition & IOCondition.IN))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
X.Event ev = {0};
|
||||||
|
while (0 != dpy.pending ()) {
|
||||||
|
if (0 != dpy.next_event (ref ev)) {
|
||||||
|
exit_fatal ("XNextEvent returned non-zero");
|
||||||
|
} else if (ev.type == X.EventType.PropertyNotify) {
|
||||||
|
on_x_property_notify (&ev.xproperty);
|
||||||
|
} else if (ev.type == sync_base + X.Sync.EventType.AlarmNotify) {
|
||||||
|
on_x_alarm_notify ((X.Sync.AlarmNotifyEvent *) (&ev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
loop.run ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
//
|
||||||
|
// xsync.vapi: selected XSync APIs
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
// SPECIAL, DIRECT, 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.
|
||||||
|
//
|
||||||
|
// vim: set sw=2 ts=2 sts=2 et tw=80:
|
||||||
|
// modules: x11
|
||||||
|
|
||||||
|
// TODO: move this outside, I didn't expect the Xlib binding to be this shitty
|
||||||
|
namespace X {
|
||||||
|
[CCode (cname = "XErrorHandler", has_target = false)]
|
||||||
|
public delegate int ErrorHandler (Display dpy, ErrorEvent *ee);
|
||||||
|
[CCode (cname = "XSetErrorHandler")]
|
||||||
|
public ErrorHandler set_error_handler (ErrorHandler handler);
|
||||||
|
|
||||||
|
// XXX: can we extend the Display class so that the argument goes away?
|
||||||
|
[CCode (cname = "XSync")]
|
||||||
|
public int sync (Display dpy, bool discard);
|
||||||
|
[CCode (cname = "XSupportsLocale")]
|
||||||
|
public int supports_locale ();
|
||||||
|
|
||||||
|
[CCode (cname = "XTextProperty", has_type_id = false)]
|
||||||
|
public struct TextProperty {
|
||||||
|
// There is always a null byte at the end but it may also appear earlier
|
||||||
|
// depending on the other fields, so this is a bit misleading
|
||||||
|
[CCode (array_null_terminated = true)]
|
||||||
|
// Vala tries to g_free0() owned arrays, you still need to call XFree()
|
||||||
|
public unowned uint8[]? @value;
|
||||||
|
public Atom encoding;
|
||||||
|
public int format;
|
||||||
|
public ulong nitems;
|
||||||
|
}
|
||||||
|
[CCode (cname = "XGetTextProperty")]
|
||||||
|
public int get_text_property (Display dpy, Window window, out TextProperty text_prop_return, Atom property);
|
||||||
|
|
||||||
|
[CCode (cname = "XmbTextPropertyToTextList")]
|
||||||
|
public int mb_text_property_to_text_list (Display dpy, ref TextProperty text_prop, [CCode (type = "char ***")] out uint8 **list_return, out int count_return);
|
||||||
|
[CCode (cname = "XFreeStringList")]
|
||||||
|
public void free_string_list ([CCode (type = "char **")] uint8** list);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace X {
|
||||||
|
[CCode (cprefix = "", cheader_filename = "X11/extensions/sync.h")]
|
||||||
|
namespace Sync {
|
||||||
|
[CCode (cprefix = "XSync", cname = "int", has_type_id = false)]
|
||||||
|
public enum EventType {
|
||||||
|
CounterNotify,
|
||||||
|
AlarmNotify
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "", cname = "int", has_type_id = false)]
|
||||||
|
public enum ErrorCode {
|
||||||
|
[CCode (cname = "XSyncBadCounter")]
|
||||||
|
BAD_COUNTER,
|
||||||
|
[CCode (cname = "XSyncBadAlarm")]
|
||||||
|
BAD_ALARM,
|
||||||
|
[CCode (cname = "XSyncBadFence")]
|
||||||
|
BAD_FENCE
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cprefix = "XSyncCA", cname = "int")]
|
||||||
|
[Flags]
|
||||||
|
public enum CA {
|
||||||
|
Counter,
|
||||||
|
ValueType,
|
||||||
|
Value,
|
||||||
|
TestType,
|
||||||
|
Delta,
|
||||||
|
Events
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncValueType", cprefix = "XSync")]
|
||||||
|
public enum ValueType {
|
||||||
|
Absolute,
|
||||||
|
Relative
|
||||||
|
}
|
||||||
|
[CCode (cname = "XSyncTestType", cprefix = "XSync")]
|
||||||
|
public enum TestType {
|
||||||
|
PositiveTransition,
|
||||||
|
NegativeTransition,
|
||||||
|
PositiveComparison,
|
||||||
|
NegativeComparison
|
||||||
|
}
|
||||||
|
[CCode (cname = "XSyncAlarmState", cprefix = "XSyncAlarm")]
|
||||||
|
public enum AlarmState {
|
||||||
|
Active,
|
||||||
|
Inactive,
|
||||||
|
Destroyed
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncValue", has_type_id = false)]
|
||||||
|
[SimpleType]
|
||||||
|
public struct Value {
|
||||||
|
public int hi;
|
||||||
|
public uint lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncIntToValue")]
|
||||||
|
public void int_to_value (out Value value, int v);
|
||||||
|
[CCode (cname = "XSyncIntsToValue")]
|
||||||
|
public void ints_to_value (out Value value, uint l, int h);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncValueGreaterThan")]
|
||||||
|
public int value_greater_than (Value a, Value b);
|
||||||
|
[CCode (cname = "XSyncValueLessThan")]
|
||||||
|
public int value_less_than (Value a, Value b);
|
||||||
|
[CCode (cname = "XSyncValueGreaterOrEqual")]
|
||||||
|
public int value_greater_or_equal (Value a, Value b);
|
||||||
|
[CCode (cname = "XSyncValueLessOrEqual")]
|
||||||
|
public int value_less_or_equal (Value a, Value b);
|
||||||
|
[CCode (cname = "XSyncValueEqual")]
|
||||||
|
public int value_equal (Value a, Value b);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncValueIsNegative")]
|
||||||
|
public int value_is_negative (Value a, Value b);
|
||||||
|
[CCode (cname = "XSyncValueIsZero")]
|
||||||
|
public int value_is_zero (Value a, Value b);
|
||||||
|
[CCode (cname = "XSyncValueIsPositive")]
|
||||||
|
public int value_is_positive (Value a, Value b);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncValueLow32")]
|
||||||
|
public uint value_low32 (Value value);
|
||||||
|
[CCode (cname = "XSyncValueHigh32")]
|
||||||
|
public int value_high32 (Value value);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncValueAdd")]
|
||||||
|
public void value_add (out Value result, Value a, Value b, out int poverflow);
|
||||||
|
[CCode (cname = "XSyncValueSubtract")]
|
||||||
|
public void value_subtract (out Value result, Value a, Value b, out int poverflow);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncMaxValue")]
|
||||||
|
public void max_value (out Value pv);
|
||||||
|
[CCode (cname = "XSyncMinValue")]
|
||||||
|
public void min_value (out Value pv);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncSystemCounter", has_type_id = false)]
|
||||||
|
public struct SystemCounter {
|
||||||
|
public string name;
|
||||||
|
public X.ID counter;
|
||||||
|
public Value resolution;
|
||||||
|
}
|
||||||
|
[CCode (cname = "XSyncTrigger", has_type_id = false)]
|
||||||
|
public struct Trigger {
|
||||||
|
public X.ID counter;
|
||||||
|
public ValueType value_type;
|
||||||
|
public Value wait_value;
|
||||||
|
public TestType test_type;
|
||||||
|
}
|
||||||
|
[CCode (cname = "XSyncWaitCondition", has_type_id = false)]
|
||||||
|
public struct WaitCondition {
|
||||||
|
public Trigger trigger;
|
||||||
|
public Value event_threshold;
|
||||||
|
}
|
||||||
|
[CCode (cname = "XSyncAlarmAttributes", has_type_id = false)]
|
||||||
|
public struct AlarmAttributes {
|
||||||
|
public Trigger trigger;
|
||||||
|
public Value delta;
|
||||||
|
public int events;
|
||||||
|
public AlarmState state;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncCounterNotifyEvent", has_type_id = false)]
|
||||||
|
public struct CounterNotifyEvent {
|
||||||
|
// TODO: other fields
|
||||||
|
public X.ID counter;
|
||||||
|
public Value wait_value;
|
||||||
|
public Value counter_value;
|
||||||
|
}
|
||||||
|
[CCode (cname = "XSyncAlarmNotifyEvent", has_type_id = false)]
|
||||||
|
public struct AlarmNotifyEvent {
|
||||||
|
// TODO: other fields
|
||||||
|
public X.ID alarm;
|
||||||
|
public Value counter_value;
|
||||||
|
public Value alarm_value;
|
||||||
|
public AlarmState state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: XSyncAlarmError
|
||||||
|
// TODO: XSyncCounterError
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncQueryExtension")]
|
||||||
|
public X.Status query_extension (X.Display dpy, out int event_base, out int error_base);
|
||||||
|
[CCode (cname = "XSyncInitialize")]
|
||||||
|
public X.Status initialize (X.Display dpy, out int major_version, out int minor_version);
|
||||||
|
[CCode (cname = "XSyncListSystemCounters")]
|
||||||
|
public SystemCounter *list_system_counters (X.Display dpy, out int n_counters);
|
||||||
|
[CCode (cname = "XSyncFreeSystemCounterList")]
|
||||||
|
public void free_system_counter_list (SystemCounter *counters);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncCreateCounter")]
|
||||||
|
public X.ID create_counter (X.Display dpy, Value initial_value);
|
||||||
|
[CCode (cname = "XSyncSetCounter")]
|
||||||
|
public X.Status set_counter (X.Display dpy, X.ID counter, Value value);
|
||||||
|
[CCode (cname = "XSyncChangeCounter")]
|
||||||
|
public X.Status change_counter (X.Display dpy, X.ID counter, Value value);
|
||||||
|
[CCode (cname = "XSyncDestroyCounter")]
|
||||||
|
public X.Status destroy_counter (X.Display dpy, X.ID counter);
|
||||||
|
[CCode (cname = "XSyncQueryCounter")]
|
||||||
|
public X.Status query_counter (X.Display dpy, X.ID counter, out Value value);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncAwait")]
|
||||||
|
public X.Status await (X.Display dpy, WaitCondition *wait_list, int n_conditions);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncCreateAlarm")]
|
||||||
|
public X.ID create_alarm (X.Display dpy, CA values_mask, ref AlarmAttributes values);
|
||||||
|
[CCode (cname = "XSyncDestroyAlarm")]
|
||||||
|
public X.Status destroy_alarm (X.Display dpy, X.ID alarm);
|
||||||
|
[CCode (cname = "XSyncQueryAlarm")]
|
||||||
|
public X.Status query_alarm (X.Display dpy, X.ID alarm, out AlarmAttributes values_return);
|
||||||
|
[CCode (cname = "XSyncChangeAlarm")]
|
||||||
|
public X.Status change_alarm (X.Display dpy, X.ID alarm, CA values_mask, ref AlarmAttributes values);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncSetPriority")]
|
||||||
|
public X.Status set_priority (X.Display dpy, X.ID alarm, int priority);
|
||||||
|
[CCode (cname = "XSyncGetPriority")]
|
||||||
|
public X.Status get_priority (X.Display dpy, X.ID alarm, out int priority);
|
||||||
|
|
||||||
|
[CCode (cname = "XSyncCreateFence")]
|
||||||
|
public X.ID create_fence (X.Display dpy, X.Drawable d, int initially_triggered);
|
||||||
|
[CCode (cname = "XSyncTriggerFence")]
|
||||||
|
public int trigger_fence (X.Display dpy, X.ID fence);
|
||||||
|
[CCode (cname = "XSyncResetFence")]
|
||||||
|
public int reset_fence (X.Display dpy, X.ID fence);
|
||||||
|
[CCode (cname = "XSyncDestroyFence")]
|
||||||
|
public int destroy_fence (X.Display dpy, X.ID fence);
|
||||||
|
[CCode (cname = "XSyncQueryFence")]
|
||||||
|
public int query_fence (X.Display dpy, X.ID fence, out int triggered);
|
||||||
|
[CCode (cname = "XSyncAwaitFence")]
|
||||||
|
public int await_fence (X.Display dpy, X.ID *fence_list, int n_fences);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue