Example #1
0
File: win.go Project: uriel/vimg
// setupEventHandlers attaches the canvas' channels to the window and
// sets the appropriate callbacks to some events:
// ConfigureNotify events will cause the window to update its state of geometry.
// Expose events will cause the window to repaint the current image.
// Button events to allow panning.
// Key events to perform various tasks when certain keys are pressed.
func (w *Window) setupEventHandlers(chans chans) {
	w.Listen(xproto.EventMaskStructureNotify | xproto.EventMaskExposure |
		xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskKeyPress)

	// Get the current geometry in case we don't get a ConfigureNotify event
	// (or have already missed it).
	if _, err := w.Geometry(); err != nil {
		errLg.Fatal(err)
	}

	// Keep a state of window geometry.
	xevent.ConfigureNotifyFun(
		func(X *xgbutil.XUtil, ev xevent.ConfigureNotifyEvent) {
			w.Geom.WidthSet(int(ev.Width))
			w.Geom.HeightSet(int(ev.Height))
		}).Connect(w.X, w.Id)

	// Repaint the window on expose events.
	xevent.ExposeFun(
		func(X *xgbutil.XUtil, ev xevent.ExposeEvent) {
			chans.ctl <- []string{"pan", "origin"}
		}).Connect(w.X, w.Id)

	// Setup a drag handler to allow panning.
	mousebind.Drag(w.X, w.Id, w.Id, "1", false,
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) {
			chans.panStartChan <- image.Point{ex, ey}
			return true, 0
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			chans.panStepChan <- image.Point{ex, ey}
		},
		// We do nothing on mouse release
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) { return })

	for _, kb := range keybinds {
		k := kb // Needed because the callback closure will capture kb
		err := keybind.KeyPressFun(
			func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
				chans.ctl <- k.command
			}).Connect(w.X, w.Id, k.key, false)
		if err != nil {
			errLg.Println(err)
		}
	}
}
Example #2
0
// setupEventHandlers attaches the canvas' channels to the window and
// sets the appropriate callbacks to some events:
// ConfigureNotify events will cause the window to update its state of geometry.
// Expose events will cause the window to repaint the current image.
// Button events to allow panning.
// Key events to perform various tasks when certain keys are pressed. Should
// these be configurable? Meh.
func (w *window) setupEventHandlers(chans chans) {
	w.chans = chans
	w.Listen(xproto.EventMaskStructureNotify | xproto.EventMaskExposure |
		xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease |
		xproto.EventMaskKeyPress)

	// Get the current geometry in case we don't get a ConfigureNotify event
	// (or have already missed it).
	_, err := w.Geometry()
	if err != nil {
		errLg.Fatal(err)
	}

	// And ask the canvas to draw the first image when it gets around to it.
	go func() {
		w.chans.drawChan <- func(origin image.Point) image.Point {
			return image.Point{}
		}
	}()

	// Keep a state of window geometry.
	xevent.ConfigureNotifyFun(
		func(X *xgbutil.XUtil, ev xevent.ConfigureNotifyEvent) {
			w.Geom.WidthSet(int(ev.Width))
			w.Geom.HeightSet(int(ev.Height))
		}).Connect(w.X, w.Id)

	// Repaint the window on expose events.
	xevent.ExposeFun(
		func(X *xgbutil.XUtil, ev xevent.ExposeEvent) {
			w.chans.drawChan <- func(origin image.Point) image.Point {
				return origin
			}
		}).Connect(w.X, w.Id)

	// Setup a drag handler to allow panning.
	mousebind.Drag(w.X, w.Id, w.Id, "1", false,
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) {
			w.chans.panStartChan <- image.Point{ex, ey}
			return true, 0
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			w.chans.panStepChan <- image.Point{ex, ey}
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			w.chans.panEndChan <- image.Point{ex, ey}
		})

	// Set up a map of keybindings to avoid a lot of boiler plate.
	// for keystring, fun := range kbs {
	for _, keyb := range keybinds {
		keyb := keyb
		err := keybind.KeyPressFun(
			func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
				keyb.action(w)
			}).Connect(w.X, w.Id, keyb.key, false)
		if err != nil {
			errLg.Println(err)
		}
	}
}
Example #3
0
func makeWindow(ximage *xgraphics.Image) (*xwindow.Window, *bool) {
	w, h := ximage.Rect.Dx(), ximage.Rect.Dy()

	window, err := xwindow.Generate(ximage.X)
	if err != nil {
		xgbutil.Logger.Printf("Could not generate new window id: %s", err)
		return nil, nil
	}

	window.Create(ximage.X.RootWin(), 0, 0, w, h, xproto.CwBackPixel, 0x00000000)
	window.Listen(xproto.EventMaskExposure,
		xproto.EventMaskKeyPress,
		xproto.EventMaskStructureNotify,
		xproto.EventMaskVisibilityChange)

	window.WMGracefulClose(func(w *xwindow.Window) {
		xevent.Detach(w.X, w.Id)
		keybind.Detach(w.X, w.Id)
		mousebind.Detach(w.X, w.Id)
		w.Destroy()
		xevent.Quit(w.X)
	})

	err = icccm.WmStateSet(ximage.X, window.Id, &icccm.WmState{
		State: icccm.StateNormal,
	})
	if err != nil {
		xgbutil.Logger.Printf("Could not set WM_STATE: %s", err)
	}

	err = ewmh.WmNameSet(ximage.X, window.Id, "Computer System Monitor")
	if err != nil {
		xgbutil.Logger.Printf("Could not set _NET_WM_NAME: %s", err)
	}

	err = keybind.KeyPressFun(
		func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
			err := ewmh.WmStateReq(ximage.X, window.Id, ewmh.StateToggle,
				"_NET_WM_STATE_FULLSCREEN")
			if err != nil {
				log.Fatal(err)
			}
		}).Connect(ximage.X, window.Id, "f", false)
	if err != nil {
		log.Fatal(err)
	}

	xevent.ExposeFun(
		func(xu *xgbutil.XUtil, event xevent.ExposeEvent) {
			ximage.XExpPaint(window.Id, 0, 0)
		}).Connect(ximage.X, window.Id)

	obscured := false
	xevent.VisibilityNotifyFun(
		func(xu *xgbutil.XUtil, event xevent.VisibilityNotifyEvent) {
			obscured = event.State == xproto.VisibilityFullyObscured
		}).Connect(ximage.X, window.Id)

	window.Map()

	return window, &obscured
}