5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 15:30:37 +08:00
wails/lib/renderer/bridge/bridge.go
RH12503 a1bd1013cb
Support for minimum and maximum window sizes (#612)
* add support for minimum and maximum window sizes

* attempt to fix windows

* bug fixes

* support min/max window sizes on Linux and Windows

* fix min/max window sizes on Linux

* formatting and comments

* fixes Windows DPI issue, clamps width/height values to min/max

* App can't go into full screen when max size is set for Mac

* fixed Linux maximum width/height on window maximize

* Revert "fixed Linux maximum width/height on window maximize"

This reverts commit 3f7ba8b264.

The fix glitches on PopOS

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
2021-04-02 16:14:09 +11:00

231 lines
6.0 KiB
Go

package renderer
import (
"encoding/json"
"fmt"
"net/http"
"sync"
"github.com/gorilla/websocket"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
)
type messageType int
const (
jsMessage messageType = iota
cssMessage
htmlMessage
notifyMessage
bindingMessage
callbackMessage
wailsRuntimeMessage
)
func (m messageType) toString() string {
return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
}
// Bridge is a backend that opens a local web server
// and renders the files over a websocket
type Bridge struct {
// Common
log *logger.CustomLogger
ipcManager interfaces.IPCManager
appConfig interfaces.AppConfig
eventManager interfaces.EventManager
bindingCache []string
// Bridge specific
server *http.Server
lock sync.Mutex
sessions map[string]*session
}
// Initialise the Bridge Renderer
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
h.sessions = map[string]*session{}
h.ipcManager = ipcManager
h.appConfig = appConfig
h.eventManager = eventManager
ipcManager.BindRenderer(h)
h.log = logger.NewCustomLogger("Bridge")
return nil
}
func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
if err != nil {
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
}
h.log.Infof("Connection from frontend accepted [%s].", conn.RemoteAddr().String())
h.startSession(conn)
}
func (h *Bridge) startSession(conn *websocket.Conn) {
s := newSession(conn,
h.bindingCache,
h.ipcManager,
logger.NewCustomLogger("BridgeSession"),
h.eventManager)
conn.SetCloseHandler(func(int, string) error {
h.log.Infof("Connection dropped [%s].", s.Identifier())
h.eventManager.Emit("wails:bridge:session:closed", s.Identifier())
h.lock.Lock()
defer h.lock.Unlock()
delete(h.sessions, s.Identifier())
return nil
})
h.lock.Lock()
defer h.lock.Unlock()
go s.start(len(h.sessions) == 0)
h.sessions[s.Identifier()] = s
}
// Run the app in Bridge mode!
func (h *Bridge) Run() error {
h.server = &http.Server{Addr: ":34115"}
http.HandleFunc("/bridge", h.wsBridgeHandler)
h.log.Info("Bridge mode started.")
h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
h.log.Fatal(err.Error())
}
return err
}
// NewBinding creates a new binding with the frontend
func (h *Bridge) NewBinding(methodName string) error {
h.bindingCache = append(h.bindingCache, methodName)
return nil
}
// SelectFile is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectFile(title string, filter string) string {
h.log.Warn("SelectFile() unsupported in bridge mode")
return ""
}
// SelectDirectory is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectDirectory() string {
h.log.Warn("SelectDirectory() unsupported in bridge mode")
return ""
}
// SelectSaveFile is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectSaveFile(title string, filter string) string {
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
return ""
}
// NotifyEvent notifies the frontend of an event
func (h *Bridge) NotifyEvent(event *messages.EventData) error {
// Look out! Nils about!
var err error
if event == nil {
err = fmt.Errorf("Sent nil event to renderer.webViewRenderer")
h.log.Error(err.Error())
return err
}
// Default data is a blank array
data := []byte("[]")
// Process event data
if event.Data != nil {
// Marshall the data
data, err = json.Marshal(event.Data)
if err != nil {
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
return err
}
}
// Double encode data to ensure everything is escaped correctly.
data, err = json.Marshal(string(data))
if err != nil {
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
return err
}
message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
dead := []*session{}
for _, session := range h.sessions {
err := session.evalJS(message, notifyMessage)
if err != nil {
h.log.Debugf("Failed to send message to %s - Removing listener : %v", session.Identifier(), err)
h.log.Infof("Connection from [%v] unresponsive - dropping", session.Identifier())
dead = append(dead, session)
}
}
h.lock.Lock()
defer h.lock.Unlock()
for _, session := range dead {
delete(h.sessions, session.Identifier())
}
return nil
}
// SetColour is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetColour(colour string) error {
h.log.WarnFields("SetColour ignored for Bridge more", logger.Fields{"col": colour})
return nil
}
// SetMinSize is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetMinSize(width, height int) {
h.log.Warn("SetMinSize() unsupported in bridge mode")
}
// SetMaxSize is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetMaxSize(width, height int) {
h.log.Warn("SetMaxSize() unsupported in bridge mode")
}
// Fullscreen is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) Fullscreen() {
h.log.Warn("Fullscreen() unsupported in bridge mode")
}
// UnFullscreen is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) UnFullscreen() {
h.log.Warn("UnFullscreen() unsupported in bridge mode")
}
// SetTitle is currently unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetTitle(title string) {
h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
}
// Close is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) Close() {
h.log.Debug("Shutting down")
for _, session := range h.sessions {
session.Shutdown()
}
err := h.server.Close()
if err != nil {
h.log.Errorf(err.Error())
}
}