mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
[v3] Add single_instance plugin
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
version: '3'
|
||||
|
||||
tasks:
|
||||
|
||||
pre-build:
|
||||
summary: Pre-build hooks
|
||||
|
||||
post-build:
|
||||
summary: Post-build hooks
|
||||
|
||||
build:
|
||||
summary: Builds the application
|
||||
cmds:
|
||||
- task: pre-build
|
||||
- go build -gcflags=all="-N -l" -o bin/testapp main.go
|
||||
- task: post-build
|
||||
env:
|
||||
CGO_CFLAGS: "-mmacosx-version-min=10.13"
|
||||
CGO_LDFLAGS: "-mmacosx-version-min=10.13"
|
||||
|
||||
generate-icons:
|
||||
summary: Generates Windows `.ico` and Mac `.icns` files from an image
|
||||
cmds:
|
||||
# Generates both .ico and .icns files
|
||||
- wails generate icons -input build/appicon.png
|
||||
|
||||
build-prod:
|
||||
summary: Creates a production build of the application
|
||||
cmds:
|
||||
- go build -tags production -ldflags="-w -s" -o bin/testapp
|
||||
|
||||
package-darwin:
|
||||
summary: Packages a production build of the application into a `.app` bundle
|
||||
deps:
|
||||
- build-prod
|
||||
- generate-icons
|
||||
cmds:
|
||||
- mkdir -p buildtest.app/Contents/{MacOS,Resources}
|
||||
- cp build/icons.icns buildtest.app/Contents/Resources
|
||||
- cp bin/testapp buildtest.app/Contents/MacOS
|
||||
- cp build/Info.plist buildtest.app/Contents
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>My App</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>app</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.app</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>v1.0.0</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>The ultimate thing</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>v1</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icons</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>true</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>(c) Me</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>My App</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>testapp</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.app</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>v1.0.0</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>The ultimate thing</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>v1</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icons</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>true</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>(c) Me</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"fixed": {
|
||||
"file_version": "v1.0.0"
|
||||
},
|
||||
"info": {
|
||||
"0000": {
|
||||
"ProductVersion": "v1.0.0",
|
||||
"CompanyName": "My Company Name",
|
||||
"FileDescription": "A thing that does a thing",
|
||||
"LegalCopyright": "(c) 2023 My Company Name",
|
||||
"ProductName": "My Product Name",
|
||||
"Comments": "This is a comment"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity type="win32" name="com.wails.myproductname" version="v1.0.0.0" processorArchitecture="*"/>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- fallback for Windows 7 and 8 -->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to per-monitor if per-monitor v2 is not supported -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
@@ -3,7 +3,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
@@ -15,6 +17,7 @@ github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5Az
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
@@ -58,6 +61,8 @@ modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||
modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
@@ -70,5 +75,7 @@ modernc.org/sqlite v1.21.0 h1:4aP4MdUf15i3R3M2mx6Q90WHKz3nZLoz96zlB6tNdow=
|
||||
modernc.org/sqlite v1.21.0/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/wailsapp/wails/v3/plugins/browser"
|
||||
"github.com/wailsapp/wails/v3/plugins/kvstore"
|
||||
"github.com/wailsapp/wails/v3/plugins/log"
|
||||
"github.com/wailsapp/wails/v3/plugins/single_instance"
|
||||
"github.com/wailsapp/wails/v3/plugins/sqlite"
|
||||
"os"
|
||||
"plugin_demo/plugins/hashes"
|
||||
@@ -31,6 +32,10 @@ func main() {
|
||||
Filename: "store.json",
|
||||
AutoSave: true,
|
||||
}),
|
||||
"single_instance": single_instance.NewPlugin(&single_instance.Config{
|
||||
// When true, the original app will be activated when a second instance is launched
|
||||
ActivateAppOnSubsequentLaunch: true,
|
||||
}),
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
|
||||
@@ -37,6 +37,7 @@ func New(appOptions Options) *App {
|
||||
systemTrays: make(map[uint]*SystemTray),
|
||||
log: logger.New(appOptions.Logger.CustomLoggers...),
|
||||
contextMenus: make(map[string]*Menu),
|
||||
pid: os.Getpid(),
|
||||
}
|
||||
globalApplication = result
|
||||
|
||||
@@ -187,6 +188,7 @@ type App struct {
|
||||
|
||||
// Hooks
|
||||
windowCreatedCallbacks []func(window *WebviewWindow)
|
||||
pid int
|
||||
}
|
||||
|
||||
func (a *App) getSystemTrayID() uint {
|
||||
@@ -215,6 +217,10 @@ func (a *App) NewWebviewWindow() *WebviewWindow {
|
||||
return a.NewWebviewWindowWithOptions(nil)
|
||||
}
|
||||
|
||||
func (a *App) GetPID() int {
|
||||
return a.pid
|
||||
}
|
||||
|
||||
func (a *App) info(message string, args ...any) {
|
||||
a.Log(&logger.Message{
|
||||
Level: "INFO",
|
||||
@@ -458,7 +464,9 @@ func (a *App) Quit() {
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Wait()
|
||||
a.impl.destroy()
|
||||
if a.impl != nil {
|
||||
a.impl.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) SetMenu(menu *Menu) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# single-instance Plugin
|
||||
|
||||
This example plugin provides a way to generate hashes of strings.
|
||||
|
||||
## Installation
|
||||
|
||||
Add the plugin to the `Plugins` option in the Applications options:
|
||||
|
||||
```go
|
||||
Plugins: map[string]application.Plugin{
|
||||
"single_instance": single_instance.NewPlugin(&single_instance.Config{
|
||||
// When true, the original app will be activated when a second instance is launched
|
||||
ActivateAppOnSubsequentLaunch: true,
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
This plugin prevents the launch of multiple copies of your application.
|
||||
If you set `ActivateAppOnSubsequentLaunch` to true the original app will be activated when a second instance is launched.
|
||||
|
||||
## Support
|
||||
|
||||
If you find a bug in this plugin, please raise a ticket [here](https://github.com/plugin/repository).
|
||||
Please do not contact the Wails team for support.
|
||||
|
||||
## Credit
|
||||
|
||||
This plugin contains modified code from the awesome [go-singleinstance](https://github.com/allan-simon/go-singleinstance) module (c) 2015 Allan Simon.
|
||||
Original license file has been renamed `go-singleinstance.LICENSE` and is available [here](./singleinstance_LICENSE).
|
||||
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Allan Simon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package single_instance
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GetLockFilePid(filename string) (pid int, err error) {
|
||||
contents, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pid, err = strconv.Atoi(string(contents))
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//go:build !windows
|
||||
|
||||
package single_instance
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// CreateLockFile tries to create a file with given name and acquire an
|
||||
// exclusive lock on it. If the file already exists AND is still locked, it will
|
||||
// fail.
|
||||
func CreateLockFile(filename string, PID int) (*os.File, error) {
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
|
||||
if err != nil {
|
||||
file.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Write PID to lock file
|
||||
contents := strconv.Itoa(PID)
|
||||
if err := file.Truncate(0); err != nil {
|
||||
file.Close()
|
||||
return nil, err
|
||||
}
|
||||
if _, err := file.WriteString(contents); err != nil {
|
||||
file.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//go:build windows
|
||||
|
||||
package single_instance
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// CreateLockFile tries to create a file with given name and acquire an
|
||||
// exclusive lock on it. If the file already exists AND is still locked, it will
|
||||
// fail.
|
||||
func CreateLockFile(filename string, PID int) (*os.File, error) {
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
// If the file exists, we first try to remove it
|
||||
if err = os.Remove(filename); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Write PID to lock file
|
||||
_, err = file.WriteString(strconv.Itoa(PID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package single_instance
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
// Add any configuration options here
|
||||
LockFileName string
|
||||
LockFilePath string
|
||||
ActivateAppOnSubsequentLaunch bool
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
config *Config
|
||||
app *application.App
|
||||
lockfile *os.File
|
||||
}
|
||||
|
||||
func (p *Plugin) CallableByJS() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (p *Plugin) InjectJS() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func NewPlugin(config *Config) *Plugin {
|
||||
if config.LockFilePath == "" {
|
||||
// Use the system default temp directory
|
||||
config.LockFilePath = os.TempDir()
|
||||
}
|
||||
if config.LockFileName == "" {
|
||||
// Use the executable name
|
||||
config.LockFileName = filepath.Base(os.Args[0]) + ".lock"
|
||||
}
|
||||
return &Plugin{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown is called when the app is shutting down
|
||||
func (p *Plugin) Shutdown() {
|
||||
p.lockfile.Close()
|
||||
}
|
||||
|
||||
// Name returns the name of the plugin.
|
||||
func (p *Plugin) Name() string {
|
||||
return "github.com/wailsapp/wails/v3/plugins/single-instance"
|
||||
}
|
||||
|
||||
// Init is called when the app is starting up. You can use this to
|
||||
// initialise any resources you need. You can also access the application
|
||||
// instance via the app property.
|
||||
func (p *Plugin) Init(app *application.App) error {
|
||||
p.app = app
|
||||
|
||||
var err error
|
||||
lockfileName := p.config.LockFilePath + "/" + p.config.LockFileName
|
||||
p.lockfile, err = CreateLockFile(lockfileName, p.app.GetPID())
|
||||
if err != nil {
|
||||
if p.config.ActivateAppOnSubsequentLaunch {
|
||||
pid, err := GetLockFilePid(lockfileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.activeInstance(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exported returns a list of exported methods that can be called from the frontend
|
||||
func (p *Plugin) Exported() []string {
|
||||
return []string{}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# This is the plugin definition file for the "single-instance" plugin.
|
||||
|
||||
Name = "single-instance"
|
||||
Description = "Allows only a single instance of your application to run"
|
||||
Author = "Lea Anthony"
|
||||
Version = "v1.0.0"
|
||||
Website = "https://wails.io"
|
||||
Repository = "https://github.com/wailsapp/wails/v3/plugins/single-instance
|
||||
License = "MIT"
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//go:build darwin
|
||||
|
||||
package single_instance
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c
|
||||
#cgo LDFLAGS: -framework Cocoa -framework AppKit -mmacosx-version-min=10.13
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
void activateApplicationWithProcessID(int pid) {
|
||||
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
|
||||
if (app != nil) {
|
||||
[app unhide];
|
||||
[app activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
|
||||
}
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func (p *Plugin) activeInstance(pid int) error {
|
||||
C.activateApplicationWithProcessID(C.int(pid))
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user