mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
Add Window methods Width(), Height(), Size() + Position()
Fix main thread locking issue Add Window aliases
This commit is contained in:
parent
ddb2f63f7b
commit
f6a16950f2
5 changed files with 195 additions and 45 deletions
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/exp/pkg/application"
|
||||
|
|
@ -63,10 +64,12 @@ func main() {
|
|||
println(myWindow.ID(), "WindowWillClose")
|
||||
})
|
||||
myWindow.On(events.Mac.WindowDidResize, func() {
|
||||
println(myWindow.ID(), "WindowDidResize")
|
||||
w, h := myWindow.Size()
|
||||
println(myWindow.ID(), "WindowDidResize", w, h)
|
||||
})
|
||||
myWindow.On(events.Mac.WindowDidMove, func() {
|
||||
println(myWindow.ID(), "WindowDidMove")
|
||||
x, y := myWindow.Position()
|
||||
println(myWindow.ID(), "WindowDidMove", x, y)
|
||||
})
|
||||
myWindow.On(events.Mac.WindowDidMiniaturize, func() {
|
||||
println(myWindow.ID(), "WindowDidMiniaturize")
|
||||
|
|
@ -112,36 +115,28 @@ func main() {
|
|||
})
|
||||
|
||||
var myWindow2 *application.Window
|
||||
go func() {
|
||||
time.Sleep(2 * time.Second)
|
||||
myWindow2 = app.NewWindow(&options.Window{
|
||||
Title: "#2",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AlwaysOnTop: false,
|
||||
URL: "https://google.com",
|
||||
DisableResize: true,
|
||||
Mac: &options.MacWindow{
|
||||
Backdrop: options.MacBackdropTranslucent,
|
||||
},
|
||||
})
|
||||
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(5 * time.Second)
|
||||
println("window 1 is fullscreen?", myWindow.IsFullscreen())
|
||||
println("window 2 is fullscreen?", myWindow2.IsFullscreen())
|
||||
println("window 1 is maximised?", myWindow.IsMaximised())
|
||||
println("window 2 is maximised?", myWindow2.IsMaximised())
|
||||
println("window 1 is minimised?", myWindow.IsMinimised())
|
||||
println("window 2 is minimised?", myWindow2.IsMinimised())
|
||||
}
|
||||
}()
|
||||
var myWindow2Lock sync.RWMutex
|
||||
myWindow2 = app.NewWindow(&options.Window{
|
||||
Title: "#2",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AlwaysOnTop: false,
|
||||
URL: "https://google.com",
|
||||
Mac: &options.MacWindow{
|
||||
Backdrop: options.MacBackdropTranslucent,
|
||||
},
|
||||
})
|
||||
//myWindow2.On(events.Mac.WindowDidMove, func() {
|
||||
// myWindow2Lock.RLock()
|
||||
// x, y := myWindow2.Position()
|
||||
// println(myWindow2.ID(), "WindowDidMove: ", x, y)
|
||||
// myWindow2Lock.RUnlock()
|
||||
//})
|
||||
//
|
||||
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
myWindow2Lock.RLock()
|
||||
myWindow.SetTitle("Wooooo")
|
||||
myWindow.SetAlwaysOnTop(true)
|
||||
myWindow2.EnableDevTools()
|
||||
|
|
@ -150,6 +145,7 @@ func main() {
|
|||
myWindow.SetMinSize(600, 600)
|
||||
myWindow.SetMaxSize(650, 650)
|
||||
myWindow.Center()
|
||||
myWindow2Lock.RUnlock()
|
||||
|
||||
}()
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,16 @@ package application
|
|||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/wailsapp/wails/exp/pkg/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
// Messages sent from javascript get routed here
|
||||
type windowMessage struct {
|
||||
windowId uint
|
||||
|
|
@ -22,8 +28,10 @@ type App struct {
|
|||
options *options.Application
|
||||
applicationEventListeners map[uint][]func()
|
||||
|
||||
windows map[uint]*Window
|
||||
windowAliases map[string]uint
|
||||
windows map[uint]*Window
|
||||
windowsLock sync.Mutex
|
||||
windowAliases map[string]uint
|
||||
windowAliasesLock sync.Mutex
|
||||
|
||||
// Running
|
||||
running bool
|
||||
|
|
@ -47,12 +55,17 @@ func (a *App) NewWindow(options *options.Window) *Window {
|
|||
if a.windows == nil {
|
||||
a.windows = make(map[uint]*Window)
|
||||
}
|
||||
a.windowsLock.Lock()
|
||||
a.windows[id] = newWindow
|
||||
a.windowsLock.Unlock()
|
||||
|
||||
if options.Alias != "" {
|
||||
if a.windowAliases == nil {
|
||||
a.windowAliases = make(map[string]uint)
|
||||
}
|
||||
a.windowAliasesLock.Lock()
|
||||
a.windowAliases[options.Alias] = id
|
||||
a.windowAliasesLock.Unlock()
|
||||
}
|
||||
if a.running {
|
||||
newWindow.Run()
|
||||
|
|
@ -93,7 +106,9 @@ func (a *App) Run() error {
|
|||
|
||||
func (a *App) handleMessage(event *windowMessage) {
|
||||
// Get window from window map
|
||||
a.windowsLock.Lock()
|
||||
window, ok := a.windows[event.windowId]
|
||||
a.windowsLock.Unlock()
|
||||
if !ok {
|
||||
log.Printf("Window #%d not found", event.windowId)
|
||||
return
|
||||
|
|
@ -104,7 +119,9 @@ func (a *App) handleMessage(event *windowMessage) {
|
|||
|
||||
func (a *App) handleWindowEvent(event *WindowEvent) {
|
||||
// Get window from window map
|
||||
a.windowsLock.Lock()
|
||||
window, ok := a.windows[event.WindowID]
|
||||
a.windowsLock.Unlock()
|
||||
if !ok {
|
||||
log.Printf("Window #%d not found", event.WindowID)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@ package application
|
|||
extern void dispatch(unsigned int id);
|
||||
*/
|
||||
import "C"
|
||||
import "strconv"
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var mainThreadFuntionStore = make(map[uint]func())
|
||||
var mainThreadFuntionStoreLock sync.RWMutex
|
||||
|
||||
func generateFunctionStoreID() uint {
|
||||
startID := 0
|
||||
|
|
@ -24,18 +28,23 @@ func generateFunctionStoreID() uint {
|
|||
}
|
||||
|
||||
func Dispatch(fn func()) {
|
||||
mainThreadFuntionStoreLock.Lock()
|
||||
id := generateFunctionStoreID()
|
||||
mainThreadFuntionStore[id] = fn
|
||||
mainThreadFuntionStoreLock.Unlock()
|
||||
C.dispatch(C.uint(id))
|
||||
}
|
||||
|
||||
//export dispatchCallback
|
||||
func dispatchCallback(id C.uint) {
|
||||
|
||||
fn := mainThreadFuntionStore[uint(id)]
|
||||
func dispatchCallback(callbackID C.uint) {
|
||||
mainThreadFuntionStoreLock.RLock()
|
||||
id := uint(callbackID)
|
||||
fn := mainThreadFuntionStore[id]
|
||||
if fn == nil {
|
||||
panic("dispatchCallback called with invalid id " + strconv.Itoa(int(id)))
|
||||
println("***** dispatchCallback called with invalid id: ", id)
|
||||
os.Exit(1)
|
||||
}
|
||||
delete(mainThreadFuntionStore, id)
|
||||
mainThreadFuntionStoreLock.RUnlock()
|
||||
fn()
|
||||
delete(mainThreadFuntionStore, uint(id))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,14 +27,20 @@ type windowImpl interface {
|
|||
setBackgroundColor(color *options.RGBA)
|
||||
run()
|
||||
center()
|
||||
size() (int, int)
|
||||
width() int
|
||||
height() int
|
||||
position() (int, int)
|
||||
}
|
||||
|
||||
type Window struct {
|
||||
options *options.Window
|
||||
impl windowImpl
|
||||
id uint
|
||||
options *options.Window
|
||||
impl windowImpl
|
||||
implLock sync.RWMutex
|
||||
id uint
|
||||
|
||||
eventListeners map[uint][]func()
|
||||
eventListeners map[uint][]func()
|
||||
eventListenersLock sync.RWMutex
|
||||
}
|
||||
|
||||
var windowID uint
|
||||
|
|
@ -48,7 +54,6 @@ func getWindowID() uint {
|
|||
}
|
||||
|
||||
func NewWindow(options *options.Window) *Window {
|
||||
|
||||
return &Window{
|
||||
id: getWindowID(),
|
||||
options: options,
|
||||
|
|
@ -57,6 +62,8 @@ func NewWindow(options *options.Window) *Window {
|
|||
}
|
||||
|
||||
func (w *Window) SetTitle(title string) {
|
||||
w.implLock.RLock()
|
||||
defer w.implLock.RUnlock()
|
||||
if w.impl == nil {
|
||||
w.options.Title = title
|
||||
return
|
||||
|
|
@ -74,7 +81,9 @@ func (w *Window) SetSize(width, height int) {
|
|||
}
|
||||
|
||||
func (w *Window) Run() {
|
||||
w.implLock.Lock()
|
||||
w.impl = newWindowImpl(w.id, w.options)
|
||||
w.implLock.Unlock()
|
||||
w.impl.run()
|
||||
}
|
||||
|
||||
|
|
@ -191,8 +200,18 @@ func (w *Window) IsMaximised() bool {
|
|||
return w.impl.isMaximised()
|
||||
}
|
||||
|
||||
// Size returns the current size of the window
|
||||
func (w *Window) Size() (int, int) {
|
||||
if w.impl == nil {
|
||||
return 0, 0
|
||||
}
|
||||
return w.impl.size()
|
||||
}
|
||||
|
||||
// IsFullscreen returns true if the window is fullscreen
|
||||
func (w *Window) IsFullscreen() bool {
|
||||
w.implLock.RLock()
|
||||
defer w.implLock.RUnlock()
|
||||
if w.impl == nil {
|
||||
return false
|
||||
}
|
||||
|
|
@ -223,15 +242,42 @@ func (w *Window) Center() {
|
|||
}
|
||||
|
||||
func (w *Window) On(eventID uint, callback func()) {
|
||||
w.eventListenersLock.Lock()
|
||||
w.eventListeners[eventID] = append(w.eventListeners[eventID], callback)
|
||||
w.eventListenersLock.Unlock()
|
||||
}
|
||||
|
||||
func (w *Window) handleWindowEvent(id uint) {
|
||||
w.eventListenersLock.RLock()
|
||||
for _, callback := range w.eventListeners[id] {
|
||||
callback()
|
||||
go callback()
|
||||
}
|
||||
w.eventListenersLock.RUnlock()
|
||||
}
|
||||
|
||||
func (w *Window) ID() uint {
|
||||
return w.id
|
||||
}
|
||||
|
||||
func (w *Window) Width() int {
|
||||
if w.impl == nil {
|
||||
return 0
|
||||
}
|
||||
return w.impl.width()
|
||||
}
|
||||
|
||||
func (w *Window) Height() int {
|
||||
if w.impl == nil {
|
||||
return 0
|
||||
}
|
||||
return w.impl.height()
|
||||
}
|
||||
|
||||
func (w *Window) Position() (int, int) {
|
||||
w.implLock.RLock()
|
||||
defer w.implLock.RUnlock()
|
||||
if w.impl == nil {
|
||||
return 0, 0
|
||||
}
|
||||
return w.impl.position()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,8 +394,47 @@ void windowCenter(void* nsWindow) {
|
|||
});
|
||||
}
|
||||
|
||||
// Get the current size of the window
|
||||
void windowGetSize(void* nsWindow, int* width, int* height) {
|
||||
// get main window
|
||||
NSWindow* window = (NSWindow*)nsWindow;
|
||||
// get window frame
|
||||
NSRect frame = [window frame];
|
||||
// set width and height
|
||||
*width = frame.size.width;
|
||||
*height = frame.size.height;
|
||||
}
|
||||
|
||||
// Get window width
|
||||
int windowGetWidth(void* nsWindow) {
|
||||
// get main window
|
||||
NSWindow* window = (NSWindow*)nsWindow;
|
||||
// get window frame
|
||||
NSRect frame = [window frame];
|
||||
// return width
|
||||
return frame.size.width;
|
||||
}
|
||||
|
||||
// Get window height
|
||||
int windowGetHeight(void* nsWindow) {
|
||||
// get main window
|
||||
NSWindow* window = (NSWindow*)nsWindow;
|
||||
// get window frame
|
||||
NSRect frame = [window frame];
|
||||
// return height
|
||||
return frame.size.height;
|
||||
}
|
||||
|
||||
// Get window position
|
||||
void windowGetPosition(void* nsWindow, int* x, int* y) {
|
||||
// get main window
|
||||
NSWindow* window = (NSWindow*)nsWindow;
|
||||
// get window frame
|
||||
NSRect frame = [window frame];
|
||||
// set x and y
|
||||
*x = frame.origin.x;
|
||||
*y = frame.origin.y;
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
|
@ -511,6 +550,41 @@ func (w *macosWindow) enableDevTools() {
|
|||
C.windowEnableDevTools(w.nsWindow)
|
||||
}
|
||||
|
||||
func (w *macosWindow) size() (int, int) {
|
||||
var width, height C.int
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
Dispatch(func() {
|
||||
C.windowGetSize(w.nsWindow, &width, &height)
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
return int(width), int(height)
|
||||
}
|
||||
|
||||
func (w *macosWindow) width() int {
|
||||
var width C.int
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
Dispatch(func() {
|
||||
width = C.windowGetWidth(w.nsWindow)
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
return int(width)
|
||||
}
|
||||
func (w *macosWindow) height() int {
|
||||
var height C.int
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
Dispatch(func() {
|
||||
height = C.windowGetHeight(w.nsWindow)
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
return int(height)
|
||||
}
|
||||
|
||||
func (w *macosWindow) run() {
|
||||
Dispatch(func() {
|
||||
w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height))
|
||||
|
|
@ -575,6 +649,14 @@ func (w *macosWindow) setBackgroundColor(colour *options.RGBA) {
|
|||
C.webviewSetBackgroundColor(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha))
|
||||
}
|
||||
|
||||
func (w *macosWindow) Center() {
|
||||
C.windowCenter(w.nsWindow)
|
||||
func (w *macosWindow) position() (int, int) {
|
||||
var x, y C.int
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go Dispatch(func() {
|
||||
C.windowGetPosition(w.nsWindow, &x, &y)
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
return int(x), int(y)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue