Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
On Windows we use msys2 and ucrt64 to compile.
You need to prefix commands with `C:\msys64\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.

Prefix build directories with `cmake-build-`.

The test executable is named `test_tray` and will be located inside the `tests` directory within
the build directory.

The project uses gtest as a test framework.

Always follow the style guidelines defined in .clang-format for c/c++ code.
140 changes: 131 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ jobs:
shell: "bash"
- os: ubuntu-latest
appindicator: "libayatana-appindicator3-dev"
appindicator_type: "ayatana"
shell: "bash"
- os: ubuntu-latest
appindicator: "libappindicator3-dev"
appindicator_type: "legacy"
shell: "bash"
- os: windows-latest
shell: "msys2 {0}"
Expand All @@ -54,11 +56,19 @@ jobs:
build-essential \
cmake \
${{ matrix.appindicator }} \
imagemagick \
libglib2.0-dev \
libnotify-dev \
ninja-build \
xvfb

- name: Setup virtual desktop
if: runner.os == 'Linux'
uses: LizardByte/actions/actions/setup_virtual_desktop@feat/actions/linux-display # todo: pin version
with:
appindicator-version: ${{ matrix.appindicator_type }}
environment: mate

- name: Setup Dependencies macOS
if: runner.os == 'macOS'
run: |
Expand All @@ -67,9 +77,81 @@ jobs:
cmake \
doxygen \
graphviz \
imagemagick \
ninja \
node

- name: Fix macOS screen recording permissions
if: runner.os == 'macOS'
run: |
# Grant screen recording permissions to prevent popup dialogs in CI
# This modifies the TCC (Transparency, Consent, and Control) database

# https://apple.stackexchange.com/questions/362865/macos-list-apps-authorized-for-full-disk-access
# https://github.com/actions/runner-images/issues/9529
# https://github.com/actions/runner-images/pull/9530

# Get macOS version
os_version=$(sw_vers -productVersion | cut -d '.' -f 1)
echo "macOS version: $os_version"

# function to execute sql query for each value
function execute_sql_query {
local value=$1
local dbPath=$2
echo "Executing SQL query for value: $value"
sudo sqlite3 "$dbPath" "INSERT OR IGNORE INTO access VALUES($value);"
}

# Find all provisioner paths and store them in an array
declare -a app_paths=()
while IFS= read -r line; do
app_paths+=("$line")
done < <(sudo find /opt /usr -name bash 2>/dev/null)
echo "Provisioner paths: ${app_paths[@]}"

# Create an empty array
declare -a values=()

# Loop through the provisioner paths and add them to the values array
for p_path in "${app_paths[@]}"; do
# Adjust the service name and other parameters as needed
values+=("'kTCCServiceAccessibility','${p_path}',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,NULL,1592919552")
values+=("'kTCCServiceScreenCapture','${p_path}',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159")
done
echo "Values: ${values[@]}"

# Adjust for Sonoma (macOS 14+) which has extra columns
if [[ "$os_version" -ge 14 ]]; then
echo "Adjusting for macOS Sonoma or later (extra TCC columns)"
# TCC access table in Sonoma has extra 4 columns: pid, pid_version, boot_uuid, last_reminded
for i in "${!values[@]}"; do
values[$i]="${values[$i]},NULL,NULL,'UNUSED',${values[$i]##*,}"
done
fi

# System and user TCC databases
dbPaths=(
"/Library/Application Support/com.apple.TCC/TCC.db"
"$HOME/Library/Application Support/com.apple.TCC/TCC.db"
)

# Execute SQL queries
for value in "${values[@]}"; do
for dbPath in "${dbPaths[@]}"; do
echo "Column names for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "PRAGMA table_info(access);"
echo "Current permissions for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "SELECT * FROM access WHERE service='kTCCServiceScreenCapture';"
execute_sql_query "$value" "$dbPath"
echo "Updated permissions for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "SELECT * FROM access WHERE service='kTCCServiceScreenCapture';"
done
done

- name: Setup Dependencies Windows
if: runner.os == 'Windows'
uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0
Expand All @@ -81,6 +163,7 @@ jobs:
mingw-w64-ucrt-x86_64-binutils
mingw-w64-ucrt-x86_64-cmake
mingw-w64-ucrt-x86_64-graphviz
mingw-w64-ucrt-x86_64-imagemagick
mingw-w64-ucrt-x86_64-ninja
mingw-w64-ucrt-x86_64-nodejs
mingw-w64-ucrt-x86_64-toolchain
Expand All @@ -103,7 +186,7 @@ jobs:

# step output
echo "python-path=${python_path}"
echo "python-path=${python_path}" >> $GITHUB_OUTPUT
echo "python-path=${python_path}" >> "${GITHUB_OUTPUT}"

- name: Build
run: |
Expand All @@ -124,18 +207,57 @@ jobs:
-S .
ninja -C build

- name: Init tray icon (Windows)
if: runner.os == 'Windows'
working-directory: build/tests
run: ./test_tray --gtest_color=yes --gtest_filter=TrayTest.TestTrayInit

- name: Configure Windows
if: runner.os == 'Windows'
shell: pwsh
run: |
echo "::group::Enable all tray icons"
Invoke-WebRequest `
-Uri "https://raw.githubusercontent.com/paulmann/windows-show-all-tray-icons/main/Enable-AllTrayIcons.ps1" `
-OutFile "Enable-AllTrayIcons.ps1"
.\Enable-AllTrayIcons.ps1 -Action Enable -Force # Enable with comprehensive method (resets ALL icon settings)
echo "::endgroup::"

echo "::group::Disable Do Not Disturb"
Add-Type -AssemblyName System.Windows.Forms
Start-Process "ms-settings:notifications"
Start-Sleep -Seconds 2
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
[System.Windows.Forms.SendKeys]::SendWait(" ")
echo "::endgroup::"

echo "::group::Minimize all windows"
$shell = New-Object -ComObject Shell.Application
$shell.MinimizeAll()
echo "::endgroup::"

echo "::group::Set Date - Hack for Quiet Time"
$newDate = (Get-Date).AddHours(2)
Set-Date -Date $newDate
echo "::endgroup::"

- name: Run tests
id: test
# TODO: tests randomly hang on Linux, https://github.com/LizardByte/tray/issues/45
timeout-minutes: 1
timeout-minutes: 3
working-directory: build/tests
run: |
if [ "${{ runner.os }}" = "Linux" ]; then
export DISPLAY=:1
Xvfb ${DISPLAY} -screen 0 1024x768x24 &
fi
run: ./test_tray --gtest_color=yes --gtest_output=xml:test_results.xml

./test_tray --gtest_color=yes --gtest_output=xml:test_results.xml
- name: Upload screenshots
if: >-
always() &&
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
uses: actions/upload-artifact@v6
with:
name: tray-screenshots-${{ runner.os }}${{ matrix.appindicator && format('-{0}', matrix.appindicator) || '' }}
path: build/tests/screenshots
if-no-files-found: error

- name: Generate gcov report
id: test_report
Expand Down Expand Up @@ -164,7 +286,7 @@ jobs:
if [ -n "${{ matrix.appindicator }}" ]; then
flags="${flags},${{ matrix.appindicator }}"
fi
echo "flags=${flags}" >> $GITHUB_OUTPUT
echo "flags=${flags}" >> "${GITHUB_OUTPUT}"

- name: Upload coverage
# any except canceled or skipped
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/publish-screenshots.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: Publish Screenshots

on:
workflow_run:
workflows: ["CI"]
types:
- completed

permissions:
contents: write
pull-requests: write

jobs:
publish:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- name: Download Artifacts
uses: actions/download-artifact@v7
with:
path: screenshots
pattern: tray-screenshots-*
run-id: ${{ github.event.workflow_run.id }}

- name: Debug screenshots
run: ls -R screenshots

- name: Determine Branch and Path
id: determine
env:
PULL_REQUEST_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
run: |
if [ -n "${PULL_REQUEST_NUMBER}" ]; then
PR_NUMBER=${PULL_REQUEST_NUMBER}
BRANCH_PATH="PR-${PULL_REQUEST_NUMBER}"
is_pr=true
else
BRANCH_NAME=$(echo "${HEAD_BRANCH}" | sed 's/\//-/g')
BRANCH_PATH="${BRANCH_NAME}"
is_pr=false
fi

{
echo "branch_path=${BRANCH_PATH}"
echo "is_pr=${is_pr}"
echo "pr_number=${PR_NUMBER}"
} >> "${GITHUB_OUTPUT}"

# debug outputs
cat "${GITHUB_OUTPUT}"

- name: Checkout Screenshots Branch
uses: actions/checkout@v6
with:
ref: screenshots
path: screenshots-repo
1 change: 1 addition & 0 deletions docs/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ PROJECT_NAME = tray
DOT_GRAPH_MAX_NODES = 50
IMAGE_PATH = ../docs/images
INCLUDE_PATH =
PREDEFINED += TRAY_WINAPI

# files and directories to process
USE_MDFILE_AS_MAINPAGE = ../README.md
Expand Down
17 changes: 17 additions & 0 deletions src/tray.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#ifndef TRAY_H
#define TRAY_H

#if defined(TRAY_WINAPI)
#include <Windows.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -64,11 +68,24 @@ extern "C" {
*/
void tray_update(struct tray *tray);

/**
* @brief Force show the tray menu (for testing purposes).
*/
void tray_show_menu(void);

/**
* @brief Terminate UI loop.
*/
void tray_exit(void);

#if defined(TRAY_WINAPI)
/**
* @brief Get the tray window handle.
* @return The window handle.
*/
HWND tray_get_hwnd(void);
#endif

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
Loading
Loading