window

package
v0.0.0-...-793ea6c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2021 License: BSD-3-Clause Imports: 18 Imported by: 28

Documentation

Overview

Package window is the easiest way to open a window and draw graphics.

Through this package you can easilly create windows that can be drawn to via the gfx package. A single API is used and works to target desktop, mobile and web platforms.

Simple

The package is extremely easy to use, simply declare a graphics loop and call the Run function:

// gfxLoop is our graphics loop, which runs in a separate goroutine.
func gfxLoop(w window.Window, d gfx.Device) {
    // Initialization here.

    // Enter our render loop:
    for {
        // TODO: clear and draw to the canvas, r.
        d.Render()
    }
}

func main() {
    // Create a window and run our graphics loop.
    window.Run(gfxLoop, nil)
}

Events

Windows can notify you of the events that they recieve over a channel, which allows for user input to be processed in any goroutine completely independent of rendering.

A bitmask is used to efficiently select the events that you are interested in, rather than you receiving all of them and discarding the ones you don't want:

// Create our events channel with sufficient buffer size.
events := make(chan window.Event, 256)

// Get notified of just mouse and keyboard events.
w.Notify(events, window.MouseEvents|window.KeyboardTypedEvents)

// Less efficient:
// w.Notify(events, window.AllEvents)

Properties

