Fix x/window.go
This commit is contained in:
parent
ee64650c19
commit
b58932f02b
121
x/window.go
121
x/window.go
@ -1,6 +1,7 @@
|
|||||||
package x
|
package x
|
||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
import "git.tebibyte.media/tomo/tomo"
|
import "git.tebibyte.media/tomo/tomo"
|
||||||
import "git.tebibyte.media/tomo/tomo/data"
|
import "git.tebibyte.media/tomo/tomo/data"
|
||||||
@ -41,7 +42,10 @@ type window struct {
|
|||||||
innerBounds image.Rectangle // bounds of the drawable area
|
innerBounds image.Rectangle // bounds of the drawable area
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose event.FuncBroadcaster
|
on struct {
|
||||||
|
close event.FuncBroadcaster
|
||||||
|
tryClose event.Broadcaster[func () bool]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type windowLink struct {
|
type windowLink struct {
|
||||||
@ -64,27 +68,12 @@ func (this *windowLink) NotifyMinimumSizeChange () {
|
|||||||
this.window.doMinimumSize()
|
this.window.doMinimumSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Backend) NewWindow (
|
func (this *Backend) NewWindow (kind tomo.WindowKind, bounds image.Rectangle) (tomo.Window, error) {
|
||||||
bounds image.Rectangle,
|
|
||||||
) (
|
|
||||||
output tomo.Window,
|
|
||||||
err error,
|
|
||||||
) {
|
|
||||||
this.assert()
|
|
||||||
return this.newWindow(bounds, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *Backend) NewPlainWindow (
|
|
||||||
bounds image.Rectangle,
|
|
||||||
) (
|
|
||||||
output tomo.Window,
|
|
||||||
err error,
|
|
||||||
) {
|
|
||||||
this.assert()
|
this.assert()
|
||||||
window, err := this.newWindow(bounds, false)
|
window, err := this.newWindow(bounds, false)
|
||||||
window.setType("dock")
|
if err != nil { return nil, err }
|
||||||
|
window.setKind(kind)
|
||||||
return window, err
|
return window, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Backend) newWindow (
|
func (this *Backend) newWindow (
|
||||||
@ -131,7 +120,11 @@ func (this *Backend) newWindow (
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
|
||||||
window.xWindow.WMGracefulClose (func (xWindow *xwindow.Window) {
|
window.xWindow.WMGracefulClose (func (xWindow *xwindow.Window) {
|
||||||
window.Close()
|
holdOff := false
|
||||||
|
for _, callback := range window.on.tryClose.Listeners() {
|
||||||
|
if !callback() { holdOff = true }
|
||||||
|
}
|
||||||
|
if !holdOff { window.Close() }
|
||||||
})
|
})
|
||||||
|
|
||||||
xevent.ExposeFun(window.handleExpose).
|
xevent.ExposeFun(window.handleExpose).
|
||||||
@ -247,56 +240,29 @@ func (this *window) SetBounds (bounds image.Rectangle) {
|
|||||||
bounds.Min.Y + bounds.Dy())
|
bounds.Min.Y + bounds.Dy())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *window) NewChild (bounds image.Rectangle) (tomo.Window, error) {
|
func (this *window) NewChild (kind tomo.WindowKind, bounds image.Rectangle) (tomo.Window, error) {
|
||||||
leader := this.leader
|
leader := this.leader
|
||||||
|
|
||||||
child, err := this.backend.newWindow (
|
child, err := this.backend.newWindow (
|
||||||
bounds.Add(this.metrics.innerBounds.Min), false)
|
bounds.Add(this.metrics.innerBounds.Min), false)
|
||||||
child.leader = leader
|
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
child.setClientLeader(leader)
|
child.leader = leader
|
||||||
leader.setClientLeader(leader)
|
err = child.setKind(kind)
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
if kind == tomo.WindowKindModal {
|
||||||
|
this.hasModal = true
|
||||||
|
child.modalParent = this
|
||||||
|
}
|
||||||
|
|
||||||
icccm.WmTransientForSet (
|
icccm.WmTransientForSet (
|
||||||
this.backend.x,
|
this.backend.x,
|
||||||
child.xWindow.Id,
|
child.xWindow.Id,
|
||||||
leader.xWindow.Id)
|
leader.xWindow.Id)
|
||||||
child.setType("UTILITY")
|
|
||||||
// child.inheritProperties(leader.window)
|
// child.inheritProperties(leader.window)
|
||||||
return child, err
|
return child, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *window) NewMenu (bounds image.Rectangle) (tomo.Window, error) {
|
|
||||||
menu, err := this.backend.newWindow (
|
|
||||||
bounds.Add(this.metrics.innerBounds.Min), true)
|
|
||||||
menu.shy = true
|
|
||||||
icccm.WmTransientForSet (
|
|
||||||
this.backend.x,
|
|
||||||
menu.xWindow.Id,
|
|
||||||
this.xWindow.Id)
|
|
||||||
menu.setType("POPUP_MENU")
|
|
||||||
// menu.inheritProperties(this)
|
|
||||||
return menu, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *window) NewModal (bounds image.Rectangle) (tomo.Window, error) {
|
|
||||||
modal, err := this.backend.newWindow (
|
|
||||||
bounds.Add(this.metrics.innerBounds.Min), false)
|
|
||||||
icccm.WmTransientForSet (
|
|
||||||
this.backend.x,
|
|
||||||
modal.xWindow.Id,
|
|
||||||
this.xWindow.Id)
|
|
||||||
ewmh.WmStateSet (
|
|
||||||
this.backend.x,
|
|
||||||
modal.xWindow.Id,
|
|
||||||
[]string { "_NET_WM_STATE_MODAL" })
|
|
||||||
modal.modalParent = this
|
|
||||||
this.hasModal = true
|
|
||||||
// modal.inheritProperties(window)
|
|
||||||
return modal, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *window) Modifiers () input.Modifiers {
|
func (this *window) Modifiers () input.Modifiers {
|
||||||
return this.hierarchy.Modifiers()
|
return this.hierarchy.Modifiers()
|
||||||
}
|
}
|
||||||
@ -330,12 +296,12 @@ func (this *window) Visible () bool {
|
|||||||
return this.visible
|
return this.visible
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *window) Close () {
|
func (this *window) Close () error {
|
||||||
xevent .Detach(this.backend.x, this.xWindow.Id)
|
xevent .Detach(this.backend.x, this.xWindow.Id)
|
||||||
keybind .Detach(this.backend.x, this.xWindow.Id)
|
keybind .Detach(this.backend.x, this.xWindow.Id)
|
||||||
mousebind.Detach(this.backend.x, this.xWindow.Id)
|
mousebind.Detach(this.backend.x, this.xWindow.Id)
|
||||||
|
|
||||||
this.onClose.Broadcast()
|
this.on.close.Broadcast()
|
||||||
if this.modalParent != nil {
|
if this.modalParent != nil {
|
||||||
// we are a modal dialog, so unlock the parent
|
// we are a modal dialog, so unlock the parent
|
||||||
this.modalParent.hasModal = false
|
this.modalParent.hasModal = false
|
||||||
@ -345,10 +311,15 @@ func (this *window) Close () {
|
|||||||
delete(this.backend.windows, this.xWindow.Id)
|
delete(this.backend.windows, this.xWindow.Id)
|
||||||
this.xWindow.Destroy()
|
this.xWindow.Destroy()
|
||||||
this.hierarchy.Close()
|
this.hierarchy.Close()
|
||||||
|
return nil // TODO maybe return an error? maybe join them?
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *window) OnClose (callback func ()) event.Cookie {
|
func (this *window) OnClose (callback func ()) event.Cookie {
|
||||||
return this.onClose.Connect(callback)
|
return this.on.close.Connect(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *window) OnTryClose (callback func () bool) event.Cookie {
|
||||||
|
return this.on.tryClose.Connect(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *window) grabInput () {
|
func (this *window) grabInput () {
|
||||||
@ -364,6 +335,19 @@ func (this *window) ungrabInput () {
|
|||||||
mousebind.UngrabPointer(this.backend.x)
|
mousebind.UngrabPointer(this.backend.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *window) setKind (kind tomo.WindowKind) error {
|
||||||
|
err := this.setType(windowKindToType(kind))
|
||||||
|
if err != nil { return err }
|
||||||
|
if kind == tomo.WindowKindModal {
|
||||||
|
err = this.setState("MODAL")
|
||||||
|
if err != nil { return err }
|
||||||
|
}
|
||||||
|
if kind == tomo.WindowKindMenu {
|
||||||
|
this.shy = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (this *window) setType (ty string) error {
|
func (this *window) setType (ty string) error {
|
||||||
return ewmh.WmWindowTypeSet (
|
return ewmh.WmWindowTypeSet (
|
||||||
this.backend.x,
|
this.backend.x,
|
||||||
@ -371,6 +355,13 @@ func (this *window) setType (ty string) error {
|
|||||||
[]string { "_NET_WM_WINDOW_TYPE_" + ty })
|
[]string { "_NET_WM_WINDOW_TYPE_" + ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *window) setState (state string) error {
|
||||||
|
return ewmh.WmStateSet (
|
||||||
|
this.backend.x,
|
||||||
|
this.xWindow.Id,
|
||||||
|
[]string { "_NET_WM_STATE_" + state })
|
||||||
|
}
|
||||||
|
|
||||||
func (this *window) setClientLeader (leader *window) error {
|
func (this *window) setClientLeader (leader *window) error {
|
||||||
hints, _ := icccm.WmHintsGet(this.backend.x, this.xWindow.Id)
|
hints, _ := icccm.WmHintsGet(this.backend.x, this.xWindow.Id)
|
||||||
if hints == nil {
|
if hints == nil {
|
||||||
@ -476,3 +467,15 @@ func (this *window) doMinimumSize () {
|
|||||||
this.xWindow.Resize(newWidth, newHeight)
|
this.xWindow.Resize(newWidth, newHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func windowKindToType (kind tomo.WindowKind) string {
|
||||||
|
switch kind {
|
||||||
|
case tomo.WindowKindNormal: return "NORMAL"
|
||||||
|
case tomo.WindowKindPlain: return "DOCK"
|
||||||
|
case tomo.WindowKindUtility: return "UTILITY"
|
||||||
|
case tomo.WindowKindToolbar: return "TOOLBAR"
|
||||||
|
case tomo.WindowKindMenu: return "POPUP_MENU"
|
||||||
|
case tomo.WindowKindModal: return "NORMAL"
|
||||||
|
default: return strings.ReplaceAll(strings.ToUpper(string(kind)), " ", "_")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user