github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/frontend/desktop/linux/single_instance.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package linux
     5  
     6  import (
     7  	"encoding/json"
     8  	"github.com/AlpineAIO/wails/v2/pkg/options"
     9  	"github.com/godbus/dbus/v5"
    10  	"log"
    11  	"os"
    12  	"strings"
    13  )
    14  
    15  type dbusHandler func(string)
    16  
    17  func (f dbusHandler) SendMessage(message string) *dbus.Error {
    18  	f(message)
    19  	return nil
    20  }
    21  
    22  func SetupSingleInstance(uniqueID string) {
    23  	id := "wails_app_" + strings.ReplaceAll(strings.ReplaceAll(uniqueID, "-", "_"), ".", "_")
    24  
    25  	dbusName := "org." + id + ".SingleInstance"
    26  	dbusPath := "/org/" + id + "/SingleInstance"
    27  
    28  	conn, err := dbus.ConnectSessionBus()
    29  	// if we will reach any error during establishing connection or sending message we will just continue.
    30  	// It should not be the case that such thing will happen actually, but just in case.
    31  	if err != nil {
    32  		return
    33  	}
    34  
    35  	f := dbusHandler(func(message string) {
    36  		var secondInstanceData options.SecondInstanceData
    37  
    38  		err := json.Unmarshal([]byte(message), &secondInstanceData)
    39  		if err == nil {
    40  			secondInstanceBuffer <- secondInstanceData
    41  		}
    42  	})
    43  
    44  	err = conn.Export(f, dbus.ObjectPath(dbusPath), dbusName)
    45  	if err != nil {
    46  		return
    47  	}
    48  
    49  	reply, err := conn.RequestName(dbusName, dbus.NameFlagDoNotQueue)
    50  	if err != nil {
    51  		return
    52  	}
    53  
    54  	// if name already taken, try to send args to existing instance, if no success just launch new instance
    55  	if reply == dbus.RequestNameReplyExists {
    56  		data := options.SecondInstanceData{
    57  			Args: os.Args[1:],
    58  		}
    59  		data.WorkingDirectory, err = os.Getwd()
    60  		if err != nil {
    61  			log.Printf("Failed to get working directory: %v", err)
    62  			return
    63  		}
    64  
    65  		serialized, err := json.Marshal(data)
    66  		if err != nil {
    67  			log.Printf("Failed to marshal data: %v", err)
    68  			return
    69  		}
    70  
    71  		err = conn.Object(dbusName, dbus.ObjectPath(dbusPath)).Call(dbusName+".SendMessage", 0, string(serialized)).Store()
    72  		if err != nil {
    73  			return
    74  		}
    75  		os.Exit(1)
    76  	}
    77  }