Compare commits

...

6 Commits

Author SHA1 Message Date
Kevin Yue
c70c7ee5b9 fix: multiple tray icon related: #464 2025-02-09 08:23:40 +00:00
Kevin Yue
fe3d3df662 ci: upload offline tarball 2025-01-23 21:59:59 +08:00
Kevin Yue
2f90b73683 fix: check the cli running state 2025-01-22 21:30:42 +08:00
Kevin Yue
5186e80c6f doc: update installation for Ubuntu 18.04 2025-01-21 23:00:32 +08:00
Kevin Yue
4ff1c1dc1f Release 2.4.3 2025-01-21 00:16:00 +08:00
Kevin Yue
c1427040f6 fix: do not use default value for os_version 2025-01-21 00:14:13 +08:00
15 changed files with 228 additions and 108 deletions

View File

@@ -44,7 +44,8 @@ jobs:
with: with:
version: 9 version: 9
- name: Prepare workspace - name: Prepare workspace
run: rm -rf source && mkdir source run: rm -rf source && mkdir -p source/artifacts
- name: Checkout GlobalProtect-openconnect - name: Checkout GlobalProtect-openconnect
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@@ -52,6 +53,7 @@ jobs:
repository: yuezk/GlobalProtect-openconnect repository: yuezk/GlobalProtect-openconnect
ref: ${{ github.ref }} ref: ${{ github.ref }}
path: source/gp path: source/gp
- name: Create tarball - name: Create tarball
run: | run: |
cd source/gp cd source/gp
@@ -60,13 +62,69 @@ jobs:
touch SNAPSHOT touch SNAPSHOT
fi fi
make tarball make tarball
mv -v .build/tarball/*.tar.gz ../artifacts/
- name: Generate RPM spec file
env:
RELEASE_TAG: ${{ github.ref == 'refs/heads/dev' && 'snapshot' || github.ref_name }}
run: |
cd source/gp
make init-rpm \
REVISION='1%{?dist}' \
RPM_SOURCE=https://github.com/yuezk/GlobalProtect-openconnect/releases/download/${RELEASE_TAG}/%{name}-%{version}.tar.gz
mv -v .build/rpm/*.spec ../artifacts/
- name: Upload tarball - name: Upload tarball
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: artifact-source name: artifact-source
if-no-files-found: error if-no-files-found: error
path: | path: |
source/gp/.build/tarball/*.tar.gz source/artifacts/*
tarball-offline:
if: ${{ github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/') }}
runs-on: ubuntu-latest
needs:
- tarball
steps:
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Prepare workspace
run: rm -rf source-offline && mkdir source-offline
- name: Download tarball
uses: actions/download-artifact@v4
with:
name: artifact-source
path: source-offline
- name: Create offline tarball
run: |
cd source-offline
offline_tarball=$(basename *.tar.gz .tar.gz).offline.tar.gz
# Extract the tarball
tar -xzf *.tar.gz
cd */
make tarball OFFLINE=1
# Rename the tarball to .offline.tar.gz
mv -v .build/tarball/*.tar.gz ../$offline_tarball
- name: Upload offline tarball
uses: actions/upload-artifact@v4
with:
path: source-offline/*.offline.tar.gz
name: artifact-source-offline
if-no-files-found: error
build-gp: build-gp:
needs: needs:
@@ -168,6 +226,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- tarball - tarball
- tarball-offline
- build-gp - build-gp
- build-gpgui - build-gpgui

View File

@@ -52,22 +52,26 @@ jobs:
version: 9 version: 9
- name: Prepare workspace - name: Prepare workspace
run: rm -rf publish-ppa && mkdir publish-ppa run: rm -rf publish-ppa && mkdir publish-ppa
- name: Download ${{ inputs.tag }} source code - name: Download ${{ inputs.tag }} offline source code
uses: robinraju/release-downloader@v1.9 env:
with: GH_TOKEN: ${{ secrets.GH_PAT }}
token: ${{ secrets.GH_PAT }} run: |
tag: ${{ inputs.tag }} gh -R yuezk/GlobalProtect-openconnect \
fileName: globalprotect-openconnect-*.tar.gz release download ${{ inputs.tag }} \
tarBall: false --pattern '*.offline.tar.gz' \
zipBall: false --dir publish-ppa
out-file-path: publish-ppa - name: Patch the source code
- name: Make the offline tarball
run: | run: |
cd publish-ppa cd publish-ppa
tar -xf globalprotect-openconnect-*.tar.gz
cd globalprotect-openconnect-*/
make tarball OFFLINE=1 # Rename the source tarball without the offline suffix
mv -v *.tar.gz $(basename *.tar.gz .offline.tar.gz).tar.gz
# Extract the source tarball
tar -xzf *.tar.gz
# Prepare the debian directory with custom files
cd globalprotect-openconnect-*/
# Prepare the debian directory with custom files # Prepare the debian directory with custom files
mkdir -p .build/debian mkdir -p .build/debian
@@ -78,7 +82,6 @@ jobs:
cp -v packaging/deb/postrm .build/debian/postrm cp -v packaging/deb/postrm .build/debian/postrm
sed -i "s/@RUST@/cargo-1.80/g" .build/debian/control sed -i "s/@RUST@/cargo-1.80/g" .build/debian/control
sed -i "s/@OFFLINE@/1/g" .build/debian/rules sed -i "s/@OFFLINE@/1/g" .build/debian/rules
sed -i "s/@BUILD_GUI@/1/g" .build/debian/rules sed -i "s/@BUILD_GUI@/1/g" .build/debian/rules
sed -i "s/@RUST_VERSION@/1.80/g" .build/debian/rules sed -i "s/@RUST_VERSION@/1.80/g" .build/debian/rules
@@ -89,7 +92,7 @@ jobs:
repository: "yuezk/globalprotect-openconnect" repository: "yuezk/globalprotect-openconnect"
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }} gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }} gpg_passphrase: ${{ secrets.PPA_GPG_PASSPHRASE }}
tarball: publish-ppa/globalprotect-openconnect-*/.build/tarball/*.tar.gz tarball: publish-ppa/globalprotect-openconnect-*.tar.gz
debian_dir: publish-ppa/globalprotect-openconnect-*/.build/debian debian_dir: publish-ppa/globalprotect-openconnect-*/.build/debian
deb_email: "k3vinyue@gmail.com" deb_email: "k3vinyue@gmail.com"
deb_fullname: "Kevin Yue" deb_fullname: "Kevin Yue"

