Compare commits

...

68 Commits

Author SHA1 Message Date
Adrian Lucrèce Céleste
5c18ddb6cf [2.3.2-alpha] 2019-08-22 17:15:19 -04:00
Adrian Lucrèce Céleste
f1c570752b Merge pull request #413 from debauchee/revert-405-fix/build-scripts
Revert "Tidy up and fix lint errors in build scripts"
2019-08-22 17:11:02 -04:00
Adrian Lucrèce Céleste
70a4ece9e8 Revert "Tidy up and fix lint errors in build scripts" 2019-08-22 17:03:18 -04:00
Adrian Lucrèce Céleste
58f6c735ff Merge pull request #412 from maxiberta/rename-snap
Rename the snap as `barrier`.
2019-08-22 15:03:58 -04:00
Adrian Lucrèce Céleste
fca05b9163 Use standard mutex APIs instead of the home-grown wrapper (#410)
Use standard mutex APIs instead of the home-grown wrapper
2019-08-22 15:01:35 -04:00
Adrian Lucrèce Céleste
7bb541ea91 Merge pull request #411 from p12tic/rewrite-memory-management
Use explicit memory ownership in SocketMultiplexer
2019-08-22 15:01:21 -04:00
Adrian Lucrèce Céleste
ccfa10f2a0 Merge pull request #391 from EbonJaeger
Re-implement patch for horizontal scrolling and extra mouse buttons
2019-08-22 14:57:46 -04:00
Maximiliano Bertacchini
5812030f43 Rename the snap as barrier. 2019-08-22 15:55:12 -03:00
Adrian Lucrèce Céleste
e31ebc1b22 Merge pull request #408 from p12tic/fix-ssl-mem-leak
Fix memory leak during SSL socket shutdown
2019-08-22 12:54:27 -04:00
Adrian Lucrèce Céleste
69ea670c1f Fix retry timer not being unregistered properly (#409)
Fix retry timer not being unregistered properly
2019-08-22 12:54:19 -04:00
Povilas Kanapickas
3600f4b255 Fix retry timer not being unregistered properly
This is cherry-pick of 70ba53caf4 from symless/synergy-core
2019-08-22 18:11:03 +03:00
Adrian Lucrèce Céleste
4ec30b6ade Tidy up and fix lint errors in build scripts (#405)
Tidy up and fix lint errors in build scripts
2019-08-20 13:36:54 -04:00
Dom Rodriguez
452820eef7 Interim fix for failed macOS builds
Not ideal, but it might just work. Take two!

Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2019-08-20 18:29:17 +01:00
Dom Rodriguez
c685f0f231 Tidy up and fix lint errors in build scripts
I've tidied up the code in both of the build scripts used for *nix-like
systems, and the macOS/OSX specific build script helper.

This has been tested on Linux with no issues, but this PR will hopefully
indicate if the changes run without issues on macOS as well.

Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2019-08-20 18:08:03 +01:00
Adrian Lucrèce Céleste
cf3b86341a Merge pull request #404 from shymega/fix/cmake-qt
Fix: CMake now checks for required Qt5 libraries
2019-08-18 17:35:57 -04:00
Dom Rodriguez
6c88843771 Fix: CMake now checks for required Qt5 libraries
This won't fix #402 completely, but it *will* help mitigate similar
issues with Qt5 libraries during compilation in the future.
2019-08-18 22:29:19 +01:00
Adrian Lucrèce Céleste
dea143bfd7 Merge pull request #403 from shymega/fix/snap-flags
Snap: Change CMake builds to be of Release type
2019-08-18 17:26:55 -04:00
Dom Rodriguez
dcc45dd80e Snap: Change CMake builds to be of Release type 2019-08-18 22:24:32 +01:00
Adrian Lucrèce Céleste
7bcb74adc1 [Build[ update pre-build script to call VS2019 (#401)
[Build[ update pre-build script to call VS2019
2019-08-17 17:03:24 -04:00
Adrian Lucrèce Céleste
e9f6092172 [Build[ update pre-build script to call VS2019 2019-08-17 16:52:24 -04:00
Povilas Kanapickas
b0e415de03 Fix race condition in IArchString
Even though the calls to C functions are protected with a mutex, the
initialization and destruction of the mutex itself had race conditions.
2019-08-17 16:40:25 +03:00
Povilas Kanapickas
83d0639230 Use std::mutex instead of ArchMutex in IpcLogOutputter 2019-08-17 16:40:24 +03:00
Povilas Kanapickas
93c04bb2fa Use std::mutex instead of ArchMutex in IpcClientProxy 2019-08-17 16:40:23 +03:00
Povilas Kanapickas
36f3235f51 Use std::mutex instead of ArchMutex in IpcServer 2019-08-17 16:40:22 +03:00
Povilas Kanapickas
d9d39040ae Use std::mutex instead of ArchMutex in Log 2019-08-17 16:40:21 +03:00
Povilas Kanapickas
9df4741748 Use std::mutex instead of ArchMutex in EventQueue 2019-08-17 16:40:20 +03:00
Povilas Kanapickas
f71c68506e Use std::mutex instead of ArchMutex in ArchMultithreadPosix 2019-08-17 16:40:19 +03:00
Povilas Kanapickas
a841b2858f Make ownership of SocketMultiplexerJob explicit 2019-08-17 16:17:50 +03:00
Povilas Kanapickas
8dd6bc2c55 Make ownership of SocketMultiplexer explicit 2019-08-17 16:17:49 +03:00
Adrian Lucrèce Céleste
58d8f020dc [Version] bump to 2.3.1 for new release 2019-08-09 16:17:30 -04:00
Adrian Lucrèce Céleste
910f1f3ac1 Delete .travis.yml As We Switch To Azure Pipelines (#376)
Delete .travis.yml As We Switch To Azure Pipelines
2019-08-09 09:34:51 -04:00
walker0643
f7b7c55b53 Drop Travis CI 2019-08-09 09:31:31 -04:00
Evan Maddock
0cd2e6bb6c Use Windows helper function to check for Windows version
Signed-off-by: Evan Maddock <maddock.evan@vivaldi.net>
2019-08-06 17:02:37 -04:00
Evan Maddock
00c18b4c92 Used the wrong key button by accident
Signed-off-by: Evan Maddock <maddock.evan@vivaldi.net>
2019-08-06 15:23:22 -04:00
Evan Maddock
9f15b1bcf2 Reimplement patch for horizontal scrolling and extra mouse buttons
Signed-off-by: Evan Maddock <maddock.evan@vivaldi.net>
2019-08-05 21:59:43 -04:00
Adrian Lucrèce Céleste
c6ff6a6de6 Merge pull request #374 from TafThorne/patch-1
Reference Only Microsoft Azue Pipelines In Readme.md
2019-08-05 12:07:06 -04:00
Adrian Lucrèce Céleste
0ddd38ece1 Merge pull request #373 from shymega/feature/compile_commands_cmake
Feature: CMake now generates compile_commands.json
2019-08-04 18:02:21 -04:00
Thomas Thorne
3e3e183e75 Delete .travis.yml As We Switch To Azure Pipelines
Azure Pipelines have been made to work well enough for this project.  All other CI systems are to be disabled as mentioned dunder #308 

Delete the .travis.yml file now that it is not longer needed.  It can be recovered from git history if we ever wish to resurrect it.  

A separate action will need to be taken by someone with administrator access to the present https://travis-ci.org/debauchee/barrier project to unlink from the system there.
2019-07-26 10:52:01 +01:00
Thomas Thorne
6dc59d14a3 Reference Only Microsoft Azue Pipelines In Readme.md
We plan to remove all the CI pipeline apart from Microsoft Azue Pipelines.  This was documented under #308 after the Azure Pipeline system was successfully integrated under #303 and shown to provide all the build targetes we needed.

As there are presently have 4 seperate main build targes.  As well as giving the overall master branch status in the Readme (which forms part of the main page on github.com) also show the seperate build status.  This makes it clear if a single part fails and gives an obvious indicator that this project works for Linux, Mac and Windows.
2019-07-26 10:24:37 +01:00
Dom Rodriguez
f399c8c642 Feature: CMake now generates compile_commands.json
This commit adds suppotr for generating a 'compile commands' JSON
file. This provides fairly sufficient autocomplete support for most text
editors, such as (Neo)vim and VS Code. It specifies include paths, and
the compiler arguments used to compile each source file.

Signed-off-by: Dom Rodriguez <shymega@shymega.org.uk>
2019-07-25 13:46:00 +01:00
Adrian Lucrèce Céleste
ea0717b5f5 Merge pull request #368 from maxiberta/snap-fix-version-script
Fix snap version-control script for local LXD builds
2019-07-23 19:00:26 -04:00
Maximiliano Bertacchini
4e83ea7f9a Fix snap version-control script for local lxd builds. 2019-07-23 18:44:12 -03:00
Maximiliano Bertacchini
f23a2ecec3 Use appstream metadata from flathub. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
30bc1948c6 Set snap icon and license. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
bad0373bbb Add desktop entry with an app icon. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
7a2c3f7741 Update build-packages and stage-packages. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
e2f59c7475 Drop custom qt5, use distro provided one. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
49210e1ea4 Add commands: barrier, barrierc, barriers. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
1c5a95f810 Fix interface plugs. 2019-07-10 15:38:01 -04:00
Maximiliano Bertacchini
1c398dcd66 Use version from git tag. 2019-07-10 15:38:01 -04:00
Patrizio Tufarolo
40ee389296 Fixed quote key on US International keyboard
Fixes single quote key on US international keyboard, backported from symless/synergy-core#6448
2019-07-10 09:28:22 -04:00
Nelson Chen
af444a6932 Ensure Inno Setup 5 is installed in Azure Pipelines 2019-07-09 08:25:20 -04:00
Adrian Lucrèce Céleste
8e8b38b493 [Cmake] bump version to 2.3.0 2019-06-27 21:33:34 -04:00
Adrian Lucrèce Céleste
8e1a5921f6 [Release] Bump up to a new release version 2019-06-27 21:18:24 -04:00
Adrian Lucrèce Céleste
1e118ee8e8 [README] Add FaQ to the bottom 2019-06-26 18:07:19 -04:00
Chun Wang
0f5cdecf51 Fix #232 MACOS serious config file errors - hotkeys totally broken 2019-06-14 12:22:56 -07:00
Adrian Lucrèce Céleste
6c19a87f63 Add Q/A about 32-bit windows
Clarify that 32-bit editions of windows are not supported.
2019-06-14 09:34:18 -04:00
Adrian Lucrèce Céleste
b3374a07ed Add a quick Q/A about what OSes are supported 2019-06-14 09:32:08 -04:00
Adrian Lucrèce Céleste
b09a3985d0 fix #163 2019-05-30 09:30:38 -04:00
Nelson Chen
40f94c6477 Upgrade QLI Installer and use Cal's Qt Mirror
This should provide more reliable Windows builds in CI.
2019-05-26 13:22:10 -04:00
Nelson Chen
0be33c3032 Publish Mac Artifacts 2019-05-26 13:20:00 -04:00
Nelson Chen
500a82824f Build Release version of Barrier on Mac 2019-05-26 13:20:00 -04:00
Nelson Chen
cd8176e69f Install Pinned Qt and OpenSSL on Mac 2019-05-26 13:20:00 -04:00
Nelson Chen
ae8ef7f4f2 Prefix Windows artifact names with 'Windows' on Azure Pipelines (#319) 2019-05-26 13:18:55 -04:00
Nelson Chen
6074f9b648 Update Apt on Linux before installing dependencies on Azure Pipelines (#321) 2019-05-26 13:16:41 -04:00
pack
a3804c4915 typo fix (#311) 2019-05-17 22:54:42 -04:00
Adrian Lucrèce Céleste
e4392b51b4 📝 add release link and contact info (#310)
📝 add release link and contact info
2019-05-17 19:30:02 -04:00
Povilas Kanapickas
71f2ca7c35 Fix memory leak during socket shutdown 2019-03-13 10:14:29 +03:00
46 changed files with 548 additions and 556 deletions

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ CMakeCache.txt
.vscode/
# Transient in-project-directory dependencies
/deps/
/out/build/x64-Debug

View File

@@ -1,34 +0,0 @@
language: cpp
matrix:
include:
- os: linux
sudo: false
dist: trusty
addons:
apt:
packages:
- libxtst-dev
- qtdeclarative5-dev
- libavahi-compat-libdnssd-dev
script: sh -x ./clean_build.sh
- os: osx
osx_image: xcode9
script:
- export COLUMNS=80
- curl -LO https://raw.githubusercontent.com/GiovanniBussi/macports-ci/master/macports-ci
- chmod +x ./macports-ci
- ./macports-ci install
- PATH="$PATH:/opt/local/bin"
- sudo port -N install qt5-qtbase openssl
- sh -x ./clean_build.sh
- os: osx
osx_image: xcode9
script:
- brew update
- brew install qt openssl
- sh -x ./clean_build.sh
install: true

View File

@@ -1,7 +1,7 @@
#
# Barrier build parameters
#
BARRIER_VERSION_MAJOR = 1
BARRIER_VERSION_MINOR = 9
BARRIER_VERSION_PATCH = 0
BARRIER_VERSION_MAJOR = 2
BARRIER_VERSION_MINOR = 3
BARRIER_VERSION_PATCH = 2
BARRIER_VERSION_STAGE = snapshot

View File

@@ -21,6 +21,7 @@ project (barrier C CXX)
option (BARRIER_BUILD_GUI "Build the GUI" ON)
option (BARRIER_BUILD_INSTALLER "Build the installer" ON)
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_EXTENSIONS OFF)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -348,6 +349,12 @@ else()
set (OPENSSL_LIBS ${lib_ssl} ${lib_crypto})
endif()
# Check we have the *required* Qt5 libs.
find_package(Qt5Core REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5Widgets REQUIRED)
#
# Configure_file... but for directories, recursively.
#

View File

@@ -1,15 +1,21 @@
# Barrier
Eliminate the barrier between your machines.
Find [releaes here](https://github.com/debauchee/barrier/releases).
Find [releases here](https://github.com/debauchee/barrier/releases).
### Contact info:
- `#barrier` on freenode
Master branch build status: &nbsp; [![Build Status](https://travis-ci.org/debauchee/barrier.svg?branch=master)](https://travis-ci.org/debauchee/barrier)
#### CI Build Status
Azure Pipelines build status: [![Build Status](https://dev.azure.com/debauchee/Barrier/_apis/build/status/debauchee.barrier?branchName=master)](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
Master branch overall build status: [![Build Status](https://dev.azure.com/debauchee/Barrier/_apis/build/status/debauchee.barrier?branchName=master)](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
* Linux Build Status: [![Build Status](https://dev.azure.com/debauchee/Barrier/_apis/build/status/debauchee.barrier?branchName=master&jobName=Linux%20Build)](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
* Mac Build Status: [![Build Status](https://dev.azure.com/debauchee/Barrier/_apis/build/status/debauchee.barrier?branchName=master&jobName=Mac%20Build)](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
* Windows Debug Build Status: [![Build Status](https://dev.azure.com/debauchee/Barrier/_apis/build/status/debauchee.barrier?branchName=master&jobName=Windows%20Build&configuration=Windows%20Build%20Debug)](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
* Windows Release Build Status: [![Build Status](https://dev.azure.com/debauchee/Barrier/_apis/build/status/debauchee.barrier?branchName=master&jobName=Windows%20Build&configuration=Windows%20Build%20Release%20with%20Release%20Installer)](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)
Our CI Builds are provided by Microsoft Azure Pipelines.
### What is it?
@@ -36,3 +42,21 @@ For short and simple questions or to just say hello find us on the Freenode IRC
### Contributions
At this time we are looking for developers to help fix the issues found in the issue tracker. Submit pull requests once you've polished up your patch and we'll review and possibly merge it.
### FAQ
Q: Does drag and drop work on linux?
A: No
Q: What OSes are supported?
A:
- Windows 7, 8, 8.1, and 10
- MacOS/OS X
- Linux
- FreeBSD
Q: Are 32-bit versions of Windows supported?
A: No

View File

@@ -48,7 +48,10 @@ jobs:
displayName: Publish Completed Build Directory Archive Build Artifact
inputs:
pathtoPublish: $(Build.ArtifactStagingDirectory)\$(CI_ENV_BUILD_TYPE).zip
artifactName: $(CI_ENV_BUILD_TYPE)
artifactName: Windows $(CI_ENV_BUILD_TYPE)
- script: choco install innosetup --version 5.6.1.20190126 --allow-downgrade
displayName: Ensure desired version of Inno Setup is installed.
condition: eq(variables['CI_ENV_BUILD_TYPE'], 'Release')
- script: build_installer.bat
displayName: Build Installer
condition: eq(variables['CI_ENV_BUILD_TYPE'], 'Release')
@@ -57,13 +60,14 @@ jobs:
condition: eq(variables['CI_ENV_BUILD_TYPE'], 'Release')
inputs:
pathtoPublish: build\installer-inno\bin
artifactName: Release Installer
artifactName: Windows Release Installer
- job: LinuxBuild
displayName: Linux Build
pool:
vmImage: 'ubuntu-16.04'
steps:
- script: sudo apt-get update -y
- script: sudo apt-get install -y libxtst-dev qtdeclarative5-dev libavahi-compat-libdnssd-dev libcurl4-openssl-dev
displayName: Install Dependencies
- script: sh -x ./clean_build.sh
@@ -73,10 +77,21 @@ jobs:
displayName: Mac Build
pool:
vmImage: 'macOS-10.14'
strategy:
matrix:
Release:
B_BUILD_TYPE: Release
BARRIER_VERSION_STAGE: Release
steps:
- script: brew update
displayName: Update brew
- script: brew install qt openssl
displayName: Install Dependencies
- script: brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/aac86fc018c48d7b6f23a2e7535276899774567a/Formula/qt.rb
displayName: Installed Pinned Qt
- script: brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/aac86fc018c48d7b6f23a2e7535276899774567a/Formula/openssl.rb
displayName: Installed Pinned OpenSSL
- script: sh -x ./clean_build.sh
displayName: Clean Build
- task: PublishBuildArtifacts@1
displayName: Publish Release DMG
condition: eq(variables['B_BUILD_TYPE'], 'Release')
inputs:
pathtoPublish: build/bundle
artifactName: Mac Release Disk Image and App

View File

@@ -1,6 +1,6 @@
$ErrorActionPreference = "Stop"
$qli_install_version = '2019.05.12.4'
$qli_install_version = '2019.05.26.1'
$qt_version = '5.12.3'
New-Item -Force -ItemType Directory -Path ".\deps\"
@@ -21,5 +21,6 @@ Write-Output 'Installed QLI Installer Dependencies'
Write-Output 'Starting QT Installer'
$Env:QLI_OUT_DIR = ".\deps\Qt\Qt$qt_version"
$Env:QLI_BASE_URL = "http://mirrors.ocf.berkeley.edu/qt/online/qtsdkrepository/"
python .\deps\qli-installer\qli-installer.py $qt_version windows desktop win64_msvc2017_64
Write-Output 'Installed QT Installer'

View File

@@ -1,8 +1,8 @@
cmake_minimum_required (VERSION 3.4)
set (BARRIER_VERSION_MAJOR 2)
set (BARRIER_VERSION_MINOR 2)
set (BARRIER_VERSION_PATCH 0)
set (BARRIER_VERSION_MINOR 3)
set (BARRIER_VERSION_PATCH 2)
#
# Barrier Version

View File

@@ -1 +1 @@
%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat"
%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat"

View File

@@ -1,104 +1,84 @@
name: barrier-kvm # the Barrier Snappy for Linux / not tested on MAC yet
base: core18
version: '2.2.0' # 03/2019
summary: Eliminate the barrier between your machines.
description: |
Barrier is KVM software forked from Symless's synergy 1.9 codebase.
Synergy was a commercialized reimplementation of the original
CosmoSynergy written by Chris Schoeneman.
name: barrier
base: core18
version: master
version-script: git describe --tags --long | sed "s/^v//"
adopt-info: appstream-flathub
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots
icon: res/barrier.svg
license: GPL-2.0
apps:
barrier-kvm:
barrier:
command: desktop-launch barrier #first run might take longer
plugs:
gnome-3-26-1604:
interface: content
target: gnome-platform
default-provider: gnome-3-26-1604:gnome-3-26-1604
plugs: [gnome-3-26-1604]
plugs: [x11]
parts: [qt5conf]
desktop: usr/share/applications/barrier.desktop
common-id: com.github.debauchee.barrier
plugs: &plugs
- desktop
- desktop-legacy
- home
- joystick
- network
- opengl
- pulseaudio
- screen-inhibit-control
- unity7
- wayland
- x11
barrierc:
command: desktop-launch barrierc
plugs: *plugs
barriers:
command: desktop-launch barriers
plugs: *plugs
parts:
desktop:
plugin: nil
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
desktop-qt5:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: qt
plugin: make
make-parameters: ["FLAVOR=qt5"]
build-packages:
- build-essential
- qtbase5-dev
- dpkg-dev
stage-packages:
- libxkbcommon0
- ttf-ubuntu-font-family
- dmz-cursor-theme
- light-themes
- adwaita-icon-theme
- gnome-themes-standard
- shared-mime-info
- libqt5gui5
- libgdk-pixbuf2.0-0
- libqt5svg5 # for loading icon themes which are svg
- try: [appmenu-qt5] # not available on core18
- locales-all
- xdg-user-dirs
- fcitx-frontend-qt5
qt5:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: qt
plugin: make
make-parameters: ["FLAVOR=qt5"]
build-packages:
- qtbase5-dev
- dpkg-dev
stage-packages:
- libxkbcommon0
- ttf-ubuntu-font-family
- dmz-cursor-theme
- light-themes
- adwaita-icon-theme
- gnome-themes-standard
- shared-mime-info
- libqt5gui5
- libgdk-pixbuf2.0-0
- libqt5svg5 # for loading icon themes which are svg
- try: [appmenu-qt5] # not available on core18
- locales-all
barrier-kvm:
source: https://github.com/payomagic/barrier.git
barrier:
source: .
plugin: cmake
configflags:
- "-DCMAKE_INSTALL_PREFIX=/usr"
- "-DCMAKE_BUILD_TYPE=Release"
build-packages:
- g++
- gcc
- make
- xorg-dev
- xorg-dev
- libcurl4-openssl-dev
- libavahi-compat-libdnssd-dev
- libssl-dev
- libx11-dev
- libqt4-dev
- qtbase5-dev
- qt5-style-plugins
- qt5ct
stage-packages:
- libxinerama-dev
- libxinerama1
- libxrandr-dev
- libxrandr2
- libxrender-dev
- libxrender1
- libxtst-dev
- qtdeclarative5-dev
- libavahi-compat-libdnssd-dev
- libqt5gui5
- libavahi-common-dev
- libqt5svg5-dev
stage-packages:
- libxinerama1
- libxrandr2
- libxrender1
- libqt5gui5
- libqt5x11extras5
- libqt5svg5
- libqt5svg5-dev
- qt5ct
- libxtst6
- libavahi-client3
- libavahi-common3
- libavahi-compat-libdnssd1
after: [desktop-qt5]
fix-icon:
plugin: nil
override-build:
sed -i 's|Icon=barrier|Icon=/usr/share/icons/hicolor/scalable/apps/barrier.svg|' $SNAPCRAFT_STAGE/usr/share/applications/barrier.desktop
after: [barrier]
appstream-flathub:
plugin: dump
source: https://github.com/flathub/com.github.debauchee.barrier.git
parse-info: [com.github.debauchee.barrier.appdata.xml]

View File

@@ -24,7 +24,9 @@
#include <cstring>
#include <cstdlib>
static ArchMutex s_mutex = NULL;
#include <mutex>
std::mutex s_mutex;
//
// use C library non-reentrant multibyte conversion with mutex
@@ -32,16 +34,14 @@ static ArchMutex s_mutex = NULL;
IArchString::~IArchString()
{
if (s_mutex != NULL) {
ARCH->closeMutex(s_mutex);
s_mutex = NULL;
}
}
int
IArchString::convStringWCToMB(char* dst,
const wchar_t* src, UInt32 n, bool* errors)
{
std::lock_guard<std::mutex> lock(s_mutex);
ptrdiff_t len = 0;
bool dummyErrors;
@@ -49,12 +49,6 @@ IArchString::convStringWCToMB(char* dst,
errors = &dummyErrors;
}
if (s_mutex == NULL) {
s_mutex = ARCH->newMutex();
}
ARCH->lockMutex(s_mutex);
if (dst == NULL) {
char dummy[MB_LEN_MAX];
for (const wchar_t* scan = src; n > 0; ++scan, --n) {
@@ -89,7 +83,6 @@ IArchString::convStringWCToMB(char* dst,
}
len = dst - dst0;
}
ARCH->unlockMutex(s_mutex);
return (int)len;
}
@@ -98,6 +91,8 @@ int
IArchString::convStringMBToWC(wchar_t* dst,
const char* src, UInt32 n_param, bool* errors)
{
std::lock_guard<std::mutex> lock(s_mutex);
ptrdiff_t n = (ptrdiff_t)n_param; // fix compiler warning
ptrdiff_t len = 0;
wchar_t dummy;
@@ -107,12 +102,6 @@ IArchString::convStringMBToWC(wchar_t* dst,
errors = &dummyErrors;
}
if (s_mutex == NULL) {
s_mutex = ARCH->newMutex();
}
ARCH->lockMutex(s_mutex);
if (dst == NULL) {
for (const char* scan = src; n > 0; ) {
ptrdiff_t mblen = mbtowc(&dummy, scan, n);
@@ -184,7 +173,6 @@ IArchString::convStringMBToWC(wchar_t* dst,
}
len = dst - dst0;
}
ARCH->unlockMutex(s_mutex);
return (int)len;
}

View File

@@ -114,9 +114,6 @@ ArchMultithreadPosix::ArchMultithreadPosix() :
m_signalUserData[i] = NULL;
}
// create mutex for thread list
m_threadMutex = newMutex();
// create thread for calling (main) thread and add it to our
// list. no need to lock the mutex since we're the only thread.
m_mainThread = new ArchThreadImpl;
@@ -153,26 +150,22 @@ ArchMultithreadPosix::~ArchMultithreadPosix()
{
assert(s_instance != NULL);
closeMutex(m_threadMutex);
s_instance = NULL;
}
void
ArchMultithreadPosix::setNetworkDataForCurrentThread(void* data)
{
lockMutex(m_threadMutex);
std::lock_guard<std::mutex> lock(m_threadMutex);
ArchThreadImpl* thread = find(pthread_self());
thread->m_networkData = data;
unlockMutex(m_threadMutex);
}
void*
ArchMultithreadPosix::getNetworkDataForThread(ArchThread thread)
{
lockMutex(m_threadMutex);
void* data = thread->m_networkData;
unlockMutex(m_threadMutex);
return data;
std::lock_guard<std::mutex> lock(m_threadMutex);
return thread->m_networkData;
}
ArchMultithreadPosix*
@@ -356,7 +349,8 @@ ArchMultithreadPosix::newThread(ThreadFunc func, void* data)
#endif
}
lockMutex(m_threadMutex);
// note that the child thread will wait until we release this mutex
std::lock_guard<std::mutex> lock(m_threadMutex);
// create thread impl for new thread
ArchThreadImpl* thread = new ArchThreadImpl;
@@ -387,18 +381,15 @@ ArchMultithreadPosix::newThread(ThreadFunc func, void* data)
refThread(thread);
}
// note that the child thread will wait until we release this mutex
unlockMutex(m_threadMutex);
return thread;
}
ArchThread
ArchMultithreadPosix::newCurrentThread()
{
lockMutex(m_threadMutex);
std::lock_guard<std::mutex> lock(m_threadMutex);
ArchThreadImpl* thread = find(pthread_self());
unlockMutex(m_threadMutex);
assert(thread != NULL);
return thread;
}
@@ -416,10 +407,11 @@ ArchMultithreadPosix::closeThread(ArchThread thread)
}
// remove thread from list
lockMutex(m_threadMutex);
assert(findNoRef(thread->m_thread) == thread);
erase(thread);
unlockMutex(m_threadMutex);
{
std::lock_guard<std::mutex> lock(m_threadMutex);
assert(findNoRef(thread->m_thread) == thread);
erase(thread);
}
// done with thread
delete thread;
@@ -440,12 +432,14 @@ ArchMultithreadPosix::cancelThread(ArchThread thread)
// set cancel and wakeup flags if thread can be cancelled
bool wakeup = false;
lockMutex(m_threadMutex);
if (!thread->m_exited && !thread->m_cancelling) {
thread->m_cancel = true;
wakeup = true;
{
std::lock_guard<std::mutex> lock(m_threadMutex);
if (!thread->m_exited && !thread->m_cancelling) {
thread->m_cancel = true;
wakeup = true;
}
}
unlockMutex(m_threadMutex);
// force thread to exit system calls if wakeup is true
if (wakeup) {
@@ -465,9 +459,11 @@ void
ArchMultithreadPosix::testCancelThread()
{
// find current thread
lockMutex(m_threadMutex);
ArchThreadImpl* thread = findNoRef(pthread_self());
unlockMutex(m_threadMutex);
ArchThreadImpl* thread = nullptr;
{
std::lock_guard<std::mutex> lock(m_threadMutex);
thread = findNoRef(pthread_self());
}
// test cancel on thread
testCancelThreadImpl(thread);
@@ -478,22 +474,23 @@ ArchMultithreadPosix::wait(ArchThread target, double timeout)
{
assert(target != NULL);
lockMutex(m_threadMutex);
ArchThreadImpl* self = nullptr;
// find current thread
ArchThreadImpl* self = findNoRef(pthread_self());
{
std::lock_guard<std::mutex> lock(m_threadMutex);
// ignore wait if trying to wait on ourself
if (target == self) {
unlockMutex(m_threadMutex);
return false;
// find current thread
self = findNoRef(pthread_self());
// ignore wait if trying to wait on ourself
if (target == self) {
return false;
}
// ref the target so it can't go away while we're watching it
refThread(target);
}
// ref the target so it can't go away while we're watching it
refThread(target);
unlockMutex(m_threadMutex);
try {
// do first test regardless of timeout
testCancelThreadImpl(self);
@@ -538,19 +535,15 @@ ArchMultithreadPosix::isSameThread(ArchThread thread1, ArchThread thread2)
bool
ArchMultithreadPosix::isExitedThread(ArchThread thread)
{
lockMutex(m_threadMutex);
bool exited = thread->m_exited;
unlockMutex(m_threadMutex);
return exited;
std::lock_guard<std::mutex> lock(m_threadMutex);
return thread->m_exited;
}
void*
ArchMultithreadPosix::getResultOfThread(ArchThread thread)
{
lockMutex(m_threadMutex);
void* result = thread->m_result;
unlockMutex(m_threadMutex);
return result;
std::lock_guard<std::mutex> lock(m_threadMutex);
return thread->m_result;
}
IArchMultithread::ThreadID
@@ -563,16 +556,15 @@ void
ArchMultithreadPosix::setSignalHandler(
ESignal signal, SignalFunc func, void* userData)
{
lockMutex(m_threadMutex);
std::lock_guard<std::mutex> lock(m_threadMutex);
m_signalFunc[signal] = func;
m_signalUserData[signal] = userData;
unlockMutex(m_threadMutex);
}
void
ArchMultithreadPosix::raiseSignal(ESignal signal)
{
lockMutex(m_threadMutex);
std::lock_guard<std::mutex> lock(m_threadMutex);
if (m_signalFunc[signal] != NULL) {
m_signalFunc[signal](signal, m_signalUserData[signal]);
pthread_kill(m_mainThread->m_thread, SIGWAKEUP);
@@ -580,7 +572,6 @@ ArchMultithreadPosix::raiseSignal(ESignal signal)
else if (signal == kINTERRUPT || signal == kTERMINATE) {
ARCH->cancelThread(m_mainThread);
}
unlockMutex(m_threadMutex);
}
void
@@ -677,15 +668,15 @@ ArchMultithreadPosix::testCancelThreadImpl(ArchThreadImpl* thread)
{
assert(thread != NULL);
std::lock_guard<std::mutex> lock(m_threadMutex);
// update cancel state
lockMutex(m_threadMutex);
bool cancel = false;
if (thread->m_cancel && !thread->m_cancelling) {
thread->m_cancelling = true;
thread->m_cancel = false;
cancel = true;
}
unlockMutex(m_threadMutex);
// unwind thread's stack if cancelling
if (cancel) {
@@ -717,8 +708,9 @@ ArchMultithreadPosix::doThreadFunc(ArchThread thread)
setPriorityOfThread(thread, 1);
// wait for parent to initialize this object
lockMutex(m_threadMutex);
unlockMutex(m_threadMutex);
{
std::lock_guard<std::mutex> lock(m_threadMutex);
}
void* result = NULL;
try {
@@ -731,18 +723,20 @@ ArchMultithreadPosix::doThreadFunc(ArchThread thread)
}
catch (...) {
// note -- don't catch (...) to avoid masking bugs
lockMutex(m_threadMutex);
thread->m_exited = true;
unlockMutex(m_threadMutex);
{
std::lock_guard<std::mutex> lock(m_threadMutex);
thread->m_exited = true;
}
closeThread(thread);
throw;
}
// thread has exited
lockMutex(m_threadMutex);
thread->m_result = result;
thread->m_exited = true;
unlockMutex(m_threadMutex);
{
std::lock_guard<std::mutex> lock(m_threadMutex);
thread->m_result = result;
thread->m_exited = true;
}
// done with thread
closeThread(thread);

View File

@@ -22,6 +22,7 @@
#include "common/stdlist.h"
#include <pthread.h>
#include <mutex>
#define ARCH_MULTITHREAD ArchMultithreadPosix
@@ -104,7 +105,7 @@ private:
bool m_newThreadCalled;
ArchMutex m_threadMutex;
std::mutex m_threadMutex;
ArchThread m_mainThread;
ThreadList m_threadList;
ThreadID m_nextID;

View File

@@ -200,7 +200,7 @@ App::initApp(int argc, const char** argv)
void
App::initIpcClient()
{
m_ipcClient = new IpcClient(m_events, m_socketMultiplexer);
m_ipcClient = new IpcClient(m_events, m_socketMultiplexer.get());
m_ipcClient->connect();
m_events->adoptHandler(

View File

@@ -23,7 +23,9 @@
#include "base/String.h"
#include "base/Log.h"
#include "base/EventQueue.h"
#include "net/SocketMultiplexer.h"
#include "common/common.h"
#include <memory>
#if SYSAPI_WIN32
#include "barrier/win32/AppUtilWindows.h"
@@ -95,8 +97,8 @@ public:
virtual IEventQueue* getEvents() const { return m_events; }
void setSocketMultiplexer(SocketMultiplexer* sm) { m_socketMultiplexer = sm; }
SocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
void setSocketMultiplexer(std::unique_ptr<SocketMultiplexer>&& sm) { m_socketMultiplexer = std::move(sm); }
SocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer.get(); }
void setEvents(EventQueue& events) { m_events = &events; }
@@ -119,7 +121,7 @@ private:
CreateTaskBarReceiverFunc m_createTaskBarReceiver;
ARCH_APP_UTIL m_appUtil;
IpcClient* m_ipcClient;
SocketMultiplexer* m_socketMultiplexer;
std::unique_ptr<SocketMultiplexer> m_socketMultiplexer;
};
class MinimalApp : public App {

View File

@@ -443,8 +443,7 @@ ClientApp::mainLoop()
{
// create socket multiplexer. this must happen after daemonization
// on unix because threads evaporate across a fork().
SocketMultiplexer multiplexer;
setSocketMultiplexer(&multiplexer);
setSocketMultiplexer(std::make_unique<SocketMultiplexer>());
// start client, etc
appUtil().startNode();

View File

@@ -1104,6 +1104,7 @@ KeyMap::getDeadKey(KeyID key)
case '`':
return kKeyDeadGrave;
case '\'':
case 0xb4u:
return kKeyDeadAcute;

View File

@@ -302,8 +302,8 @@ void
ServerApp::stopRetryTimer()
{
if (m_timer != NULL) {
m_events->removeHandler(Event::kTimer, m_timer);
m_events->deleteTimer(m_timer);
m_events->removeHandler(Event::kTimer, NULL);
m_timer = NULL;
}
}
@@ -713,8 +713,7 @@ ServerApp::mainLoop()
{
// create socket multiplexer. this must happen after daemonization
// on unix because threads evaporate across a fork().
SocketMultiplexer multiplexer;
setSocketMultiplexer(&multiplexer);
setSocketMultiplexer(std::make_unique<SocketMultiplexer>());
// if configuration has no screens then add this system
// as the default

View File

@@ -32,10 +32,13 @@ static const ButtonID kButtonNone = 0;
static const ButtonID kButtonLeft = 1;
static const ButtonID kButtonMiddle = 2;
static const ButtonID kButtonRight = 3;
// mouse button 4
static const ButtonID kButtonExtra0 = 4;
// mouse button 5
static const ButtonID kButtonExtra1 = 5;
static const ButtonID kMacButtonRight = 2;
static const ButtonID kMacButtonMiddle = 3;
//@}
static const UInt8 NumButtonIDs = 5;
static const UInt8 NumButtonIDs = 6;

View File

@@ -90,7 +90,6 @@ EventQueue::EventQueue() :
m_readyMutex(new Mutex),
m_readyCondVar(new CondVar<bool>(m_readyMutex, false))
{
m_mutex = ARCH->newMutex();
ARCH->setSignalHandler(Arch::kINTERRUPT, &interrupt, this);
ARCH->setSignalHandler(Arch::kTERMINATE, &interrupt, this);
m_buffer = new SimpleEventQueueBuffer;
@@ -104,7 +103,6 @@ EventQueue::~EventQueue()
ARCH->setSignalHandler(Arch::kINTERRUPT, NULL, NULL);
ARCH->setSignalHandler(Arch::kTERMINATE, NULL, NULL);
ARCH->closeMutex(m_mutex);
}
void
@@ -136,7 +134,7 @@ EventQueue::loop()
Event::Type
EventQueue::registerTypeOnce(Event::Type& type, const char* name)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
if (type == Event::kUnknown) {
m_typeMap.insert(std::make_pair(m_nextType, name));
m_nameMap.insert(std::make_pair(name, m_nextType));
@@ -176,7 +174,7 @@ EventQueue::getTypeName(Event::Type type)
void
EventQueue::adoptBuffer(IEventQueueBuffer* buffer)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
LOG((CLOG_DEBUG "adopting new buffer"));
@@ -261,7 +259,7 @@ retry:
case IEventQueueBuffer::kUser:
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
event = removeEvent(dataID);
return true;
}
@@ -316,7 +314,7 @@ EventQueue::addEvent(const Event& event)
void
EventQueue::addEventToBuffer(const Event& event)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
// store the event's data locally
UInt32 eventID = saveEvent(event);
@@ -338,7 +336,7 @@ EventQueue::newTimer(double duration, void* target)
if (target == NULL) {
target = timer;
}
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
m_timers.insert(timer);
// initial duration is requested duration plus whatever's on
// the clock currently because the latter will be subtracted
@@ -357,7 +355,7 @@ EventQueue::newOneShotTimer(double duration, void* target)
if (target == NULL) {
target = timer;
}
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
m_timers.insert(timer);
// initial duration is requested duration plus whatever's on
// the clock currently because the latter will be subtracted
@@ -370,7 +368,7 @@ EventQueue::newOneShotTimer(double duration, void* target)
void
EventQueue::deleteTimer(EventQueueTimer* timer)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
for (TimerQueue::iterator index = m_timerQueue.begin();
index != m_timerQueue.end(); ++index) {
if (index->getTimer() == timer) {
@@ -388,7 +386,7 @@ EventQueue::deleteTimer(EventQueueTimer* timer)
void
EventQueue::adoptHandler(Event::Type type, void* target, IEventJob* handler)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
IEventJob*& job = m_handlers[target][type];
delete job;
job = handler;
@@ -399,7 +397,7 @@ EventQueue::removeHandler(Event::Type type, void* target)
{
IEventJob* handler = NULL;
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
HandlerTable::iterator index = m_handlers.find(target);
if (index != m_handlers.end()) {
TypeHandlerTable& typeHandlers = index->second;
@@ -418,7 +416,7 @@ EventQueue::removeHandlers(void* target)
{
std::vector<IEventJob*> handlers;
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
HandlerTable::iterator index = m_handlers.find(target);
if (index != m_handlers.end()) {
// copy to handlers array and clear table for target
@@ -447,7 +445,7 @@ EventQueue::isEmpty() const
IEventJob*
EventQueue::getHandler(Event::Type type, void* target) const
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
HandlerTable::const_iterator index = m_handlers.find(target);
if (index != m_handlers.end()) {
const TypeHandlerTable& typeHandlers = index->second;

View File

@@ -28,10 +28,9 @@
#include "common/stdset.h"
#include "base/NonBlockingStream.h"
#include <mutex>
#include <queue>
class Mutex;
//! Event queue
/*!
An event queue that implements the platform independent parts and
@@ -114,7 +113,7 @@ private:
typedef std::map<void*, TypeHandlerTable> HandlerTable;
int m_systemTarget;
ArchMutex m_mutex;
mutable std::mutex m_mutex;
// registered events
Event::Type m_nextType;

View File

@@ -63,9 +63,6 @@ Log::Log()
{
assert(s_log == NULL);
// create mutex for multithread safe operation
m_mutex = ARCH->newMutex();
// other initalization
m_maxPriority = g_defaultMaxPriority;
m_maxNewlineLength = 0;
@@ -90,7 +87,6 @@ Log::~Log()
index != m_alwaysOutputters.end(); ++index) {
delete *index;
}
ARCH->closeMutex(m_mutex);
}
Log*
@@ -214,7 +210,7 @@ Log::insert(ILogOutputter* outputter, bool alwaysAtHead)
{
assert(outputter != NULL);
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
if (alwaysAtHead) {
m_alwaysOutputters.push_front(outputter);
}
@@ -237,7 +233,7 @@ Log::insert(ILogOutputter* outputter, bool alwaysAtHead)
void
Log::remove(ILogOutputter* outputter)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
m_outputters.remove(outputter);
m_alwaysOutputters.remove(outputter);
}
@@ -245,7 +241,7 @@ Log::remove(ILogOutputter* outputter)
void
Log::pop_front(bool alwaysAtHead)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
OutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
if (!list->empty()) {
delete list->front();
@@ -271,14 +267,14 @@ Log::setFilter(const char* maxPriority)
void
Log::setFilter(int maxPriority)
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
m_maxPriority = maxPriority;
}
int
Log::getFilter() const
{
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
return m_maxPriority;
}
@@ -289,7 +285,7 @@ Log::output(ELevel priority, char* msg)
assert(msg != NULL);
if (!msg) return;
ArchMutexLock lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
OutputterList::const_iterator i;

View File

@@ -24,6 +24,7 @@
#include "common/stdlist.h"
#include <stdarg.h>
#include <mutex>
#define CLOG (Log::getInstance())
#define BYE "\nTry `%s --help' for more information."
@@ -132,7 +133,7 @@ private:
static Log* s_log;
ArchMutex m_mutex;
mutable std::mutex m_mutex;
OutputterList m_outputters;
OutputterList m_alwaysOutputters;
int m_maxNewlineLength;

View File

@@ -34,8 +34,6 @@ IpcClientProxy::IpcClientProxy(barrier::IStream& stream, IEventQueue* events) :
m_stream(stream),
m_clientType(kIpcClientUnknown),
m_disconnecting(false),
m_readMutex(ARCH->newMutex()),
m_writeMutex(ARCH->newMutex()),
m_events(events)
{
m_events->adoptHandler(
@@ -71,14 +69,11 @@ IpcClientProxy::~IpcClientProxy()
m_events->forIStream().outputShutdown(), m_stream.getEventTarget());
// don't delete the stream while it's being used.
ARCH->lockMutex(m_readMutex);
ARCH->lockMutex(m_writeMutex);
delete &m_stream;
ARCH->unlockMutex(m_readMutex);
ARCH->unlockMutex(m_writeMutex);
ARCH->closeMutex(m_readMutex);
ARCH->closeMutex(m_writeMutex);
{
std::lock_guard<std::mutex> lock_read(m_readMutex);
std::lock_guard<std::mutex> lock_write(m_writeMutex);
delete &m_stream;
}
}
void
@@ -99,7 +94,7 @@ void
IpcClientProxy::handleData(const Event&, void*)
{
// don't allow the dtor to destroy the stream while we're using it.
ArchMutexLock lock(m_readMutex);
std::lock_guard<std::mutex> lock(m_readMutex);
LOG((CLOG_DEBUG "start ipc handle data"));
@@ -139,7 +134,7 @@ IpcClientProxy::send(const IpcMessage& message)
// don't allow other threads to write until we've finished the entire
// message. stream write is locked, but only for that single write.
// also, don't allow the dtor to destroy the stream while we're using it.
ArchMutexLock lock(m_writeMutex);
std::lock_guard<std::mutex> lock(m_writeMutex);
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));

View File

@@ -23,6 +23,8 @@
#include "base/EventTypes.h"
#include "base/Event.h"
#include <mutex>
namespace barrier { class IStream; }
class IpcMessage;
class IpcCommandMessage;
@@ -49,7 +51,7 @@ private:
barrier::IStream& m_stream;
EIpcClientType m_clientType;
bool m_disconnecting;
ArchMutex m_readMutex;
ArchMutex m_writeMutex;
std::mutex m_readMutex;
std::mutex m_writeMutex;
IEventQueue* m_events;
};

View File

@@ -39,7 +39,6 @@ enum EIpcLogOutputter {
IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType, bool useThread) :
m_ipcServer(ipcServer),
m_bufferMutex(ARCH->newMutex()),
m_sending(false),
m_bufferThread(nullptr),
m_running(false),
@@ -52,8 +51,7 @@ IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType
m_bufferRateTimeLimit(kBufferRateTimeLimit),
m_bufferWriteCount(0),
m_bufferRateStart(ARCH->time()),
m_clientType(clientType),
m_runningMutex(ARCH->newMutex())
m_clientType(clientType)
{
if (useThread) {
m_bufferThread = new Thread(new TMethodJob<IpcLogOutputter>(
@@ -65,8 +63,6 @@ IpcLogOutputter::~IpcLogOutputter()
{
close();
ARCH->closeMutex(m_bufferMutex);
if (m_bufferThread != nullptr) {
m_bufferThread->cancel();
m_bufferThread->wait();
@@ -86,7 +82,7 @@ void
IpcLogOutputter::close()
{
if (m_bufferThread != nullptr) {
ArchMutexLock lock(m_runningMutex);
std::lock_guard<std::mutex> lock(m_runningMutex);
m_running = false;
notifyBuffer();
m_bufferThread->wait(5);
@@ -116,7 +112,7 @@ IpcLogOutputter::write(ELevel, const char* text)
void
IpcLogOutputter::appendBuffer(const String& text)
{
ArchMutexLock lock(m_bufferMutex);
std::lock_guard<std::mutex> lock(m_bufferMutex);
double elapsed = ARCH->time() - m_bufferRateStart;
if (elapsed < m_bufferRateTimeLimit) {
@@ -143,7 +139,7 @@ IpcLogOutputter::appendBuffer(const String& text)
bool
IpcLogOutputter::isRunning()
{
ArchMutexLock lock(m_runningMutex);
std::lock_guard<std::mutex> lock(m_runningMutex);
return m_running;
}
@@ -180,7 +176,7 @@ IpcLogOutputter::notifyBuffer()
String
IpcLogOutputter::getChunk(size_t count)
{
ArchMutexLock lock(m_bufferMutex);
std::lock_guard<std::mutex> lock(m_bufferMutex);
if (m_buffer.size() < count) {
count = m_buffer.size();

View File

@@ -24,6 +24,7 @@
#include "ipc/Ipc.h"
#include <deque>
#include <mutex>
class IpcServer;
class Event;
@@ -100,7 +101,7 @@ private:
IpcServer& m_ipcServer;
Buffer m_buffer;
ArchMutex m_bufferMutex;
std::mutex m_bufferMutex;
bool m_sending;
Thread* m_bufferThread;
bool m_running;
@@ -115,5 +116,5 @@ private:
UInt16 m_bufferWriteCount;
double m_bufferRateStart;
EIpcClientType m_clientType;
ArchMutex m_runningMutex;
std::mutex m_runningMutex;
};

View File

@@ -56,7 +56,6 @@ IpcServer::init()
{
m_socket = new TCPListenSocket(m_events, m_socketMultiplexer, IArchNetwork::kINET);
m_clientsMutex = ARCH->newMutex();
m_address.resolve();
m_events->adoptHandler(
@@ -75,15 +74,15 @@ IpcServer::~IpcServer()
delete m_socket;
}
ARCH->lockMutex(m_clientsMutex);
ClientList::iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {
deleteClient(*it);
{
std::lock_guard<std::mutex> lock(m_clientsMutex);
ClientList::iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {
deleteClient(*it);
}
m_clients.clear();
}
m_clients.clear();
ARCH->unlockMutex(m_clientsMutex);
ARCH->closeMutex(m_clientsMutex);
m_events->removeHandler(m_events->forIListenSocket().connecting(), m_socket);
}
@@ -103,10 +102,12 @@ IpcServer::handleClientConnecting(const Event&, void*)
LOG((CLOG_DEBUG "accepted ipc client connection"));
ARCH->lockMutex(m_clientsMutex);
IpcClientProxy* proxy = new IpcClientProxy(*stream, m_events);
m_clients.push_back(proxy);
ARCH->unlockMutex(m_clientsMutex);
IpcClientProxy* proxy = nullptr;
{
std::lock_guard<std::mutex> lock(m_clientsMutex);
proxy = new IpcClientProxy(*stream, m_events);
m_clients.push_back(proxy);
}
m_events->adoptHandler(
m_events->forIpcClientProxy().disconnected(), proxy,
@@ -127,7 +128,7 @@ IpcServer::handleClientDisconnected(const Event& e, void*)
{
IpcClientProxy* proxy = static_cast<IpcClientProxy*>(e.getTarget());
ArchMutexLock lock(m_clientsMutex);
std::lock_guard<std::mutex> lock(m_clientsMutex);
m_clients.remove(proxy);
deleteClient(proxy);
@@ -153,7 +154,7 @@ IpcServer::deleteClient(IpcClientProxy* proxy)
bool
IpcServer::hasClients(EIpcClientType clientType) const
{
ArchMutexLock lock(m_clientsMutex);
std::lock_guard<std::mutex> lock(m_clientsMutex);
if (m_clients.empty()) {
return false;
@@ -175,7 +176,7 @@ IpcServer::hasClients(EIpcClientType clientType) const
void
IpcServer::send(const IpcMessage& message, EIpcClientType filterType)
{
ArchMutexLock lock(m_clientsMutex);
std::lock_guard<std::mutex> lock(m_clientsMutex);
ClientList::iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {

View File

@@ -25,6 +25,7 @@
#include "base/EventTypes.h"
#include <list>
#include <mutex>
class Event;
class IpcClientProxy;
@@ -79,7 +80,7 @@ private:
TCPListenSocket* m_socket;
NetworkAddress m_address;
ClientList m_clients;
ArchMutex m_clientsMutex;
mutable std::mutex m_clientsMutex;
#ifdef TEST_ENV
public:

View File

@@ -20,6 +20,19 @@
#include "arch/IArchNetwork.h"
#include "common/IInterface.h"
#include <memory>
class ISocketMultiplexerJob;
struct MultiplexerJobStatus
{
MultiplexerJobStatus(bool cont, std::unique_ptr<ISocketMultiplexerJob>&& nj) :
continue_servicing(cont), new_job(std::move(nj))
{}
bool continue_servicing = false;
std::unique_ptr<ISocketMultiplexerJob> new_job;
};
//! Socket multiplexer job
/*!
@@ -32,21 +45,20 @@ public:
//! Handle socket event
/*!
Called by a socket multiplexer when the socket becomes readable,
writable, or has an error. It should return itself if the same
job can continue to service events, a new job if the socket must
be serviced differently, or NULL if the socket should no longer
be serviced. The socket is readable if \p readable is true,
writable if \p writable is true, and in error if \p error is
true.
Called by a socket multiplexer when the socket becomes readable, writable, or has an error.
The socket is readable if \p readable is true, writable if \p writable is true, and in error
if \p error is true.
The method returns false as the continue_servicing member of the returned struct if the socket
should no longer be served and true otherwise. Additionally, if the new_job member of the
returned pair is not empty, the socket should be serviced differently with the specified job.
This call must not attempt to directly change the job for this
socket by calling \c addSocket() or \c removeSocket() on the
multiplexer. It must instead return the new job. It can,
however, add or remove jobs for other sockets.
*/
virtual ISocketMultiplexerJob*
run(bool readable, bool writable, bool error) = 0;
virtual MultiplexerJobStatus run(bool readable, bool writable, bool error) = 0;
//@}
//! @name accessors
@@ -72,5 +84,6 @@ public:
*/
virtual bool isWritable() const = 0;
virtual bool isCursor() const { return false; }
//@}
};

View File

@@ -83,17 +83,9 @@ SecureSocket::~SecureSocket()
// take socket from multiplexer ASAP otherwise the race condition
// could cause events to get called on a dead object. TCPSocket
// will do this, too, but the double-call is harmless
setJob(NULL);
if (m_ssl->m_ssl != NULL) {
SSL_shutdown(m_ssl->m_ssl);
removeJob();
freeSSLResources();
SSL_free(m_ssl->m_ssl);
m_ssl->m_ssl = NULL;
}
if (m_ssl->m_context != NULL) {
SSL_CTX_free(m_ssl->m_context);
m_ssl->m_context = NULL;
}
// removing sleep() because I have no idea why you would want to do it
// ... smells of trying to cover up a bug you don't understand
//ARCH->sleep(1);
@@ -104,12 +96,24 @@ void
SecureSocket::close()
{
isFatal(true);
SSL_shutdown(m_ssl->m_ssl);
freeSSLResources();
TCPSocket::close();
}
void SecureSocket::freeSSLResources()
{
if (m_ssl->m_ssl != NULL) {
SSL_shutdown(m_ssl->m_ssl);
SSL_free(m_ssl->m_ssl);
m_ssl->m_ssl = NULL;
}
if (m_ssl->m_context != NULL) {
SSL_CTX_free(m_ssl->m_context);
m_ssl->m_context = NULL;
}
}
void
SecureSocket::connect(const NetworkAddress& addr)
{
@@ -121,13 +125,12 @@ SecureSocket::connect(const NetworkAddress& addr)
TCPSocket::connect(addr);
}
ISocketMultiplexerJob*
SecureSocket::newJob()
std::unique_ptr<ISocketMultiplexerJob> SecureSocket::newJob()
{
// after TCP connection is established, SecureSocket will pick up
// connected event and do secureConnect
if (m_connected && !m_secureReady) {
return NULL;
return {};
}
return TCPSocket::newJob();
@@ -136,7 +139,7 @@ SecureSocket::newJob()
void
SecureSocket::secureConnect()
{
setJob(new TSocketMultiplexerMethodJob<SecureSocket>(
setJob(std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceConnect,
getSocket(), isReadable(), isWritable()));
}
@@ -144,7 +147,7 @@ SecureSocket::secureConnect()
void
SecureSocket::secureAccept()
{
setJob(new TSocketMultiplexerMethodJob<SecureSocket>(
setJob(std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceAccept,
getSocket(), isReadable(), isWritable()));
}
@@ -736,10 +739,11 @@ SecureSocket::verifyCertFingerprint()
return isValid;
}
ISocketMultiplexerJob*
SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
bool, bool write, bool error)
MultiplexerJobStatus SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
bool read, bool write, bool error)
{
(void) read;
Lock lock(&getMutex());
int status = 0;
@@ -751,25 +755,28 @@ SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
// If status < 0, error happened
if (status < 0) {
return NULL;
return {false, {}};
}
// If status > 0, success
if (status > 0) {
sendEvent(m_events->forIDataSocket().secureConnected());
return newJob();
return {true, newJob()};
}
// Retry case
return new TSocketMultiplexerMethodJob<SecureSocket>(
return {
true,
std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceConnect,
getSocket(), isReadable(), isWritable());
getSocket(), isReadable(), isWritable())
};
}
ISocketMultiplexerJob*
SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
bool, bool write, bool error)
MultiplexerJobStatus SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
bool read, bool write, bool error)
{
(void) read;
Lock lock(&getMutex());
int status = 0;
@@ -780,19 +787,19 @@ SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
#endif
// If status < 0, error happened
if (status < 0) {
return NULL;
return {false, {}};
}
// If status > 0, success
if (status > 0) {
sendEvent(m_events->forClientListener().accepted());
return newJob();
return {true, newJob()};
}
// Retry case
return new TSocketMultiplexerMethodJob<SecureSocket>(
return {true, std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceAccept,
getSocket(), isReadable(), isWritable());
getSocket(), isReadable(), isWritable())};
}
void

View File

@@ -44,8 +44,7 @@ public:
// IDataSocket overrides
virtual void connect(const NetworkAddress&);
ISocketMultiplexerJob*
newJob();
std::unique_ptr<ISocketMultiplexerJob> newJob() override;
bool isFatal() const { return m_fatal; }
void isFatal(bool b) { m_fatal = b; }
bool isSecureReady();
@@ -74,13 +73,8 @@ private:
bool separator = true);
bool verifyCertFingerprint();
ISocketMultiplexerJob*
serviceConnect(ISocketMultiplexerJob*,
bool, bool, bool);
ISocketMultiplexerJob*
serviceAccept(ISocketMultiplexerJob*,
bool, bool, bool);
MultiplexerJobStatus serviceConnect(ISocketMultiplexerJob*, bool, bool, bool);
MultiplexerJobStatus serviceAccept(ISocketMultiplexerJob*, bool, bool, bool);
void showSecureConnectInfo();
void showSecureLibInfo();
@@ -88,6 +82,8 @@ private:
void handleTCPConnected(const Event& event, void*);
void freeSSLResources();
private:
Ssl* m_ssl;
bool m_secureReady;

View File

@@ -33,6 +33,20 @@
// SocketMultiplexer
//
class CursorMultiplexerJob : public ISocketMultiplexerJob {
public:
MultiplexerJobStatus run(bool readable, bool writable, bool error) override
{
return {false, {}};
}
ArchSocket getSocket() const override { return {}; }
bool isReadable() const override { return false; }
bool isWritable() const override { return false; }
bool isCursor() const override { return true; }
};
SocketMultiplexer::SocketMultiplexer() :
m_mutex(new Mutex),
m_thread(NULL),
@@ -43,12 +57,6 @@ SocketMultiplexer::SocketMultiplexer() :
m_jobListLocker(NULL),
m_jobListLockLocker(NULL)
{
// this pointer just has to be unique and not NULL. it will
// never be dereferenced. it's used to identify cursor nodes
// in the jobs list.
// TODO: Remove this evilness
m_cursorMark = reinterpret_cast<ISocketMultiplexerJob*>(this);
// start thread
m_thread = new Thread(new TMethodJob<SocketMultiplexer>(
this, &SocketMultiplexer::serviceThread));
@@ -66,16 +74,9 @@ SocketMultiplexer::~SocketMultiplexer()
delete m_jobListLocker;
delete m_jobListLockLocker;
delete m_mutex;
// clean up jobs
for (SocketJobMap::iterator i = m_socketJobMap.begin();
i != m_socketJobMap.end(); ++i) {
delete *(i->second);
}
}
void
SocketMultiplexer::addSocket(ISocket* socket, ISocketMultiplexerJob* job)
void SocketMultiplexer::addSocket(ISocket* socket, std::unique_ptr<ISocketMultiplexerJob>&& job)
{
assert(socket != NULL);
assert(job != NULL);
@@ -95,16 +96,12 @@ SocketMultiplexer::addSocket(ISocket* socket, ISocketMultiplexerJob* job)
// we *must* put the job at the end so the order of jobs in
// the list continue to match the order of jobs in pfds in
// serviceThread().
JobCursor j = m_socketJobs.insert(m_socketJobs.end(), job);
JobCursor j = m_socketJobs.insert(m_socketJobs.end(), std::move(job));
m_update = true;
m_socketJobMap.insert(std::make_pair(socket, j));
}
else {
JobCursor j = i->second;
if (*j != job) {
delete *j;
*j = job;
}
*(i->second) = std::move(job);
m_update = true;
}
@@ -131,10 +128,9 @@ SocketMultiplexer::removeSocket(ISocket* socket)
// to match the order of jobs in pfds in serviceThread().
SocketJobMap::iterator i = m_socketJobMap.find(socket);
if (i != m_socketJobMap.end()) {
if (*(i->second) != NULL) {
delete *(i->second);
*(i->second) = NULL;
m_update = true;
if (*(i->second)) {
i->second->reset();
m_update = true;
}
}
@@ -173,14 +169,13 @@ SocketMultiplexer::serviceThread(void*)
JobCursor cursor = newCursor();
JobCursor jobCursor = nextCursor(cursor);
while (jobCursor != m_socketJobs.end()) {
ISocketMultiplexerJob* job = *jobCursor;
if (job != NULL) {
pfd.m_socket = job->getSocket();
if (*jobCursor) {
pfd.m_socket = (*jobCursor)->getSocket();
pfd.m_events = 0;
if (job->isReadable()) {
if ((*jobCursor)->isReadable()) {
pfd.m_events |= IArchNetwork::kPOLLIN;
}
if (job->isWritable()) {
if ((*jobCursor)->isWritable()) {
pfd.m_events |= IArchNetwork::kPOLLOUT;
}
pfds.push_back(pfd);
@@ -221,15 +216,16 @@ SocketMultiplexer::serviceThread(void*)
IArchNetwork::kPOLLNVAL)) != 0);
// run job
ISocketMultiplexerJob* job = *jobCursor;
ISocketMultiplexerJob* newJob = job->run(read, write, error);
MultiplexerJobStatus status = (*jobCursor)->run(read, write, error);
// save job, if different
if (newJob != job) {
if (!status.continue_servicing) {
Lock lock(m_mutex);
delete job;
*jobCursor = newJob;
m_update = true;
jobCursor->reset();
m_update = true;
} else if (status.new_job) {
Lock lock(m_mutex);
*jobCursor = std::move(status.new_job);
m_update = true;
}
++i;
}
@@ -262,7 +258,7 @@ SocketMultiplexer::JobCursor
SocketMultiplexer::newCursor()
{
Lock lock(m_mutex);
return m_socketJobs.insert(m_socketJobs.begin(), m_cursorMark);
return m_socketJobs.insert(m_socketJobs.begin(), std::make_unique<CursorMultiplexerJob>());
}
SocketMultiplexer::JobCursor
@@ -272,7 +268,7 @@ SocketMultiplexer::nextCursor(JobCursor cursor)
JobCursor j = m_socketJobs.end();
JobCursor i = cursor;
while (++i != m_socketJobs.end()) {
if (*i != m_cursorMark) {
if (*i && !(*i)->isCursor()) {
// found a real job (as opposed to a cursor)
j = i;

View File

@@ -21,6 +21,7 @@
#include "arch/IArchNetwork.h"
#include "common/stdlist.h"
#include "common/stdmap.h"
#include <memory>
template <class T>
class CondVar;
@@ -41,7 +42,7 @@ public:
//! @name manipulators
//@{
void addSocket(ISocket*, ISocketMultiplexerJob*);
void addSocket(ISocket*, std::unique_ptr<ISocketMultiplexerJob>&& job);
void removeSocket(ISocket*);
@@ -58,7 +59,7 @@ public:
private:
// list of jobs. we use a list so we can safely iterate over it
// while other threads modify it.
typedef std::list<ISocketMultiplexerJob*> SocketJobs;
using SocketJobs = std::list<std::unique_ptr<ISocketMultiplexerJob>>;
typedef SocketJobs::iterator JobCursor;
typedef std::map<ISocket*, JobCursor> SocketJobMap;
@@ -106,6 +107,4 @@ private:
SocketJobs m_socketJobs;
SocketJobMap m_socketJobMap;
ISocketMultiplexerJob*
m_cursorMark;
};

View File

@@ -69,10 +69,11 @@ TCPListenSocket::bind(const NetworkAddress& addr)
ARCH->setReuseAddrOnSocket(m_socket, true);
ARCH->bindSocket(m_socket, addr.getAddress());
ARCH->listenOnSocket(m_socket);
m_socketMultiplexer->addSocket(this,
new TSocketMultiplexerMethodJob<TCPListenSocket>(
this, &TCPListenSocket::serviceListening,
m_socket, true, false));
auto new_job = std::make_unique<TSocketMultiplexerMethodJob<TCPListenSocket>>(
this, &TCPListenSocket::serviceListening, m_socket, true, false);
m_socketMultiplexer->addSocket(this, std::move(new_job));
}
catch (XArchNetworkAddressInUse& e) {
throw XSocketAddressInUse(e.what());
@@ -135,24 +136,22 @@ TCPListenSocket::accept()
void
TCPListenSocket::setListeningJob()
{
m_socketMultiplexer->addSocket(this,
new TSocketMultiplexerMethodJob<TCPListenSocket>(
this, &TCPListenSocket::serviceListening,
m_socket, true, false));
auto new_job = std::make_unique<TSocketMultiplexerMethodJob<TCPListenSocket>>(
this, &TCPListenSocket::serviceListening, m_socket, true, false);
m_socketMultiplexer->addSocket(this, std::move(new_job));
}
ISocketMultiplexerJob*
TCPListenSocket::serviceListening(ISocketMultiplexerJob* job,
bool read, bool, bool error)
MultiplexerJobStatus TCPListenSocket::serviceListening(ISocketMultiplexerJob* job,
bool read, bool, bool error)
{
if (error) {
close();
return NULL;
return {false, {}};
}
if (read) {
m_events->addEvent(Event(m_events->forIListenSocket().connecting(), this, NULL));
// stop polling on this socket until the client accepts
return NULL;
return {false, {}};
}
return job;
return {true, {}};
}

View File

@@ -19,10 +19,10 @@
#pragma once
#include "net/IListenSocket.h"
#include "net/ISocketMultiplexerJob.h"
#include "arch/IArchNetwork.h"
class Mutex;
class ISocketMultiplexerJob;
class IEventQueue;
class SocketMultiplexer;
@@ -48,9 +48,7 @@ protected:
void setListeningJob();
public:
ISocketMultiplexerJob*
serviceListening(ISocketMultiplexerJob*,
bool, bool, bool);
MultiplexerJobStatus serviceListening(ISocketMultiplexerJob*, bool, bool, bool);
protected:
ArchSocket m_socket;

View File

@@ -388,40 +388,42 @@ TCPSocket::doWrite()
return kRetry;
}
void
TCPSocket::setJob(ISocketMultiplexerJob* job)
void TCPSocket::removeJob()
{
// multiplexer will delete the old job
if (job == NULL) {
m_socketMultiplexer->removeSocket(this);
}
else {
m_socketMultiplexer->addSocket(this, job);
m_socketMultiplexer->removeSocket(this);
}
void TCPSocket::setJob(std::unique_ptr<ISocketMultiplexerJob>&& job)
{
if (job.get() == nullptr) {
removeJob();
} else {
m_socketMultiplexer->addSocket(this, std::move(job));
}
}
ISocketMultiplexerJob*
TCPSocket::newJob()
std::unique_ptr<ISocketMultiplexerJob> TCPSocket::newJob()
{
// note -- must have m_mutex locked on entry
if (m_socket == NULL) {
return NULL;
return {};
}
else if (!m_connected) {
assert(!m_readable);
if (!(m_readable || m_writable)) {
return NULL;
return {};
}
return new TSocketMultiplexerMethodJob<TCPSocket>(
return std::make_unique<TSocketMultiplexerMethodJob<TCPSocket>>(
this, &TCPSocket::serviceConnecting,
m_socket, m_readable, m_writable);
}
else {
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
return NULL;
return {};
}
return new TSocketMultiplexerMethodJob<TCPSocket>(
return std::make_unique<TSocketMultiplexerMethodJob<TCPSocket>>(
this, &TCPSocket::serviceConnected,
m_socket, m_readable,
m_writable && (m_outputBuffer.getSize() > 0));
@@ -488,9 +490,7 @@ TCPSocket::onDisconnected()
m_connected = false;
}
ISocketMultiplexerJob*
TCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
bool, bool write, bool error)
MultiplexerJobStatus TCPSocket::serviceConnecting(ISocketMultiplexerJob* job, bool, bool write, bool error)
{
Lock lock(&m_mutex);
@@ -519,29 +519,36 @@ TCPSocket::serviceConnecting(ISocketMultiplexerJob* job,
catch (XArchNetwork& e) {
sendConnectionFailedEvent(e.what());
onDisconnected();
return newJob();
auto new_job = newJob();
if (new_job)
return {true, std::move(new_job)};
else
return {false, {}};
}
}
if (write) {
sendEvent(m_events->forIDataSocket().connected());
onConnected();
return newJob();
auto new_job = newJob();
if (new_job)
return {true, std::move(new_job)};
else
return {false, {}};
}
return job;
return {true, {}};
}
ISocketMultiplexerJob*
TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
bool read, bool write, bool error)
MultiplexerJobStatus TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
bool read, bool write, bool error)
{
Lock lock(&m_mutex);
if (error) {
sendEvent(m_events->forISocket().disconnected());
onDisconnected();
return newJob();
return {true, newJob()};
}
EJobResult writeResult = kRetry;
@@ -594,10 +601,10 @@ TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
}
if (writeResult == kBreak || readResult == kBreak) {
return NULL;
return {false, {}};
} else if (writeResult == kNew || readResult == kNew) {
return newJob();
return {true, newJob()};
} else {
return job;
return {true, {}};
}
}

View File

@@ -19,14 +19,15 @@
#pragma once
#include "net/IDataSocket.h"
#include "net/ISocketMultiplexerJob.h"
#include "io/StreamBuffer.h"
#include "mt/CondVar.h"
#include "mt/Mutex.h"
#include "arch/IArchNetwork.h"
#include <memory>
class Mutex;
class Thread;
class ISocketMultiplexerJob;
class IEventQueue;
class SocketMultiplexer;
@@ -59,8 +60,7 @@ public:
virtual void connect(const NetworkAddress&);
virtual ISocketMultiplexerJob*
newJob();
virtual std::unique_ptr<ISocketMultiplexerJob> newJob();
protected:
enum EJobResult {
@@ -74,7 +74,8 @@ protected:
virtual EJobResult doRead();
virtual EJobResult doWrite();
void setJob(ISocketMultiplexerJob*);
void removeJob();
void setJob(std::unique_ptr<ISocketMultiplexerJob>&& job);
bool isReadable() { return m_readable; }
bool isWritable() { return m_writable; }
@@ -93,12 +94,8 @@ private:
void onOutputShutdown();
void onDisconnected();
ISocketMultiplexerJob*
serviceConnecting(ISocketMultiplexerJob*,
bool, bool, bool);
ISocketMultiplexerJob*
serviceConnected(ISocketMultiplexerJob*,
bool, bool, bool);
MultiplexerJobStatus serviceConnecting(ISocketMultiplexerJob*, bool, bool, bool);
MultiplexerJobStatus serviceConnected(ISocketMultiplexerJob*, bool, bool, bool);
protected:
bool m_readable;

View File

@@ -28,8 +28,7 @@ A socket multiplexer job class that invokes a member function.
template <class T>
class TSocketMultiplexerMethodJob : public ISocketMultiplexerJob {
public:
typedef ISocketMultiplexerJob*
(T::*Method)(ISocketMultiplexerJob*, bool, bool, bool);
using Method = MultiplexerJobStatus (T::*)(ISocketMultiplexerJob*, bool, bool, bool);
//! run() invokes \c object->method(arg)
TSocketMultiplexerMethodJob(T* object, Method method,
@@ -37,11 +36,10 @@ public:
virtual ~TSocketMultiplexerMethodJob();
// IJob overrides
virtual ISocketMultiplexerJob*
run(bool readable, bool writable, bool error);
virtual ArchSocket getSocket() const;
virtual bool isReadable() const;
virtual bool isWritable() const;
virtual MultiplexerJobStatus run(bool readable, bool writable, bool error) override;
virtual ArchSocket getSocket() const override;
virtual bool isReadable() const override;
virtual bool isWritable() const override;
private:
T* m_object;
@@ -74,14 +72,12 @@ TSocketMultiplexerMethodJob<T>::~TSocketMultiplexerMethodJob()
}
template <class T>
inline
ISocketMultiplexerJob*
TSocketMultiplexerMethodJob<T>::run(bool read, bool write, bool error)
inline MultiplexerJobStatus TSocketMultiplexerMethodJob<T>::run(bool read, bool write, bool error)
{
if (m_object != NULL) {
return (m_object->*m_method)(this, read, write, error);
}
return NULL;
return {false, {}};
}
template <class T>

View File

@@ -33,6 +33,7 @@
#include "base/IEventQueue.h"
#include <malloc.h>
#include <VersionHelpers.h>
// these are only defined when WINVER >= 0x0500
#if !defined(SPI_GETMOUSESPEED)
@@ -45,6 +46,10 @@
#define SPI_GETSCREENSAVERRUNNING 114
#endif
#if !defined(MOUSEEVENTF_HWHEEL)
#define MOUSEEVENTF_HWHEEL 0x1000
#endif
// X button stuff
#if !defined(WM_XBUTTONDOWN)
#define WM_XBUTTONDOWN 0x020B
@@ -296,12 +301,12 @@ MSWindowsDesks::fakeMouseButton(ButtonID button, bool press)
flags = press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
break;
case kButtonExtra0 + 0:
case kButtonExtra0:
data = XBUTTON1;
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
break;
case kButtonExtra0 + 1:
case kButtonExtra1:
data = XBUTTON2;
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
break;
@@ -686,10 +691,12 @@ MSWindowsDesks::deskThread(void* vdesk)
break;
case BARRIER_MSG_FAKE_WHEEL:
// XXX -- add support for x-axis scrolling
if (msg.lParam != 0) {
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, (DWORD)msg.lParam, 0);
}
else if (IsWindowsVistaOrGreater() && msg.wParam != 0) {
mouse_event(MOUSEEVENTF_HWHEEL, 0, 0, (DWORD)msg.wParam, 0);
}
break;
case BARRIER_MSG_CURSOR_POS: {

View File

@@ -25,6 +25,10 @@
#include "common/DataDirectories.h"
#include "base/Log.h"
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
//
// debugging compile flag. when not zero the server doesn't grab
// the keyboard when the mouse leaves the server screen. this
@@ -473,6 +477,13 @@ mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
}
return (g_mode == kHOOK_RELAY_EVENTS);
case WM_MOUSEHWHEEL:
if (g_mode == kHOOK_RELAY_EVENTS) {
// relay event
PostThreadMessage(g_threadID, BARRIER_MSG_MOUSE_WHEEL, 0, data);
}
return (g_mode == kHOOK_RELAY_EVENTS);
case WM_NCMOUSEMOVE:
case WM_MOUSEMOVE:
if (g_mode == kHOOK_RELAY_EVENTS) {

View File

@@ -952,9 +952,9 @@ MSWindowsScreen::updateButtons()
m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0);
m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0);
m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0);
m_buttons[kButtonExtra0 + 0] = (numButtons >= 4) &&
m_buttons[kButtonExtra0] = (numButtons >= 4) &&
(GetKeyState(VK_XBUTTON1) < 0);
m_buttons[kButtonExtra0 + 1] = (numButtons >= 5) &&
m_buttons[kButtonExtra1] = (numButtons >= 5) &&
(GetKeyState(VK_XBUTTON2) < 0);
}
@@ -1007,8 +1007,7 @@ MSWindowsScreen::onPreDispatchPrimary(HWND,
static_cast<SInt32>(lParam));
case BARRIER_MSG_MOUSE_WHEEL:
// XXX -- support x-axis scrolling
return onMouseWheel(0, static_cast<SInt32>(wParam));
return onMouseWheel(static_cast<SInt32>(lParam), static_cast<SInt32>(wParam));
case BARRIER_MSG_PRE_WARP:
{
@@ -1670,13 +1669,13 @@ MSWindowsScreen::mapButtonFromEvent(WPARAM msg, LPARAM button) const
switch (button) {
case XBUTTON1:
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) {
return kButtonExtra0 + 0;
return kButtonExtra0;
}
break;
case XBUTTON2:
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) {
return kButtonExtra0 + 1;
return kButtonExtra1;
}
break;
}

View File

@@ -307,7 +307,7 @@ private:
HotKeyToIDMap m_hotKeyToIDMap;
// map of button state
bool m_buttons[1 + kButtonExtra0 + 1];
bool m_buttons[NumButtonIDs];
// the system shows the mouse cursor when an internal display count
// is >= 0. this count is maintained per application but there's

View File

@@ -422,6 +422,7 @@ OSXScreen::constructMouseButtonEventMap()
{kCGEventRightMouseUp, kCGEventRightMouseDragged, kCGEventRightMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}
};
@@ -1263,36 +1264,23 @@ OSXScreen::onKey(CGEventRef event)
return true;
}
// check for hot key. when we're on a secondary screen we disable
// all hotkeys so we can capture the OS defined hot keys as regular
// keystrokes but that means we don't get our own hot keys either.
// so we check for a key/modifier match in our hot key map.
if (!m_isOnScreen) {
HotKeyToIDMap::const_iterator i =
m_hotKeyToIDMap.find(HotKeyItem(virtualKey,
m_keyState->mapModifiersToCarbon(macMask)
& 0xff00u));
if (i != m_hotKeyToIDMap.end()) {
UInt32 id = i->second;
// determine event type
Event::Type type;
//UInt32 eventKind = GetEventKind(event);
if (eventKind == kCGEventKeyDown) {
type = m_events->forIPrimaryScreen().hotKeyDown();
}
else if (eventKind == kCGEventKeyUp) {
type = m_events->forIPrimaryScreen().hotKeyUp();
}
else {
return false;
}
m_events->addEvent(Event(type, getEventTarget(),
HotKeyInfo::alloc(id)));
return true;
HotKeyToIDMap::const_iterator i = m_hotKeyToIDMap.find(HotKeyItem(virtualKey, m_keyState->mapModifiersToCarbon(macMask) & 0xff00u));
if (i != m_hotKeyToIDMap.end()) {
UInt32 id = i->second;
// determine event type
Event::Type type;
//UInt32 eventKind = GetEventKind(event);
if (eventKind == kCGEventKeyDown) {
type = m_events->forIPrimaryScreen().hotKeyDown();
}
else if (eventKind == kCGEventKeyUp) {
type = m_events->forIPrimaryScreen().hotKeyUp();
}
else {
return false;
}
m_events->addEvent(Event(type, getEventTarget(), HotKeyInfo::alloc(id)));
return true;
}
// decode event type

View File

@@ -66,7 +66,8 @@ XWindowsScreen::XWindowsScreen(
IEventQueue* events) :
m_isPrimary(isPrimary),
m_mouseScrollDelta(mouseScrollDelta),
m_accumulatedScroll(0),
m_x_accumulatedScroll(0),
m_y_accumulatedScroll(0),
m_display(NULL),
m_root(None),
m_window(None),
@@ -829,35 +830,37 @@ XWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
}
void
XWindowsScreen::fakeMouseWheel(SInt32, SInt32 yDelta) const
XWindowsScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
{
// XXX -- support x-axis scrolling
if (yDelta == 0) {
return;
}
int numEvents;
int numEvents = accumulateMouseScroll(yDelta);
if ((!xDelta && !yDelta) || (xDelta && yDelta)) {
// Invalid scrolling inputs
return;
}
// choose button depending on rotation direction
const unsigned int xButton = mapButtonToX(static_cast<ButtonID>(
(numEvents >= 0) ? -1 : -2));
if (xButton == 0) {
// If we get here, then the XServer does not support the scroll
// wheel buttons, so send PageUp/PageDown keystrokes instead.
// Patch by Tom Chadwick.
KeyCode keycode = 0;
if (yDelta >= 0) {
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Up);
}
else {
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Down);
}
if (keycode != 0) {
m_impl->XTestFakeKeyEvent(m_display, keycode, True, CurrentTime);
m_impl->XTestFakeKeyEvent(m_display, keycode, False, CurrentTime);
}
return;
}
// 4, 5, 6, 7
// up, down, left, right
unsigned int xButton;
if (yDelta) { // vertical scroll
numEvents = y_accumulateMouseScroll(yDelta);
if (numEvents >= 0) {
xButton = 4; // up
}
else {
xButton = 5; // down
}
}
else { // horizontal scroll
numEvents = x_accumulateMouseScroll(xDelta);
if (numEvents >= 0) {
xButton = 7; // right
}
else {
xButton = 6; // left
}
}
numEvents = std::abs(numEvents);
@@ -1540,7 +1543,14 @@ XWindowsScreen::onMouseRelease(const XButtonEvent& xbutton)
// wheel backward (toward user)
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(0, -120));
}
// XXX -- support x-axis scrolling
else if (xbutton.button == 6) {
// wheel left
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(-120, 0));
}
else if (xbutton.button == 7) {
// wheel right
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(120, 0));
}
}
void
@@ -1613,11 +1623,20 @@ XWindowsScreen::onMouseMove(const XMotionEvent& xmotion)
}
int
XWindowsScreen::accumulateMouseScroll(SInt32 yDelta) const
XWindowsScreen::x_accumulateMouseScroll(SInt32 xDelta) const
{
m_accumulatedScroll += yDelta;
int numEvents = m_accumulatedScroll / m_mouseScrollDelta;
m_accumulatedScroll -= numEvents * m_mouseScrollDelta;
m_x_accumulatedScroll += xDelta;
int numEvents = m_x_accumulatedScroll / m_mouseScrollDelta;
m_x_accumulatedScroll -= numEvents * m_mouseScrollDelta;
return numEvents;
}
int
XWindowsScreen::y_accumulateMouseScroll(SInt32 yDelta) const
{
m_y_accumulatedScroll += yDelta;
int numEvents = m_y_accumulatedScroll / m_mouseScrollDelta;
m_y_accumulatedScroll -= numEvents * m_mouseScrollDelta;
return numEvents;
}
@@ -1840,19 +1859,19 @@ XWindowsScreen::mapButtonFromX(const XButtonEvent* event) const
{
unsigned int button = event->button;
// first three buttons map to 1, 2, 3 (kButtonLeft, Middle, Right)
if (button >= 1 && button <= 3) {
// http://xahlee.info/linux/linux_x11_mouse_button_number.html
// and the program `xev`
switch (button)
{
case 1: case 2: case 3: // kButtonLeft, Middle, Right
return static_cast<ButtonID>(button);
}
// buttons 4 and 5 are ignored here. they're used for the wheel.
// buttons 6, 7, etc and up map to 4, 5, etc.
else if (button >= 6) {
return static_cast<ButtonID>(button - 2);
}
// unknown button
else {
case 4: case 5: case 6: case 7: // scroll up, down, left, right -- ignored here
return kButtonNone;
case 8: // mouse button 4
return kButtonExtra0;
case 9: // mouse button 5
return kButtonExtra1;
default: // unknown button
return kButtonNone;
}
}
@@ -1860,30 +1879,17 @@ XWindowsScreen::mapButtonFromX(const XButtonEvent* event) const
unsigned int
XWindowsScreen::mapButtonToX(ButtonID id) const
{
// map button -1 to button 4 (+wheel)
if (id == static_cast<ButtonID>(-1)) {
id = 4;
}
// map button -2 to button 5 (-wheel)
else if (id == static_cast<ButtonID>(-2)) {
id = 5;
}
// map buttons 4, 5, etc. to 6, 7, etc. to make room for buttons
// 4 and 5 used to simulate the mouse wheel.
else if (id >= 4) {
id += 2;
}
// check button is in legal range
if (id < 1 || id > m_buttons.size()) {
// out of range
switch (id)
{
case kButtonLeft: case kButtonMiddle: case kButtonRight:
return id;
case kButtonExtra0:
return 8;
case kButtonExtra1:
return 9;
default:
return 0;
}
// map button
return static_cast<unsigned int>(id);
}
void

View File

@@ -139,7 +139,8 @@ private:
// Returns the number of scroll events needed after the current delta has
// been taken into account
int accumulateMouseScroll(SInt32 yDelta) const;
int x_accumulateMouseScroll(SInt32 xDelta) const;
int y_accumulateMouseScroll(SInt32 yDelta) const;
bool detectXI2();
#ifdef HAVE_XI2
@@ -183,10 +184,11 @@ private:
// The size of a smallest supported scroll event, in points
int m_mouseScrollDelta;
// Accumulates scrolls of less than m_mouseScrollDelta across multiple
// Accumulates scrolls of less than m_?_mouseScrollDelta across multiple
// scroll events. We dispatch a scroll event whenever the accumulated scroll
// becomes larger than m_mouseScrollDelta
mutable int m_accumulatedScroll;
// becomes larger than m_?_mouseScrollDelta
mutable int m_x_accumulatedScroll;
mutable int m_y_accumulatedScroll;
Display* m_display;
Window m_root;