Skip to content

Commit

Permalink
Merge pull request #1364 from cogentcore/defscreen
Browse files Browse the repository at this point in the history
Stage.Screen defaults to -1, is only used when set (0 or higher); other screen fixes
  • Loading branch information
kkoreilly authored Dec 10, 2024
2 parents affbc24 + 5d890cc commit 8b32ae0
Show file tree
Hide file tree
Showing 22 changed files with 170 additions and 147 deletions.
32 changes: 22 additions & 10 deletions core/mainstage.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ func (bd *Body) RunMainWindow() {
// on the [Stage]. It can not be called more than once for one app.
// For secondary stages, see [Stage.Run].
func (st *Stage) RunMain() {
if ExternalParent != nil {
st.Scene.Body.handleExternalParent()
return
}
st.Run()
Wait()
}

// ExternalParent is a parent widget external to this program.
// If it is set, calls to [Body.RunWindow] before [Wait] and
// calls to [Body.RunMainWindow] will add the [Body] to this
// calls to [Body.RunMainWindow] and [Stage.RunMain] will add the [Body] to this
// parent instead of creating a new window. It should typically not be
// used by end users; it is used in yaegicore and for pre-rendering apps
// as HTML that can be used as a preview and for SEO purposes.
Expand Down Expand Up @@ -178,11 +182,17 @@ func (st *Stage) firstWindowStages() *stages {
return ms
}

func (st *Stage) currentScreen() *system.Screen {
// targetScreen returns the screen to use for opening a new window
// based on Screen field, currentRenderWindow's screen, and a fallback
// default of Screen 0.
func (st *Stage) targetScreen() *system.Screen {
if st.Screen >= 0 && st.Screen < TheApp.NScreens() {
return TheApp.Screen(st.Screen)
}
if currentRenderWindow != nil {
return currentRenderWindow.SystemWindow.Screen()
}
return system.TheApp.Screen(0)
return TheApp.Screen(0)
}

// configMainStage does main-stage configuration steps
Expand Down Expand Up @@ -252,19 +262,19 @@ func (st *Stage) runWindow() *Stage {
}
if nsz != csz {
currentRenderWindow.SystemWindow.SetSize(nsz)
system.TheApp.GetScreens()
TheApp.GetScreens()
}
}
} else {
// on other platforms, we want extra space and a minimum window size
sz = sz.Add(image.Pt(20, 20))
screen := st.currentScreen()
screen := st.targetScreen()
if screen != nil {
st.SetScreen(screen.ScreenNumber)
if st.NewWindow && st.UseMinSize {
// we require windows to be at least 60% and no more than 80% of the
// screen size by default
scsz := screen.PixSize
scsz := screen.PixelSize
sz = image.Pt(max(sz.X, scsz.X*6/10), max(sz.Y, scsz.Y*6/10))
sz = image.Pt(min(sz.X, scsz.X*8/10), min(sz.Y, scsz.Y*8/10))
}
Expand Down Expand Up @@ -351,7 +361,7 @@ func (st *Stage) runDialog() *Stage {
sz.X = max(sz.X, minx)
}
sc.Events.startFocusFirst = true // popup dialogs always need focus
screen := st.currentScreen()
screen := st.targetScreen()
if screen != nil {
st.SetScreen(screen.ScreenNumber)
}
Expand Down Expand Up @@ -392,11 +402,13 @@ func (st *Stage) newRenderWindow() *renderWindow {
opts.Flags.SetFlag(!st.Resizable, system.FixedSize)
opts.Flags.SetFlag(st.Maximized, system.Maximized)
opts.Flags.SetFlag(st.Fullscreen, system.Fullscreen)
screen := st.targetScreen()
screenName := ""
if st.Screen > 0 {
screenName = TheApp.Screen(st.Screen).Name
if screen != nil {
screenName = screen.Name
}
wgp, screen := theWindowGeometrySaver.get(title, screenName)
var wgp *windowGeometry
wgp, screen = theWindowGeometrySaver.get(title, screenName)
if wgp != nil {
theWindowGeometrySaver.settingStart()
opts.Screen = screen.ScreenNumber
Expand Down
2 changes: 1 addition & 1 deletion core/renderwindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ func newRenderContext() *renderContext {
rc := &renderContext{}
scr := system.TheApp.Screen(0)
if scr != nil {
rc.geom.SetRect(image.Rectangle{Max: scr.PixSize})
rc.geom.SetRect(image.Rectangle{Max: scr.PixelSize})
rc.logicalDPI = scr.LogicalDPI
} else {
rc.geom = math32.Geom2DInt{Size: image.Pt(1080, 720)}
Expand Down
2 changes: 1 addition & 1 deletion core/scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func (sc *Scene) ResizeToContent(extra ...image.Point) {
return
}
go func() {
scsz := system.TheApp.Screen(0).PixSize
scsz := system.TheApp.Screen(0).PixelSize
sz := sc.contentSize(scsz)
if len(extra) == 1 {
sz = sz.Add(extra[0])
Expand Down
4 changes: 4 additions & 0 deletions core/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,10 @@ type DebugSettingsData struct { //types:add
// Print a trace of DND event handling
DNDTrace bool

// DisableWindowGeometrySaver disables the saving and loading of window geometry
// data to allow for easier testing of window manipulation code.
DisableWindowGeometrySaver bool

// Print a trace of Go language completion and lookup process
GoCompleteTrace bool

Expand Down
11 changes: 8 additions & 3 deletions core/stage.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,13 @@ type Stage struct { //types:add -setters
Title string

// Screen specifies the screen number on which a new window is opened
// by default on desktop platforms. 0 is the default primary screen.
// Use [TheApp].ScreenByName("name").ScreenNumber to get the number by name.
// The automatically saved user previous screen takes precedence.
// by default on desktop platforms. It defaults to -1, which indicates
// that the first window should open on screen 0 (the default primary
// screen) and any subsequent windows should open on the same screen as
// the currently active window. Regardless, the automatically saved last
// screen of a window with the same [Stage.Title] takes precedence if it exists;
// see the website documentation on window geometry saving for more information.
// Use [TheApp].ScreenByName("name").ScreenNumber to get the screen by name.
Screen int

// Modal, if true, blocks input to all other stages.
Expand Down Expand Up @@ -263,6 +267,7 @@ func (st *Stage) setType(typ StageTypes) *Stage {
st.Type = typ
st.UseMinSize = true
st.Resizable = true
st.Screen = -1
switch st.Type {
case WindowStage:
if !TheApp.Platform().IsMobile() {
Expand Down
14 changes: 9 additions & 5 deletions core/typegen.go

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions core/windowgeometry.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import (
"cogentcore.org/core/system"
)

// theWindowGeometrySaver is the manager of window geometry settings
var theWindowGeometrySaver = windowGeometrySaver{}
var (
// theWindowGeometrySaver is the manager of window geometry settings
theWindowGeometrySaver = windowGeometrySaver{}
)

// screenConfigGeometries has the window geometry data for different
// screen configurations, where a screen configuration is a specific
Expand Down Expand Up @@ -97,7 +99,7 @@ func (ws *windowGeometrySaver) init() {
// shouldSave returns whether the window geometry should be saved based on
// the platform: only for desktop native platforms.
func (ws *windowGeometrySaver) shouldSave() bool {
return !TheApp.Platform().IsMobile() && TheApp.Platform() != system.Offscreen
return !TheApp.Platform().IsMobile() && TheApp.Platform() != system.Offscreen && !DebugSettings.DisableWindowGeometrySaver
}

// resetCache resets the cache; call under mutex
Expand Down Expand Up @@ -483,5 +485,5 @@ func (wg *windowGeometry) String() string {

// constrainGeom constrains geometry based on screen params
func (wg *windowGeometry) constrainGeom(sc *system.Screen) {
wg.Pos, wg.Size = sc.ConstrainWinGeom(wg.Pos, wg.Size)
wg.Pos, wg.Size = sc.ConstrainWindowGeometry(wg.Pos, wg.Size)
}
6 changes: 3 additions & 3 deletions system/driver/android/android.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ func (a *App) MainUI(vm, jniEnv, ctx uintptr) error {
a.Scrn.Orientation = orientation

a.Scrn.DevicePixelRatio = 1
a.Scrn.PixSize = image.Pt(widthPx, heightPx)
a.Scrn.Geometry.Max = a.Scrn.PixSize
a.Scrn.PixelSize = image.Pt(widthPx, heightPx)
a.Scrn.Geometry.Max = a.Scrn.PixelSize

a.Scrn.PhysicalDPI = dpi
a.Scrn.LogicalDPI = dpi
Expand All @@ -365,7 +365,7 @@ func (a *App) MainUI(vm, jniEnv, ctx uintptr) error {
system.OnSystemWindowCreated <- struct{}{}
}

a.Draw.System.Renderer.SetSize(a.Scrn.PixSize)
a.Draw.System.Renderer.SetSize(a.Scrn.PixelSize)
a.Event.WindowResize()
case <-windowDestroyed:
// we need to set the size of the window to 0 so that it detects a size difference
Expand Down
4 changes: 2 additions & 2 deletions system/driver/android/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type App struct {

// InitGPU initializes WebGPU for the app.
func (a *App) InitGPU() {
a.GPU = gpu.NewGPU()
a.GPU = gpu.NewGPU(nil)
}

// DestroyGPU releases GPU things (the drawer of the window) for when the app becomes invisible
Expand Down Expand Up @@ -87,7 +87,7 @@ func (a *App) SetSystemWindow(winptr uintptr) error {
Window: unsafe.Pointer(winptr),
},
}
wsf := a.GPU.Instance.CreateSurface(wsd)
wsf := gpu.Instance().CreateSurface(wsd)
sf := gpu.NewSurface(a.GPU, wsf, image.Pt(512, 512), 1, gpu.UndefinedType) // placeholder size
a.Draw = gpudraw.NewDrawer(a.GPU, sf)

Expand Down
4 changes: 2 additions & 2 deletions system/driver/base/app_single.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type AppSingler interface {
Drawer() system.Drawer

// RenderGeom returns the actual effective geometry of the window used
// for rendering content, which may be different from {0, [system.Screen.PixSize]}
// for rendering content, which may be different from {0, [system.Screen.PixelSize]}
// due to insets caused by things like status bars and button overlays.
RenderGeom() math32.Geom2DInt
}
Expand All @@ -78,7 +78,7 @@ func (a *AppSingle[D, W]) RenderGeom() math32.Geom2DInt {
pos := image.Pt(a.Insets.Left, a.Insets.Top)
return math32.Geom2DInt{
Pos: pos,
Size: a.Scrn.PixSize.Sub(pos).Sub(image.Pt(a.Insets.Right, a.Insets.Bottom)),
Size: a.Scrn.PixelSize.Sub(pos).Sub(image.Pt(a.Insets.Right, a.Insets.Bottom)),
}
}

Expand Down
12 changes: 6 additions & 6 deletions system/driver/base/window_multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ type WindowMulti[A system.App, D system.Drawer] struct {
// WnSize is the size of the window in window manager coordinates
WnSize image.Point `label:"Window manager size"`

// PixSize is the pixel size of the window in raw display dots
PixSize image.Point `label:"Pixel size"`
// PixelSize is the pixel size of the window in raw display dots
PixelSize image.Point `label:"Pixel size"`

// FrameSize of the window frame: Min = left, top; Max = right, bottom.
FrameSize styles.Sides[int]
Expand All @@ -50,7 +50,7 @@ type WindowMulti[A system.App, D system.Drawer] struct {

// PhysicalDPI is the physical dots per inch of the screen,
// for generating true-to-physical-size output.
// It is computed as 25.4 * (PixSize.X / PhysicalSize.X)
// It is computed as 25.4 * (PixelSize.X / PhysicalSize.X)
// where 25.4 is the number of mm per inch.
PhysDPI float32 `label:"Physical DPI"`

Expand Down Expand Up @@ -78,7 +78,7 @@ func (w *WindowMulti[A, D]) Drawer() system.Drawer {
func (w *WindowMulti[A, D]) Size() image.Point {
// w.Mu.Lock() // this prevents race conditions but also locks up
// defer w.Mu.Unlock()
return w.PixSize
return w.PixelSize
}

func (w *WindowMulti[A, D]) WinSize() image.Point {
Expand Down Expand Up @@ -123,7 +123,7 @@ func (w *WindowMulti[A, D]) SetSize(sz image.Point) {
return
}
sc := w.This.Screen()
sz = sc.WinSizeFromPix(sz)
sz = sc.WindowSizeFromPixels(sz)
w.SetWinSize(sz)
}

Expand All @@ -139,7 +139,7 @@ func (w *WindowMulti[A, D]) SetGeometry(pos image.Point, sz image.Point, screen
return
}
sc := w.This.Screen()
sz = sc.WinSizeFromPix(sz)
sz = sc.WindowSizeFromPixels(sz)
w.SetWinSize(sz)
w.Pos = pos
}
Expand Down
8 changes: 4 additions & 4 deletions system/driver/base/window_single.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ func (w *WindowSingle[A]) Screen() *system.Screen {
func (w *WindowSingle[A]) Size() image.Point {
// w.Mu.Lock() // this prevents race conditions but also locks up
// defer w.Mu.Unlock()
return w.Screen().PixSize
return w.Screen().PixelSize
}

func (w *WindowSingle[A]) WinSize() image.Point {
// w.Mu.Lock() // this prevents race conditions but also locks up
// defer w.Mu.Unlock()
return w.Screen().PixSize
return w.Screen().PixelSize
}

func (w *WindowSingle[A]) Position(screen *system.Screen) image.Point {
Expand Down Expand Up @@ -85,14 +85,14 @@ func (w *WindowSingle[A]) SetWinSize(sz image.Point) {
if w.This.IsClosed() {
return
}
w.Screen().PixSize = sz
w.Screen().PixelSize = sz
}

func (w *WindowSingle[A]) SetSize(sz image.Point) {
if w.This.IsClosed() || (w.App.Platform().IsMobile() && w.App.Platform() != system.Offscreen) {
return
}
w.Screen().PixSize = sz
w.Screen().PixelSize = sz
}

func (w *WindowSingle[A]) SetPos(pos image.Point, screen *system.Screen) {
Expand Down
57 changes: 24 additions & 33 deletions system/driver/desktop/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,26 +100,24 @@ func (a *App) NewWindow(opts *system.NewWindowOptions) (system.Window, error) {
sc = a.Screens[opts.Screen]
}

var glw *glfw.Window
w := &Window{
WindowMulti: base.NewWindowMulti[*App, *gpudraw.Drawer](a, opts),
ScreenWindow: sc.Name,
}
w.This = w

var err error
a.RunOnMain(func() {
glw, err = NewGlfwWindow(opts, sc)
err = w.newGlfwWindow(opts, sc)
})
if err != nil {
return nil, err
}

w := &Window{
WindowMulti: base.NewWindowMulti[*App, *gpudraw.Drawer](a, opts),
Glw: glw,
ScreenWindow: sc.Name,
}
w.This = w

a.RunOnMain(func() {
surf := gpu.Instance().CreateSurface(wgpuglfw.GetSurfaceDescriptor(glw))
surf := gpu.Instance().CreateSurface(wgpuglfw.GetSurfaceDescriptor(w.Glw))
var fbsz image.Point
fbsz.X, fbsz.Y = glw.GetFramebufferSize()
fbsz.X, fbsz.Y = w.Glw.GetFramebufferSize()
if fbsz == (image.Point{}) {
fbsz = opts.Size
}
Expand All @@ -137,32 +135,25 @@ func (a *App) NewWindow(opts *system.NewWindowOptions) (system.Window, error) {
a.Windows = append(a.Windows, w)
a.Mu.Unlock()

glw.SetPosCallback(w.Moved)
glw.SetSizeCallback(w.WinResized)
glw.SetFramebufferSizeCallback(w.FbResized)
glw.SetCloseCallback(w.OnCloseReq)
// glw.SetRefreshCallback(w.refresh)
glw.SetFocusCallback(w.Focused)
glw.SetIconifyCallback(w.Iconify)

glw.SetKeyCallback(w.KeyEvent)
glw.SetCharModsCallback(w.CharEvent)
glw.SetMouseButtonCallback(w.MouseButtonEvent)
glw.SetScrollCallback(w.ScrollEvent)
glw.SetCursorPosCallback(w.CursorPosEvent)
glw.SetCursorEnterCallback(w.CursorEnterEvent)
glw.SetDropCallback(w.DropEvent)
w.Glw.SetPosCallback(w.Moved)
w.Glw.SetSizeCallback(w.WinResized)
w.Glw.SetFramebufferSizeCallback(w.FbResized)
w.Glw.SetCloseCallback(w.OnCloseReq)
// w.Glw.SetRefreshCallback(w.refresh)
w.Glw.SetFocusCallback(w.Focused)
w.Glw.SetIconifyCallback(w.Iconify)

w.Glw.SetKeyCallback(w.KeyEvent)
w.Glw.SetCharModsCallback(w.CharEvent)
w.Glw.SetMouseButtonCallback(w.MouseButtonEvent)
w.Glw.SetScrollCallback(w.ScrollEvent)
w.Glw.SetCursorPosCallback(w.CursorPosEvent)
w.Glw.SetCursorEnterCallback(w.CursorEnterEvent)
w.Glw.SetDropCallback(w.DropEvent)

w.Show()
a.RunOnMain(func() {
w.updateGeometry()
zp := image.Point{}
if w.Pos == zp && opts.Pos != zp {
w.Pos = opts.Pos
}
if w.WnSize == zp && opts.Size != zp {
w.WnSize = opts.Size
}
w.ConstrainFrame(false) // constrain full frame on open
})

Expand Down
Loading

0 comments on commit 8b32ae0

Please sign in to comment.