Creating window properties (such as a window's title, position, size, fullscreen status, etc) is very easy:

props := window.NewProps()
props.SetTitle("Hello World!")
props.SetFullscreen(true)

The backend is ultimately what interprets the window properties, for instance mobile devices have no concept of positioning windows -- so requests to do so are simply ignored.

Both the Run and New functions exposed by this package take a second argument which can be a set of window properties (or nil), this lets you specify window properties when a window is created:

// Second argument is *Props, if nil it defaults to DefaultProps.
window.Run(gfxLoop, props)

// Or when creating multiple windows:
window.New(gfxLoop, props)

Changing Properties

You can request that window properties be changed after a window has already been created, for instance to toggle fullscreen at runtime:

// Get the current window properties.
props := myWindow.Props()

// Toggle the fullscreen status.
props.SetFullscreen(!props.Fullscreen())

// Request the new window properties.
myWindow.Request(props)

FPS in Title

If the window title contains a "{FPS}" string inside of it, it will be automatically updated with the application's current frame rate (frames per second):

// The title would look like: "My App! 60FPS".
props.SetTitle("My App! {FPS}")

Multiple Windows

The package allows creation of multiple windows on platforms that support it (Windows, Linux, OS X, and the web via seperate HTML elements). Only one window can be created on mobile devices such as Android.

New can create a new window from any goroutine, for instance in the below example:

// gfxLoop is our graphics loop, which runs in a separate goroutine.
func gfxLoop(w window.Window, d gfx.Device) {
    // Create a second window!
    w2, d2, err := window.New(nil)
    if err != nil {
        log.Fatal(err)
    }

    // Spawn the same graphics loop, but drawing to the second window!
    go gfxLoop(w2, d2)

    // Enter our render loop:
    for {
        // TODO: clear and draw to the device's default canvas.
        d.Render()
    }
}

func main() {
    // Create a window and run our graphics loop.
    window.Run(gfxLoop, nil)
}

If you prefer not to use the simple Run function, you can use the New and MainLoop functions yourself. The only restriction is that New cannot complete unless MainLoop is already running.

The following code works fine, because New is run in a seperate goroutine:

func main() {
    go func() {
        // New runs in a seperate goroutine, after MainLoop has started.
        w, r, err := window.New(nil)
        ... use w, r, handle err ...
    }()
    window.MainLoop()
}

The following code does not work: a deadlock occurs because MainLoop is called after New, and New cannot complete unless MainLoop is running.

func main() {
    // Won't ever complete: the main loop isn't running yet!
    w, d, err := window.New(nil)
    ... use w, d, handle err ...
    window.MainLoop()
}

Main Thread

The MainLoop function internally locks the OS thread for you. In simple terms the only requirement is that you call either MainLoop, or Run which calls MainLoop for you, from your programs main function.

This is required because some GUI libraries (such as Cocoa on OS X) require that they be run on the main operating system thread; not just the same operating system thread, but actually the main one.

The MainLoop function takes control of the main loop for you, which is helpful. But in some situations you might want control of it (e.g. to call certain GUI libraries).

To send an arbitrary function to execute on the main loop, simply send it over the main loop channel exposed by this package:

window.MainLoopChan <- func() {
    fmt.Println("On the main thread!")
}

More complex situations can be handled as well, by implementing the (small) MainLoop function yourself.

Because a channel is used, the main loop is said to be communicative rather than employing a busy-waiting scheme.

Build Tags

The build tag "gles2" is accepted on 386 and amd64 architectures to choose to utilize a OpenGL ES 2 based device instead of the OpenGL 2 one. This is useful for testing how your application might run under more constrained OpenGL ES 2 devices (i.e. mobile devices).

Examples

The examples repository contains several examples which utilize the gfx core packages. Please see:

https://azul3d.org/examples

Index

Constants

This section is empty.

Variables

View Source
var DefaultProps = NewProps()

DefaultProps is the default set of window properties. You may modify them as you see fit.

They are used in place of nil properties (e.g. see the Run function).

View Source
var ErrSingleWindow = errors.New("only a single window is allowed")

ErrSingleWindow is returned by New if you attempt to create multiple windows on a system that does not support it.

View Source
var MainLoopChan = make(chan func())

MainLoopChan is a channel of functions over which each window created through this package will request for functions to be executed.

When any window is closed, it will send nil over this channel. The main loop should handle this case by checking the number of open windows (see the Num function). If no windows are left open, the main loop should exit.

Functions

func MainLoop

func MainLoop()

MainLoop enters the main loop, executing the main loop functions received from MainLoopChan until no windows are left open.

This function must be called only from the program's main function (other work should be done in other goroutines):

func main() {
    window.MainLoop()
}

By implementing MainLoop yourself, you can run other functions on the main OS thread (for instance Cocoa API's on OS X).

func Num

func Num(n int) int

Num tells the number of windows that are currently open, after adding the given integer to the count.

Query how many windows are currently open:

open := window.Num(0)
fmt.Println(open) // e.g. "1"

Add two windows to the current count (1) and fetch the new value:

open := window.Num(2)
fmt.Println(open) // e.g. "3"

Implementors of the Window interface are the only ones that should modify the window count.

This function is safe for access from multiple goroutines concurrently.

func Poll

func Poll(events <-chan Event, f func(e Event))

Poll calls the given function for each pending event in the given channel.

It operates identically to traditional non-blocking event polling, and is useful in situations where one wants to poll for events inside of e.g. the render loop. For example:

for{
    window.Poll(events, func(e window.Event) {
        fmt.Println("event", e)
    })

    fmt.Println("render!")
}

Is equivilent to writing:

for{
    l := len(events)
    for i := 0; i < l; i++ {
        e := <-events
        fmt.Println("event", e)
    }

    fmt.Println("render!")
}

The declaration of the variable l outside of the foor loop is critical: event channels are streams of events and there is no guarantee that there will be a pause in them, writing the loop any other way would block rendering.

func Run

func Run(gfxLoop func(w Window, d gfx.Device), p *Props)

Run opens a window with the given properties and runs the given graphics loop in a separate goroutine.

This function must be called only from the program's main function (other work should be done in other goroutines):

func main() {
    window.Run(gfxLoop, nil)
}

For more documentation about the behavior of Run, see the New function.

Types

type Clipboard

type Clipboard interface {
	// SetClipboard sets the clipboard string.
	SetClipboard(clipboard string)

	// Clipboard returns the clipboard string.
	Clipboard() string
}

Clipboard is the interface describing a system's clipboard. Grab a clipboard from a window (some platforms don't support clipboard access):

clip, ok := win.(window.Clipboard)
if ok {
    // We have clipboard access.
    clip.SetClipboard("Hello World!")
}

type Close

type Close struct {
	T time.Time
}

Close is sent when the user requests that the application window be closed, using the exit button or a quick-key combination like Alt + F4, etc.

func (Close) String

func (ev Close) String() string

String returns a string representation of this event.

func (Close) Time

func (ev Close) Time() time.Time

Time implements the Event interface.

type CursorEnter

type CursorEnter struct {
	T time.Time
}

CursorEnter is an event where the user moved the mouse cursor inside of the window.

func (CursorEnter) String

func (ev CursorEnter) String() string

String returns a string representation of this event.

func (CursorEnter) Time

func (ev CursorEnter) Time() time.Time

Time implements the Event interface.

type CursorExit

type CursorExit struct {
	T time.Time
}

CursorExit is an event where the user moved the mouse cursor outside of the window.

func (CursorExit) String

func (ev CursorExit) String() string

String returns a string representation of this event.

func (CursorExit) Time

func (ev CursorExit) Time() time.Time

Time implements the Event interface.

type CursorMoved

type CursorMoved struct {
	// Position of cursor relative to the upper-left corner of the window.
	X, Y float64

	// Whether or not the event's X and Y values are actually relative delta
	// values (e.g. for a FPS style camera).
	Delta bool

	T time.Time
}

CursorMoved is sent when the user has moved the mouse cursor.

func (CursorMoved) String

func (ev CursorMoved) String() string

String returns a string representation of this event.

func (CursorMoved) Time

func (ev CursorMoved) Time() time.Time

Time implements the Event interface.

type Damaged

type Damaged struct {
	T time.Time
}

Damaged is sent when the window's client area has been damaged and the window needs to be redrawn.

func (Damaged) String

func (ev Damaged) String() string

String returns a string representation of this event.

func (Damaged) Time

func (ev Damaged) Time() time.Time

Time implements the Event interface.

type Event

type Event interface {
	Time() time.Time
}

Event represents an event of some sort. The only requirement is that the event specify the point in time at which it happened.

Using a type assertion or a type switch you can determine the actualy type of event which contains much more information:

select ev := event.(type){
case *keyboard.StateEvent:
    fmt.Println("The keyboard button", ev.Key, "is now", ev.State)
    // example: "The keyboard button keyboard.A is now keyboard.Down"
}

type EventMask

type EventMask uint32

EventMask is a bitmask of event types. They can be combined, for instance:

mask := window.CloseEvents
mask |= window.MinimizedEvents
mask |= window.LostFocusEvents

would select events of the following types:

window.Close
window.Minimized
window.LostFocus
const (
	// CloseEvents is a event mask matching window.Close events.
	CloseEvents EventMask = 1 << iota

	// DamagedEvents is a event mask matching window.Damaged events.
	DamagedEvents

	// CursorMovedEvents is a event mask matching window.CursorMoved events.
	CursorMovedEvents

	// CursorEnterEvents is a event mask matching window.CursorEnter events.
	CursorEnterEvents

	// CursorExitEvents is a event mask matching window.CursorExit events.
	CursorExitEvents

	// MinimizedEvents is a event mask matching window.Minimized events.
	MinimizedEvents

	// RestoredEvents is a event mask matching window.Restored events.
	RestoredEvents

	// GainedFocusEvents is a event mask matching window.GainedFocus events.
	GainedFocusEvents

	// LostFocusEvents is a event mask matching window.LostFocus events.
	LostFocusEvents

	// MovedEvents is a event mask matching window.Moved events.
	MovedEvents

	// ResizedEvents is a event mask matching window.Resized events.
	ResizedEvents

	// FramebufferResizedEvents is a event mask matching
	// window.FramebufferResized events.
	FramebufferResizedEvents

	// ItemsDroppedEvents is a event mask matching window.ItemsDropped events.
	ItemsDroppedEvents

	// MouseButtonEvents is a event mask matching mouse.ButtonEvent's.
	MouseButtonEvents

	// MouseScrolledEvents is a event mask matching mouse.Scrolled events.
	MouseScrolledEvents

	// KeyboardTypedEvents is a event mask matching keyboard.Typed events.
	KeyboardTypedEvents

	// KeyboardButtonEvents is a event mask matching keyboard.ButtonEvent's.
	KeyboardButtonEvents

	// NoEvents is a event mask matching no events at all.
	NoEvents EventMask = 0

	// AllEvents is a event mask matching all possible events.
	AllEvents EventMask = math.MaxUint32
)
const (
	// CursorEvents is an event mask that selects all cursor events:
	//
	//  window.CursorMoved
	//  window.CursorEnter
	//  window.CursorExit
	//
	CursorEvents EventMask = CursorMovedEvents | CursorEnterEvents | CursorExitEvents

	// MouseEvents is an event mask that selects all mouse events:
	//
	//  mouse.ButtonEvent
	//  mouse.Scrolled
	//
	MouseEvents EventMask = MouseButtonEvents | MouseScrolledEvents

	// KeyboardEvents is an event mask that selects all keyboard events:
	//
	//  keyboard.ButtonEvent
	//  keyboard.Typed
	//
	KeyboardEvents EventMask = KeyboardButtonEvents | KeyboardTypedEvents
)

type FramebufferResized

type FramebufferResized struct {
	// Size of the framebuffer in pixels.
	Width, Height int

	T time.Time
}

FramebufferResized is an event where the framebuffer of the window has been resized.

func (FramebufferResized) String

func (ev FramebufferResized) String() string

String returns a string representation of this event.

func (FramebufferResized) Time

func (ev FramebufferResized) Time() time.Time

Time implements the Event interface.

type GainedFocus

type GainedFocus struct {
	T time.Time
}

GainedFocus is an event where the window has gained focus.

func (GainedFocus) String

func (ev GainedFocus) String() string

String returns a string representation of this event.

func (GainedFocus) Time

func (ev GainedFocus) Time() time.Time

Time implements the Event interface.

type ItemsDropped

type ItemsDropped struct {
	Items []string

	T time.Time
}

ItemsDropped is an event where the user dropped an item (or multiple items) onto the window.

func (ItemsDropped) String

func (ev ItemsDropped) String() string

String returns a string representation of this event.

func (ItemsDropped) Time

func (ev ItemsDropped) Time() time.Time

Time implements the Event interface.

type LostFocus

type LostFocus struct {
	T time.Time
}

LostFocus is an event where the window has lost focus.

func (LostFocus) String

func (ev LostFocus) String() string

String returns a string representation of this event.

func (LostFocus) Time

func (ev LostFocus) Time() time.Time

Time implements the Event interface.

type Minimized

type Minimized struct {
	T time.Time
}

Minimized is an event where the user minimized the window.

func (Minimized) String

func (ev Minimized) String() string

String returns a string representation of this event.

func (Minimized) Time

func (ev Minimized) Time() time.Time

Time implements the Event interface.

type Moved

type Moved struct {
	// Position of the window's client area, relative to the top-left of the
	// screen.
	X, Y int

	T time.Time
}

Moved is an event where the user changed the position of the window.

func (Moved) String

func (ev Moved) String() string

String returns a string representation of this event.

func (Moved) Time

func (ev Moved) Time() time.Time

Time implements the Event interface.

type Props

type Props struct {
	// contains filtered or unexported fields
}

Props represents window properties. Properties are safe for use concurrently from multiple goroutines.

func NewProps

func NewProps() *Props

NewProps returns a new initialized set of window properties. The default values for each property are as follows:

Title: "Azul3D - {FPS}"
Size: 800x450
Pos: -1, -1 (centered on screen)
CursorPos: -1.0, -1.0 (current position)
ShouldClose: true
Visible: true
Minimized: false
Fullscreen: false
Focused: true
VSync: true
Resizable: true
Decorated: true
AlwaysOnTop: false
CursorGrabbed: false
ResizeRenderSync: true
FramebufferSize: 1x1 (set via window owner)
Precision: gfx.Precision{
    RedBits: 8, GreenBits: 8, BlueBits: 8, AlphaBits: 0,
    DepthBits: 24,
    StencilBits: 0,
    Samples: 2,
}

func (*Props) AlwaysOnTop

func (p *Props) AlwaysOnTop() bool

AlwaysOnTop tells whether or not the window is set to be always on top of other windows.

func (*Props) CursorGrabbed

func (p *Props) CursorGrabbed() bool

CursorGrabbed returns whether or not the cursor is grabbed.

func (*Props) CursorPos

func (p *Props) CursorPos() (x, y float64)

CursorPos returns the position of the mouse cursor.

func (*Props) Decorated

func (p *Props) Decorated() bool

Decorated tells whether or not the window has it's decorations shown.

func (*Props) Focused

func (p *Props) Focused() bool

Focused tells whether or not the window has focus.

func (*Props) FramebufferSize

func (p *Props) FramebufferSize() (width, height int)

FramebufferSize returns the size of the framebuffer in pixels.

func (*Props) Fullscreen

func (p *Props) Fullscreen() bool

Fullscreen tells whether or not the window is fullscreen.

func (*Props) Minimized

func (p *Props) Minimized() bool

Minimized tells whether or not the window is minimized.

func (*Props) Pos

func (p *Props) Pos() (x, y int)

Pos returns the position of the upper-left corner of the client area of the window in screen coordinates.

func (*Props) Precision

func (p *Props) Precision() gfx.Precision

Precision returns the framebuffer precision that is to be requested when the window is created.

As mentioned by the SetPrecision documentation, the precision returned by this function is the one you request -- not strictly the precision that you will receive (as that is hardware dependent).

To check what framebuffer precision you actually receive, look at the precision of the device's default canvas:

device.Precision()

func (*Props) Resizable

func (p *Props) Resizable() bool

Resizable tells whether or not the window can be resized.

func (*Props) ResizeRenderSync

func (p *Props) ResizeRenderSync() bool

ResizeRenderSync returns whether or not resizing is sycnrhonized with rendering.

func (*Props) SetAlwaysOnTop

func (p *Props) SetAlwaysOnTop(alwaysOnTop bool)

SetAlwaysOnTop sets whether or not the window is always on top of other windows.

func (*Props) SetCursorGrabbed

func (p *Props) SetCursorGrabbed(grabbed bool)

SetCursorGrabbed sets whether or not the cursor should be grabbed. If the cursor is grabbed, it is hidden from sight and cannot leave the window.

When grabbed, a window generates CursorMoved events with Delta=true, this is useful for e.g. FPS style cameras.

func (*Props) SetCursorPos

func (p *Props) SetCursorPos(x, y float64)

SetCursorPos sets the position of the mouse cursor.

A special value of x=-1.0, y=-1.0 means to not move the mouse cursor at all.

func (*Props) SetDecorated

func (p *Props) SetDecorated(decorated bool)

SetDecorated sets whether or not the window has it's decorations shown.

func (*Props) SetFocused

func (p *Props) SetFocused(focused bool)

SetFocused sets whether or not the window has focus.

func (*Props) SetFramebufferSize

func (p *Props) SetFramebufferSize(width, height int)

SetFramebufferSize sets the size of the framebuffer in pixels. Each value is clamped to at least a value of 1.

Only the Window implementation should set the framebuffer size: clients who are just utilizing the existing implementations defined in this package should not invoke this method.

func (*Props) SetFullscreen

func (p *Props) SetFullscreen(fullscreen bool)

SetFullscreen sets whether or not the window is fullscreen.

func (*Props) SetMinimized

func (p *Props) SetMinimized(minimized bool)

SetMinimized sets whether or not the window is minimized.

func (*Props) SetPos

func (p *Props) SetPos(x, y int)

SetPos sets the position of the upper-left corner of the client area of the window in screen coordinates.

A special value of x=-1, y=-1 means to center the window on the screen.

func (*Props) SetPrecision

func (p *Props) SetPrecision(precision gfx.Precision)

SetPrecision sets the framebuffer precision to be requested when the window is created.

Requesting a specific framebuffer precision is simply that -- a request. No guarantee is made that you will receive that precision, as it is completely hardware dependent.

To check what framebuffer precision you actually receive, look at the precision of the device's default canvas:

device.Precision()

func (*Props) SetResizable

func (p *Props) SetResizable(resizable bool)

SetResizable sets whether or not the window can be resized.

func (*Props) SetResizeRenderSync

func (p *Props) SetResizeRenderSync(sync bool)

SetResizeRenderSync sets whether or not window resize operations should be synchronized with rendering. In general, this controls whether or not resizing the window will be appear "fluid" by halting the user from resizing the window until the next frame has been drawn. If rendering on-demand, i.e. not at a fast rate, you should disable this option.

func (*Props) SetShouldClose

func (p *Props) SetShouldClose(shouldClose bool)

SetShouldClose sets whether the window should close or not when the user tries to close the window.

func (*Props) SetSize

func (p *Props) SetSize(width, height int)

SetSize sets the size of the window in screen coordinates. Each value is clamped to at least a value of 1.

func (*Props) SetTitle

func (p *Props) SetTitle(title string)

SetTitle sets the title of the window. The backend will replace the first string in the title matching "{FPS}" with the actual frames per second.

For example, a title "Hello World - {FPS}" would end up as:

"Hello world - 60FPS"

func (*Props) SetVSync

func (p *Props) SetVSync(vsync bool)

SetVSync turns on or off vertical refresh rate synchronization (vsync).

func (*Props) SetVisible

func (p *Props) SetVisible(visible bool)

SetVisible sets whether or not the window is visible or hidden.

func (*Props) ShouldClose

func (p *Props) ShouldClose() bool

ShouldClose tells if the window will close or not when the user tries to close the window.

func (*Props) Size

func (p *Props) Size() (width, height int)

Size returns the size of the window in screen coordinates.

func (*Props) String

func (p *Props) String() string

String returns a string like:

"Window(Title="Hello World!", Fullscreen=false)"

func (*Props) Title

func (p *Props) Title() string

Title returns the title of the window, as previously set via SetTitle.

func (*Props) VSync

func (p *Props) VSync() bool

VSync tells if vertical refresh rate synchronization (vsync) is on or off.

func (*Props) Visible

func (p *Props) Visible() bool

Visible tells whether or not the window is visible or hidden.

type Resized

type Resized struct {
	// Size of the window in screen coordinates.
	Width, Height int

	T time.Time
}

Resized is an event where the user changed the size of the window.

func (Resized) String

func (ev Resized) String() string

String returns a string representation of this event.

func (Resized) Time

func (ev Resized) Time() time.Time

Time implements the Event interface.

type Restored

type Restored struct {
	T time.Time
}

Restored is an event where the user restored (un-minimized) the window.

func (Restored) String

func (ev Restored) String() string

String returns a string representation of this event.

func (Restored) Time

func (ev Restored) Time() time.Time

Time implements the Event interface.

type Window

type Window interface {
	// Props returns the window's properties.
	Props() *Props

	// Request makes a request to use a new set of properties, p. It is then
	// recommended to make changes to the window using something like:
	//
	//  props := window.Props()
	//  props.SetTitle("Hello World!")
	//  props.SetSize(640, 480)
	//  window.Request(props)
	//
	// Interpretation of the given properties is left strictly up to the
	// platform dependent implementation (for instance, on Android you cannot
	// set the window's size, so instead a request for this is simply ignored.
	Request(p *Props)

	// Keyboard returns a keyboard watcher for the window. It can be used to
	// tell if certain keyboard buttons are currently held down, for instance:
	//
	//  if w.Keyboard().Down(keyboard.W) {
	//      fmt.Println("The W key is currently held down")
	//  }
	//
	Keyboard() *keyboard.Watcher

	// Mouse returns a mouse watcher for the window. It can be used to tell if
	// certain mouse buttons are currently held down, for instance:
	//
	//  if w.Mouse().Down(mouse.Left) {
	//      fmt.Println("The left mouse button is currently held down")
	//  }
	//
	Mouse() *mouse.Watcher

	// Notify causes the window to relay window events to ch based on the event
	// mask.
	//
	// The special event mask NoEvents causes the window to stop relaying any
	// events to the given channel. You should always perform this action when
	// you are done using the event channel.
	//
	// The window will not block sending events to ch: the caller must ensure
	// that ch has a sufficient amount of buffer space to keep up with the
	// event rate.
	//
	// If you only expect to receive a single event like Close then a buffer
	// size of one is acceptable.
	//
	// You are allowed to make multiple calls to this method with the same
	// channel, if you do then the same event will be sent over the channel
	// multiple times. When you no longer want the channel to receive events
	// then call this function again with NoEvents:
	//
	//  w.Notify(ch, NoEvents)
	//
	// Multiple calls to Events with different channels works as you would
	// expect, each channel receives a copy of the events independent of other
	// ones.
	//
	// Warning: Many people use high-precision mice, some which can reach well
	// above 1000hz, so for cursor events a generous buffer size (256, etc) is
	// highly recommended.
	//
	// Warning: Depending on the operating system, window manager, etc, some of
	// the events may never be sent or may only be sent sporadically, so plan
	// for this.
	Notify(ch chan<- Event, m EventMask)

	// Close closes the window, it must be called or else the main loop (and
	// inheritely, the application) will not exit.
	Close()
}

Window represents a single window that graphics can be drawn to. The window is safe for use concurrently from multiple goroutines.

func New

func New(p *Props) (w Window, d gfx.Device, err error)

New creates a new window, and is safe to call from any goroutine.

If you just want to create a single window, use the simpler Run function instead.

If the properties, p, are nil then DefaultProps is used instead.

Interpretation of the properties is left strictly up to the platform dependent implementation (for instance, on Android you cannot set a window's size, so it is ignored).

If you attempt to create multiple windows and the system does not allow it, then ErrSingleWindow will be returned (e.g. on mobile platforms where there is no concept of multiple windows).

If any error is returned, the window could not be created, and the returned window and device are nil.

New requests several operations be run on the main loop internally, because of this it cannot be run on the main thread itself. That is, MainLoop must be running for New to complete.

The following code works fine, because New is run in a seperate goroutine:

func main() {
    go func() {
        // New runs in a seperate goroutine, after MainLoop has started.
        w, d, err := window.New(nil)
        ... use w, d, handle err ...
    }()
    window.MainLoop()
}

The following code does not work, a deadlock occurs because MainLoop is called after New, and New cannot complete unless MainLoop is running.

func main() {
    // Won't ever complete: the main loop isn't running yet!
    w, d, err := window.New(nil)
    ... use w, d, handle err ...
    window.MainLoop()
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL