This repository has been archived on 2024-06-02. You can view files and clone it, but cannot push or open issues or pull requests.
x/event.go

139 lines
3.4 KiB
Go

package x
import "image"
import "github.com/jezek/xgbutil"
import "github.com/jezek/xgb/xproto"
import "github.com/jezek/xgbutil/xevent"
func (window *window) handleExpose (
connection *xgbutil.XUtil,
event xevent.ExposeEvent,
) {
if window.xCanvas == nil {
window.reallocateCanvas()
}
window.compressExpose(*event.ExposeEvent)
window.pushAll()
}
func (window *window) updateBounds () {
// FIXME: some window managers parent windows more than once, we might
// need to sum up all their positions.
decorGeometry, _ := window.xWindow.DecorGeometry()
windowGeometry, _ := window.xWindow.Geometry()
origin := image.Pt(
windowGeometry.X() + decorGeometry.X(),
windowGeometry.Y() + decorGeometry.Y())
window.metrics.bounds = image.Rectangle {
Min: origin,
Max: origin.Add(image.Pt(windowGeometry.Width(), windowGeometry.Height())),
}
}
func (window *window) handleConfigureNotify (
connection *xgbutil.XUtil,
event xevent.ConfigureNotifyEvent,
) {
if window.root == nil { return }
configureEvent := *event.ConfigureNotifyEvent
newWidth := int(configureEvent.Width)
newHeight := int(configureEvent.Height)
sizeChanged :=
window.metrics.bounds.Dx() != newWidth ||
window.metrics.bounds.Dy() != newHeight
window.updateBounds()
if sizeChanged {
configureEvent = window.compressConfigureNotify(configureEvent)
window.reallocateCanvas()
// TODO figure out what to do with this
// if !window.exposeEventFollows(configureEvent) {
// }
}
}
func (window *window) exposeEventFollows (event xproto.ConfigureNotifyEvent) (found bool) {
nextEvents := xevent.Peek(window.backend.x)
if len(nextEvents) > 0 {
untypedEvent := nextEvents[0]
if untypedEvent.Err == nil {
typedEvent, ok :=
untypedEvent.Event.(xproto.ConfigureNotifyEvent)
if ok && typedEvent.Window == event.Window {
return true
}
}
}
return false
}
func (window *window) compressExpose (
firstEvent xproto.ExposeEvent,
) (
lastEvent xproto.ExposeEvent,
region image.Rectangle,
) {
region = image.Rect (
int(firstEvent.X), int(firstEvent.Y),
int(firstEvent.X + firstEvent.Width),
int(firstEvent.Y + firstEvent.Height))
window.backend.x.Sync()
xevent.Read(window.backend.x, false)
lastEvent = firstEvent
for index, untypedEvent := range xevent.Peek(window.backend.x) {
if untypedEvent.Err != nil { continue }
typedEvent, ok := untypedEvent.Event.(xproto.ExposeEvent)
if !ok { continue }
if firstEvent.Window == typedEvent.Window {
region = region.Union (image.Rect (
int(typedEvent.X), int(typedEvent.Y),
int(typedEvent.X + typedEvent.Width),
int(typedEvent.Y + typedEvent.Height)))
lastEvent = typedEvent
defer func (index int) {
xevent.DequeueAt(window.backend.x, index)
} (index)
}
}
return
}
func (window *window) compressConfigureNotify (
firstEvent xproto.ConfigureNotifyEvent,
) (
lastEvent xproto.ConfigureNotifyEvent,
) {
window.backend.x.Sync()
xevent.Read(window.backend.x, false)
lastEvent = firstEvent
for index, untypedEvent := range xevent.Peek(window.backend.x) {
if untypedEvent.Err != nil { continue }
typedEvent, ok := untypedEvent.Event.(xproto.ConfigureNotifyEvent)
if !ok { continue }
if firstEvent.Event == typedEvent.Event &&
firstEvent.Window == typedEvent.Window {
lastEvent = typedEvent
defer func (index int) {
xevent.DequeueAt(window.backend.x, index)
} (index)
}
}
return
}