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