View File

@@ -96,15 +96,16 @@ jobs:
steps: steps:
- name: Prepare workspace - name: Prepare workspace
run: rm -rf build-${{ matrix.package }} && mkdir -p build-${{ matrix.package }} run: rm -rf build-${{ matrix.package }} && mkdir -p build-${{ matrix.package }}
- name: Download ${{ inputs.tag }} source code - name: Download ${{ inputs.tag }} source code
uses: robinraju/release-downloader@v1.9 env:
with: GH_TOKEN: ${{ secrets.GH_PAT }}
token: ${{ secrets.GH_PAT }} run: |
tag: ${{ inputs.tag }} gh -R yuezk/GlobalProtect-openconnect \
fileName: globalprotect-openconnect-*.tar.gz release download ${{ inputs.tag }} \
tarBall: false --pattern '*[^offline].tar.gz' \
zipBall: false --dir build-${{ matrix.package }}
out-file-path: build-${{ matrix.package }}
- name: Docker Login - name: Docker Login
run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin
- name: Build ${{ matrix.package }} package in Docker - name: Build ${{ matrix.package }} package in Docker

17
Cargo.lock generated
View File

@@ -176,7 +176,7 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]] [[package]]
name = "auth" name = "auth"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"block2", "block2",
@@ -642,7 +642,7 @@ dependencies = [
[[package]] [[package]]
name = "common" name = "common"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"is_executable", "is_executable",
] ]
@@ -1590,7 +1590,7 @@ dependencies = [
[[package]] [[package]]
name = "gpapi" name = "gpapi"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.22.1", "base64 0.22.1",
@@ -1599,6 +1599,7 @@ dependencies = [
"clap-verbosity-flag", "clap-verbosity-flag",
"dns-lookup", "dns-lookup",
"env_logger", "env_logger",
"gtk",
"log", "log",
"log-reload", "log-reload",
"md5", "md5",
@@ -1626,7 +1627,7 @@ dependencies = [
[[package]] [[package]]
name = "gpauth" name = "gpauth"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"auth", "auth",
@@ -1645,7 +1646,7 @@ dependencies = [
[[package]] [[package]]
name = "gpclient" name = "gpclient"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -1667,7 +1668,7 @@ dependencies = [
[[package]] [[package]]
name = "gpgui-helper" name = "gpgui-helper"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -1685,7 +1686,7 @@ dependencies = [
[[package]] [[package]]
name = "gpservice" name = "gpservice"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum", "axum",
@@ -2951,7 +2952,7 @@ dependencies = [
[[package]] [[package]]
name = "openconnect" name = "openconnect"
version = "2.4.2" version = "2.4.3"
dependencies = [ dependencies = [
"cc", "cc",
"common", "common",

View File

@@ -11,7 +11,7 @@ members = [
[workspace.package] [workspace.package]
rust-version = "1.80" rust-version = "1.80"
version = "2.4.2" version = "2.4.3"
authors = ["Kevin Yue <k3vinyue@gmail.com>"] authors = ["Kevin Yue <k3vinyue@gmail.com>"]
homepage = "https://github.com/yuezk/GlobalProtect-openconnect" homepage = "https://github.com/yuezk/GlobalProtect-openconnect"
edition = "2021" edition = "2021"

View File

@@ -8,6 +8,8 @@ RUST_VERSION = 1.80
VERSION = $(shell $(CARGO) metadata --no-deps --format-version 1 | jq -r '.packages[0].version') VERSION = $(shell $(CARGO) metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
REVISION ?= 1 REVISION ?= 1
RPM_SOURCE ?= %{name}.tar.gz
PPA_REVISION ?= 1 PPA_REVISION ?= 1
PKG_NAME = globalprotect-openconnect PKG_NAME = globalprotect-openconnect
PKG = $(PKG_NAME)-$(VERSION) PKG = $(PKG_NAME)-$(VERSION)
@@ -234,6 +236,7 @@ init-rpm: clean-rpm
sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.spec sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.spec
sed -i "s/@REVISION@/$(REVISION)/g" .build/rpm/globalprotect-openconnect.spec sed -i "s/@REVISION@/$(REVISION)/g" .build/rpm/globalprotect-openconnect.spec
sed -i "s|@SOURCE@|$(RPM_SOURCE)|g" .build/rpm/globalprotect-openconnect.spec
sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/rpm/globalprotect-openconnect.spec sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/rpm/globalprotect-openconnect.spec
sed -i "s/@DATE@/$(shell LC_ALL=en.US date "+%a %b %d %Y")/g" .build/rpm/globalprotect-openconnect.spec sed -i "s/@DATE@/$(shell LC_ALL=en.US date "+%a %b %d %Y")/g" .build/rpm/globalprotect-openconnect.spec

View File

@@ -70,7 +70,7 @@ The GUI version is also available after you installed it. You can launch it from
### Debian/Ubuntu based distributions ### Debian/Ubuntu based distributions
#### Install from PPA (Ubuntu > 18.04) #### Install from PPA
``` ```
sudo add-apt-repository ppa:yuezk/globalprotect-openconnect sudo add-apt-repository ppa:yuezk/globalprotect-openconnect
@@ -81,10 +81,6 @@ sudo apt-get install globalprotect-openconnect
> >
> For Linux Mint, you might need to import the GPG key with: `sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7937C393082992E5D6E4A60453FC26B43838D761` if you encountered an error `gpg: keyserver receive failed: General error`. > For Linux Mint, you might need to import the GPG key with: `sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7937C393082992E5D6E4A60453FC26B43838D761` if you encountered an error `gpg: keyserver receive failed: General error`.
#### **Ubuntu 18.04**
The latest package is not available in the PPA, but you still needs to add the `ppa:yuezk/globalprotect-openconnect` repo beforehand to use the required `openconnect` package. Then you can follow the [Install from deb package](#install-from-deb-package) section to install the latest package.
#### Install from deb package #### Install from deb package
Download the latest deb package from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page. Then install it with `apt`: Download the latest deb package from [releases](https://github.com/yuezk/GlobalProtect-openconnect/releases) page. Then install it with `apt`:

View File

@@ -1,17 +1,21 @@
use std::{env::temp_dir, fs::File}; use std::{env::temp_dir, fs::File, str::FromStr};
use anyhow::bail;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use gpapi::{ use gpapi::{
clap::{handle_error, Args, InfoLevelVerbosity}, clap::{handle_error, Args, InfoLevelVerbosity},
utils::openssl, utils::openssl,
}; };
use log::info; use log::info;
use sysinfo::{Pid, System};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use tokio::fs;
use crate::{ use crate::{
connect::{ConnectArgs, ConnectHandler}, connect::{ConnectArgs, ConnectHandler},
disconnect::{DisconnectArgs, DisconnectHandler}, disconnect::{DisconnectArgs, DisconnectHandler},
launch_gui::{LaunchGuiArgs, LaunchGuiHandler}, launch_gui::{LaunchGuiArgs, LaunchGuiHandler},
GP_CLIENT_LOCK_FILE,
}; };
const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", compile_time::date_str!(), ")"); const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), " (", compile_time::date_str!(), ")");
@@ -77,6 +81,25 @@ impl Args for Cli {
} }
impl Cli { impl Cli {
async fn is_running(&self) -> bool {
let Ok(c) = fs::read_to_string(GP_CLIENT_LOCK_FILE).await else {
return false;
};
let Ok(pid) = Pid::from_str(c.trim()) else {
return false;
};
let s = System::new_all();
let Some(p) = s.process(pid) else {
return false;
};
p.exe()
.map(|exe| exe.to_string_lossy().contains("gpclient"))
.unwrap_or(false)
}
fn fix_openssl(&self) -> anyhow::Result<Option<NamedTempFile>> { fn fix_openssl(&self) -> anyhow::Result<Option<NamedTempFile>> {
if self.fix_openssl { if self.fix_openssl {
let file = openssl::fix_openssl_env()?; let file = openssl::fix_openssl_env()?;
@@ -87,6 +110,11 @@ impl Cli {
} }
async fn run(&self) -> anyhow::Result<()> { async fn run(&self) -> anyhow::Result<()> {
// check if an instance is running
if self.is_running().await {
bail!("Another instance of the client is already running");
}
// The temp file will be dropped automatically when the file handle is dropped // The temp file will be dropped automatically when the file handle is dropped
// So, declare it here to ensure it's not dropped // So, declare it here to ensure it's not dropped
let _file = self.fix_openssl()?; let _file = self.fix_openssl()?;

View File

@@ -87,8 +87,8 @@ pub(crate) struct ConnectArgs {
#[arg(long, value_enum, default_value_t = ConnectArgs::default_os())] #[arg(long, value_enum, default_value_t = ConnectArgs::default_os())]
os: Os, os: Os,
#[arg(long, default_value_t = ConnectArgs::default_os_version())] #[arg(long, help = "If not specified, it will be computed based on the --os option")]
os_version: String, os_version: Option<String>,
#[arg(long, help = "Disable DTLS and ESP")] #[arg(long, help = "Disable DTLS and ESP")]
no_dtls: bool, no_dtls: bool,
@@ -121,8 +121,12 @@ impl ConnectArgs {
} }
} }
fn default_os_version() -> String { fn os_version(&self) -> String {
match ConnectArgs::default_os() { if let Some(os_version) = self.os_version.as_deref() {
return os_version.to_string();
}
match self.os {
Os::Linux => format!("Linux {}", whoami::distro()), Os::Linux => format!("Linux {}", whoami::distro()),
Os::Windows => String::from("Microsoft Windows 11 Pro , 64-bit"), Os::Windows => String::from("Microsoft Windows 11 Pro , 64-bit"),
Os::Mac => String::from("Apple Mac OS X 13.4.0"), Os::Mac => String::from("Apple Mac OS X 13.4.0"),
@@ -149,7 +153,7 @@ impl<'a> ConnectHandler<'a> {
GpParams::builder() GpParams::builder()
.user_agent(&self.args.user_agent) .user_agent(&self.args.user_agent)
.client_os(ClientOs::from(&self.args.os)) .client_os(ClientOs::from(&self.args.os))
.os_version(self.args.os_version.clone()) .os_version(self.args.os_version())
.ignore_tls_errors(self.shared_args.ignore_tls_errors) .ignore_tls_errors(self.shared_args.ignore_tls_errors)
.certificate(self.args.certificate.clone()) .certificate(self.args.certificate.clone())
.sslkey(self.args.sslkey.clone()) .sslkey(self.args.sslkey.clone())
@@ -359,7 +363,7 @@ impl<'a> ConnectHandler<'a> {
None None
}; };
let os_version = self.args.os_version.clone(); let os_version = self.args.os_version();
let verbose = self.shared_args.verbose.to_verbose_arg(); let verbose = self.shared_args.verbose.to_verbose_arg();
let auth_launcher = SamlAuthLauncher::new(&self.args.server) let auth_launcher = SamlAuthLauncher::new(&self.args.server)
.gateway(is_gateway) .gateway(is_gateway)

View File

@@ -1,5 +1,9 @@
# Changelog # Changelog
## 2.4.3 - 2025-01-21
- Do not use static default value for `--os-version` option.
## 2.4.2 - 2025-01-20 ## 2.4.2 - 2025-01-20
- Disconnect the VPN when sleep (fix [#166](https://github.com/yuezk/GlobalProtect-openconnect/issues/166), [#267](https://github.com/yuezk/GlobalProtect-openconnect/issues/267)) - Disconnect the VPN when sleep (fix [#166](https://github.com/yuezk/GlobalProtect-openconnect/issues/166), [#267](https://github.com/yuezk/GlobalProtect-openconnect/issues/267))

View File

@@ -39,6 +39,9 @@ clap-verbosity-flag = { workspace = true, optional = true }
env_logger = { workspace = true, optional = true } env_logger = { workspace = true, optional = true }
log-reload = { version = "0.1", optional = true } log-reload = { version = "0.1", optional = true }
[target.'cfg(not(any(target_os="macos", target_os="windows")))'.dependencies]
gtk = "0.18"
[features] [features]
tauri = ["dep:tauri"] tauri = ["dep:tauri"]
clap = ["dep:clap", "dep:clap-verbosity-flag"] clap = ["dep:clap", "dep:clap-verbosity-flag"]

View File

@@ -41,12 +41,6 @@ pub fn patch_gui_runtime_env(hidpi: bool) {
// This is to avoid blank screen on some systems // This is to avoid blank screen on some systems
std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1"); std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
// Workaround for https://github.com/tauri-apps/tao/issues/929
let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland";
if is_wayland {
env::set_var("GDK_BACKEND", "x11");
}
if hidpi { if hidpi {
info!("Setting GDK_SCALE=2 and GDK_DPI_SCALE=0.5"); info!("Setting GDK_SCALE=2 and GDK_DPI_SCALE=0.5");
std::env::set_var("GDK_SCALE", "2"); std::env::set_var("GDK_SCALE", "2");

View File

@@ -1,73 +1,97 @@
use std::{process::ExitStatus, time::Duration};
use anyhow::bail;
use log::info;
use tauri::WebviewWindow; use tauri::WebviewWindow;
use tokio::process::Command;
pub trait WindowExt { pub trait WindowExt {
fn raise(&self) -> anyhow::Result<()>; fn raise(&self) -> anyhow::Result<()>;
} }
impl WindowExt for WebviewWindow { impl WindowExt for WebviewWindow {
#[cfg(any(target_os = "macos", target_os = "windows"))]
fn raise(&self) -> anyhow::Result<()> { fn raise(&self) -> anyhow::Result<()> {
raise_window(self) self.show()?;
Ok(())
}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
fn raise(&self) -> anyhow::Result<()> {
unix::raise_window(self)
} }
} }
pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> { #[cfg(not(any(target_os = "macos", target_os = "windows")))]
let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland"; mod unix {
use std::{process::ExitStatus, time::Duration};
if is_wayland { use anyhow::bail;
win.hide()?; use gtk::{
win.show()?; glib::Cast,
} else { traits::{EventBoxExt, GtkWindowExt, WidgetExt},
if !win.is_visible()? { EventBox,
win.show()?; };
} use log::info;
let title = win.title()?; use tauri::WebviewWindow;
tokio::spawn(async move { use tokio::process::Command;
if let Err(err) = wmctrl_raise_window(&title).await {
info!("Window not raised: {}", err); pub fn raise_window(win: &WebviewWindow) -> anyhow::Result<()> {
let is_wayland = std::env::var("XDG_SESSION_TYPE").unwrap_or_default() == "wayland";
if is_wayland {
let gtk_win = win.gtk_window()?;
if let Some(header) = gtk_win.titlebar() {
let _ = header.downcast::<EventBox>().map(|event_box| {
event_box.set_above_child(false);
});
} }
});
}
// Calling window.show() on Windows will cause the menu to be shown. gtk_win.hide();
// We need to hide it again. gtk_win.show_all();
win.hide_menu()?; } else {
if !win.is_visible()? {
Ok(()) win.show()?;
}
async fn wmctrl_raise_window(title: &str) -> anyhow::Result<()> {
let mut counter = 0;
loop {
if let Ok(exit_status) = wmctrl_try_raise_window(title).await {
if exit_status.success() {
info!("Window raised after {} attempts", counter + 1);
return Ok(());
} }
let title = win.title()?;
tokio::spawn(async move {
if let Err(err) = wmctrl_raise_window(&title).await {
info!("Window not raised: {}", err);
}
});
} }
if counter >= 10 { // Calling window.show() on window object will cause the menu to be shown.
bail!("Failed to raise window: {}", title) // We need to hide it again.
} win.hide_menu()?;
counter += 1; Ok(())
tokio::time::sleep(Duration::from_millis(100)).await; }
async fn wmctrl_raise_window(title: &str) -> anyhow::Result<()> {
let mut counter = 0;
loop {
if let Ok(exit_status) = wmctrl_try_raise_window(title).await {
if exit_status.success() {
info!("Window raised after {} attempts", counter + 1);
return Ok(());
}
}
if counter >= 10 {
bail!("Failed to raise window: {}", title)
}
counter += 1;
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
async fn wmctrl_try_raise_window(title: &str) -> anyhow::Result<ExitStatus> {
let exit_status = Command::new("wmctrl")
.arg("-F")
.arg("-a")
.arg(title)
.spawn()?
.wait()
.await?;
Ok(exit_status)
} }
} }
async fn wmctrl_try_raise_window(title: &str) -> anyhow::Result<ExitStatus> {
let exit_status = Command::new("wmctrl")
.arg("-F")
.arg("-a")
.arg(title)
.spawn()?
.wait()
.await?;
Ok(exit_status)
}

View File

@@ -6,7 +6,7 @@ Group: Productivity/Networking/PPP
License: GPL-3.0 License: GPL-3.0
URL: https://github.com/yuezk/GlobalProtect-openconnect URL: https://github.com/yuezk/GlobalProtect-openconnect
Source: %{name}.tar.gz Source: @SOURCE@
BuildRequires: make BuildRequires: make
BuildRequires: rust BuildRequires: rust

View File

@@ -28,7 +28,7 @@ release_snapshot() {
echo "Uploading new assets..." echo "Uploading new assets..."
gh -R "$REPO" release upload "$TAG" \ gh -R "$REPO" release upload "$TAG" \
"$PROJECT_DIR"/.build/artifacts/artifact-source/* \ "$PROJECT_DIR"/.build/artifacts/artifact-source*/* \
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/* "$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
} }
@@ -40,7 +40,7 @@ release_tag() {
gh -R "$REPO" release create $TAG \ gh -R "$REPO" release create $TAG \
--title "$TAG" \ --title "$TAG" \
--notes "$RELEASE_NOTES" \ --notes "$RELEASE_NOTES" \
"$PROJECT_DIR"/.build/artifacts/artifact-source/* \ "$PROJECT_DIR"/.build/artifacts/artifact-source*/* \
"$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/* "$PROJECT_DIR"/.build/artifacts/artifact-gpgui-*/*
} }