From 07ed8681b3a7103465599f8726f0dd7a50392b4d Mon Sep 17 00:00:00 2001 From: lucor Date: Thu, 12 Nov 2020 19:15:48 +0100 Subject: [PATCH 01/33] [fyne-cli] Android: allow to specify an inline password for the keystore --- cmd/fyne/commands/release.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index aae54da773..e6dbbe41f1 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -21,9 +21,10 @@ var _ Command = (*releaser)(nil) type releaser struct { packager - keyStore string - developer string - password string + keyStore string + keyStorePass string + developer string + password string } // NewReleaser returns a command that can adapt app packages for distribution @@ -39,6 +40,7 @@ func (r *releaser) AddFlags() { flag.StringVar(&r.appVersion, "appVersion", "", "Version number in the form x, x.y or x.y.z semantic version") flag.IntVar(&r.appBuild, "appBuild", 0, "Build number, should be greater than 0 and incremented for each build") flag.StringVar(&r.keyStore, "keyStore", "", "Android: location of .keystore file containing signing information") + flag.StringVar(&r.keyStorePass, "keyStorePass", "", "Android: password for the .keystore file, default take the password from stdin") flag.StringVar(&r.certificate, "certificate", "", "iOS/macOS/Windows: name of the certificate to sign the build") flag.StringVar(&r.profile, "profile", "", "iOS/macOS: name of the provisioning profile for this release build") flag.StringVar(&r.developer, "developer", "", "Windows: the developer identity for your Microsoft store account") @@ -192,7 +194,13 @@ func (r *releaser) packageWindowsRelease(outFile string) error { func (r *releaser) signAndroid(path string) error { signer := filepath.Join(util.AndroidBuildToolsPath(), "/apksigner") - cmd := exec.Command(signer, "sign", "--ks", r.keyStore, path) + + keyStorePass := "stdin" + if r.keyStorePass != "" { + keyStorePass = "pass:" + r.keyStorePass + } + + cmd := exec.Command(signer, "sign", "--ks", r.keyStore, "--ks-pass", keyStorePass, path) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin From 767f00ef84a044312b791e1a2318bf3ff1036903 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 18 Nov 2020 16:23:56 +0000 Subject: [PATCH 02/33] Add new Since: docs to the APIs added in 1.4 --- canvas.go | 2 ++ container.go | 2 ++ container/layouts.go | 20 ++++++++++++++++++++ container/scroll.go | 10 ++++++++++ container/split.go | 6 ++++++ container/tabs.go | 12 ++++++++++++ data/validation/regexp.go | 2 ++ dialog/color.go | 6 ++++++ dialog/file.go | 2 ++ dialog/folder.go | 4 ++++ layout/paddedlayout.go | 2 ++ storage/file.go | 2 ++ storage/uri.go | 6 ++++++ uri.go | 2 ++ validation.go | 4 ++++ widget/button.go | 4 ++++ widget/card.go | 4 ++++ widget/entry.go | 2 ++ widget/fileicon.go | 4 ++++ widget/list.go | 4 ++++ widget/progressbar.go | 2 ++ widget/radio_group.go | 4 ++++ widget/separator.go | 4 ++++ widget/table.go | 6 ++++++ widget/tree.go | 6 ++++++ window.go | 2 ++ 26 files changed, 124 insertions(+) diff --git a/canvas.go b/canvas.go index 3b35bb2392..9960ffbd79 100644 --- a/canvas.go +++ b/canvas.go @@ -56,5 +56,7 @@ type Canvas interface { // InteractiveArea returns the position and size of the central interactive area. // Operating system elements may overlap the portions outside this area and widgets should avoid being outside. + // + // Since: 1.4 InteractiveArea() (Position, Size) } diff --git a/container.go b/container.go index ffff0e23c8..8ac0d71601 100644 --- a/container.go +++ b/container.go @@ -46,6 +46,8 @@ func NewContainerWithLayout(layout Layout, objects ...CanvasObject) *Container { } // Add appends the specified object to the items this container manages. +// +// Since: 1.4 func (c *Container) Add(add CanvasObject) { c.Objects = append(c.Objects, add) c.layout() diff --git a/container/layouts.go b/container/layouts.go index f8fe527637..882c3a6b7b 100644 --- a/container/layouts.go +++ b/container/layouts.go @@ -9,6 +9,8 @@ import ( // NewAdaptiveGrid creates a new container with the specified objects and using the grid layout. // When in a horizontal arrangement the rowcols parameter will specify the column count, when in vertical // it will specify the rows. On mobile this will dynamically refresh when device is rotated. +// +// Since: 1.4 func NewAdaptiveGrid(rowcols int, objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewAdaptiveGridLayout(rowcols), objects...) } @@ -16,6 +18,8 @@ func NewAdaptiveGrid(rowcols int, objects ...fyne.CanvasObject) *fyne.Container // NewBorder creates a new container with the specified objects and using the border layout. // The top, bottom, left and right parameters specify the items that should be placed around edges, // the remaining elements will be in the center. Nil can be used to an edge if it should not be filled. +// +// Since: 1.4 func NewBorder(top, bottom, left, right fyne.CanvasObject, objects ...fyne.CanvasObject) *fyne.Container { all := objects if top != nil { @@ -34,18 +38,24 @@ func NewBorder(top, bottom, left, right fyne.CanvasObject, objects ...fyne.Canva } // NewCenter creates a new container with the specified objects centered in the available space. +// +// Since: 1.4 func NewCenter(objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewCenterLayout(), objects...) } // NewGridWithColumns creates a new container with the specified objects and using the grid layout with // a specified number of columns. The number of rows will depend on how many children are in the container. +// +// Since: 1.4 func NewGridWithColumns(cols int, objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewGridLayoutWithColumns(cols), objects...) } // NewGridWithRows creates a new container with the specified objects and using the grid layout with // a specified number of columns. The number of columns will depend on how many children are in the container. +// +// Since: 1.4 func NewGridWithRows(rows int, objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewGridLayoutWithRows(rows), objects...) } @@ -53,28 +63,38 @@ func NewGridWithRows(rows int, objects ...fyne.CanvasObject) *fyne.Container { // NewGridWrap creates a new container with the specified objects and using the gridwrap layout. // Every element will be resized to the size parameter and the content will arrange along a row and flow to a // new row if the elements don't fit. +// +// Since: 1.4 func NewGridWrap(size fyne.Size, objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewGridWrapLayout(size), objects...) } // NewHBox creates a new container with the specified objects and using the HBox layout. // The objects will be placed in the container from left to right. +// +// Since: 1.4 func NewHBox(objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewHBoxLayout(), objects...) } // NewMax creates a new container with the specified objects filling the available space. +// +// Since: 1.4 func NewMax(objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewMaxLayout(), objects...) } // NewPadded creates a new container with the specified objects inset by standard padding size. +// +// Since: 1.4 func NewPadded(objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewPaddedLayout(), objects...) } // NewVBox creates a new container with the specified objects and using the VBox layout. // The objects will be stacked in the container from top to bottom. +// +// Since: 1.4 func NewVBox(objects ...fyne.CanvasObject) *fyne.Container { return fyne.NewContainerWithLayout(layout.NewVBoxLayout(), objects...) } diff --git a/container/scroll.go b/container/scroll.go index 4ef7103ca5..b7443c638e 100644 --- a/container/scroll.go +++ b/container/scroll.go @@ -7,9 +7,13 @@ import ( // Scroll defines a container that is smaller than the Content. // The Offset is used to determine the position of the child widgets within the container. +// +// Since: 1.4 type Scroll = widget.ScrollContainer // ScrollDirection represents the directions in which a Scroll container can scroll its child content. +// +// Since: 1.4 type ScrollDirection = widget.ScrollDirection // Constants for valid values of ScrollDirection. @@ -21,18 +25,24 @@ const ( // NewScroll creates a scrollable parent wrapping the specified content. // Note that this may cause the MinSize to be smaller than that of the passed object. +// +// Since: 1.4 func NewScroll(content fyne.CanvasObject) *Scroll { return widget.NewScrollContainer(content) } // NewHScroll create a scrollable parent wrapping the specified content. // Note that this may cause the MinSize.Width to be smaller than that of the passed object. +// +// Since: 1.4 func NewHScroll(content fyne.CanvasObject) *Scroll { return widget.NewHScrollContainer(content) } // NewVScroll a scrollable parent wrapping the specified content. // Note that this may cause the MinSize.Height to be smaller than that of the passed object. +// +// Since: 1.4 func NewVScroll(content fyne.CanvasObject) *Scroll { return widget.NewVScrollContainer(content) } diff --git a/container/split.go b/container/split.go index 7bddbe27e0..dd078fe3f4 100644 --- a/container/split.go +++ b/container/split.go @@ -6,16 +6,22 @@ import ( ) // Split defines a container whose size is split between two children. +// +// Since: 1.4 type Split = widget.SplitContainer // NewHSplit creates a horizontally arranged container with the specified leading and trailing elements. // A vertical split bar that can be dragged will be added between the elements. +// +// Since: 1.4 func NewHSplit(leading, trailing fyne.CanvasObject) *Split { return widget.NewHSplitContainer(leading, trailing) } // NewVSplit creates a vertically arranged container with the specified top and bottom elements. // A horizontal split bar that can be dragged will be added between the elements. +// +// Since: 1.4 func NewVSplit(top, bottom fyne.CanvasObject) *Split { return widget.NewVSplitContainer(top, bottom) } diff --git a/container/tabs.go b/container/tabs.go index 1ef4aa57cc..8a4d60594a 100644 --- a/container/tabs.go +++ b/container/tabs.go @@ -8,13 +8,19 @@ import ( // AppTabs container is used to split your application into various different areas identified by tabs. // The tabs contain text and/or an icon and allow the user to switch between the content specified in each TabItem. // Each item is represented by a button at the edge of the container. +// +// Since: 1.4 type AppTabs = widget.TabContainer // TabItem represents a single view in a TabContainer. // The Text and Icon are used for the tab button and the Content is shown when the corresponding tab is active. +// +// Since: 1.4 type TabItem = widget.TabItem // TabLocation is the location where the tabs of a tab container should be rendered +// +// Since: 1.4 type TabLocation = widget.TabLocation // TabLocation values @@ -26,16 +32,22 @@ const ( ) // NewAppTabs creates a new tab container that allows the user to choose between different areas of an app. +// +// Since: 1.4 func NewAppTabs(items ...*TabItem) *AppTabs { return widget.NewTabContainer(items...) } // NewTabItem creates a new item for a tabbed widget - each item specifies the content and a label for its tab. +// +// Since: 1.4 func NewTabItem(text string, content fyne.CanvasObject) *TabItem { return widget.NewTabItem(text, content) } // NewTabItemWithIcon creates a new item for a tabbed widget - each item specifies the content and a label with an icon for its tab. +// +// Since: 1.4 func NewTabItemWithIcon(text string, icon fyne.Resource, content fyne.CanvasObject) *TabItem { return widget.NewTabItemWithIcon(text, icon, content) } diff --git a/data/validation/regexp.go b/data/validation/regexp.go index c0b5987bc1..e8846f27b3 100644 --- a/data/validation/regexp.go +++ b/data/validation/regexp.go @@ -10,6 +10,8 @@ import ( // NewRegexp creates a new validator that uses regular expression parsing. // The validator will return nil if valid, otherwise returns an error with a reason text. +// +// Since: 1.4 func NewRegexp(regexpstr, reason string) fyne.StringValidator { expression, err := regexp.Compile(regexpstr) if err != nil { diff --git a/dialog/color.go b/dialog/color.go index 2dc4af01af..667353e4ad 100644 --- a/dialog/color.go +++ b/dialog/color.go @@ -14,6 +14,8 @@ import ( ) // ColorPickerDialog is a simple dialog window that displays a color picker. +// +// Since: 1.4 type ColorPickerDialog struct { *dialog Advanced bool @@ -26,6 +28,8 @@ type ColorPickerDialog struct { // NewColorPicker creates a color dialog and returns the handle. // Using the returned type you should call Show() and then set its color through SetColor(). // The callback is triggered when the user selects a color. +// +// Since: 1.4 func NewColorPicker(title, message string, callback func(c color.Color), parent fyne.Window) *ColorPickerDialog { p := &ColorPickerDialog{ dialog: newDialog(title, message, theme.ColorPaletteIcon(), nil /*cancel?*/, parent), @@ -37,6 +41,8 @@ func NewColorPicker(title, message string, callback func(c color.Color), parent // ShowColorPicker creates and shows a color dialog. // The callback is triggered when the user selects a color. +// +// Since: 1.4 func ShowColorPicker(title, message string, callback func(c color.Color), parent fyne.Window) { NewColorPicker(title, message, callback, parent).Show() } diff --git a/dialog/file.go b/dialog/file.go index c8db10c218..bb7e47e4ed 100644 --- a/dialog/file.go +++ b/dialog/file.go @@ -470,6 +470,8 @@ func (f *FileDialog) SetDismissText(label string) { // SetLocation tells this FileDirectory which location to display. // This is normally called before the dialog is shown. +// +// Since: 1.4 func (f *FileDialog) SetLocation(u fyne.ListableURI) { f.startingLocation = u if f.dialog != nil { diff --git a/dialog/folder.go b/dialog/folder.go index 97a361012d..d0c9d7f94f 100644 --- a/dialog/folder.go +++ b/dialog/folder.go @@ -9,6 +9,8 @@ var folderFilter = storage.NewMimeTypeFileFilter([]string{"application/x-directo // NewFolderOpen creates a file dialog allowing the user to choose a folder to open. // The dialog will appear over the window specified when Show() is called. +// +// Since: 1.4 func NewFolderOpen(callback func(fyne.ListableURI, error), parent fyne.Window) *FileDialog { dialog := &FileDialog{} dialog.callback = callback @@ -19,6 +21,8 @@ func NewFolderOpen(callback func(fyne.ListableURI, error), parent fyne.Window) * // ShowFolderOpen creates and shows a file dialog allowing the user to choose a folder to open. // The dialog will appear over the window specified. +// +// Since: 1.4 func ShowFolderOpen(callback func(fyne.ListableURI, error), parent fyne.Window) { dialog := NewFolderOpen(callback, parent) if fileOpenOSOverride(dialog) { diff --git a/layout/paddedlayout.go b/layout/paddedlayout.go index 57a1923cd8..fd71b68512 100644 --- a/layout/paddedlayout.go +++ b/layout/paddedlayout.go @@ -37,6 +37,8 @@ func (l *paddedLayout) MinSize(objects []fyne.CanvasObject) (min fyne.Size) { } // NewPaddedLayout creates a new PaddedLayout instance +// +// Since: 1.4 func NewPaddedLayout() fyne.Layout { return &paddedLayout{} } diff --git a/storage/file.go b/storage/file.go index 3c7ee630e2..67e401823f 100644 --- a/storage/file.go +++ b/storage/file.go @@ -19,6 +19,8 @@ func SaveFileToURI(uri fyne.URI) (fyne.URIWriteCloser, error) { // ListerForURI will attempt to use the application's driver to convert a // standard URI into a listable URI. +// +// Since: 1.4 func ListerForURI(uri fyne.URI) (fyne.ListableURI, error) { if lister, ok := uri.(fyne.ListableURI); ok { return lister, nil diff --git a/storage/uri.go b/storage/uri.go index 1853b7c05f..61b06262c6 100644 --- a/storage/uri.go +++ b/storage/uri.go @@ -121,6 +121,8 @@ func parentGeneric(location string) (string, error) { // Parent gets the parent of a URI by splitting it along '/' separators and // removing the last item. +// +// Since: 1.4 func Parent(u fyne.URI) (fyne.URI, error) { s := u.String() @@ -162,6 +164,8 @@ func Parent(u fyne.URI) (fyne.URI, error) { } // Child appends a new path element to a URI, separated by a '/' character. +// +// Since: 1.4 func Child(u fyne.URI, component string) (fyne.URI, error) { // While as implemented this does not need to return an error, it is // reasonable to expect that future implementations of this, especially @@ -181,6 +185,8 @@ func Child(u fyne.URI, component string) (fyne.URI, error) { // Exists will return true if the resource the URI refers to exists, and false // otherwise. If an error occurs while checking, false is returned as the first // return. +// +// Since: 1.4 func Exists(u fyne.URI) (bool, error) { if u.Scheme() != "file" { return false, fmt.Errorf("don't know how to check existence of %s scheme", u.Scheme()) diff --git a/uri.go b/uri.go index 12815e68e9..5343aec0f3 100644 --- a/uri.go +++ b/uri.go @@ -35,6 +35,8 @@ type URI interface { // ListableURI represents a URI that can have child items, most commonly a // directory on disk in the native filesystem. +// +// Since: 1.4 type ListableURI interface { URI diff --git a/validation.go b/validation.go index 98d2d23fec..10a0cf6bcc 100644 --- a/validation.go +++ b/validation.go @@ -1,6 +1,8 @@ package fyne // Validatable is an interface for specifying if a widget is validatable. +// +// Since: 1.4 type Validatable interface { Validate() error @@ -10,4 +12,6 @@ type Validatable interface { } // StringValidator is a function signature for validating string inputs. +// +// Since: 1.4 type StringValidator func(string) error diff --git a/widget/button.go b/widget/button.go index 1a539ab9b3..00a70b1124 100644 --- a/widget/button.go +++ b/widget/button.go @@ -19,6 +19,8 @@ type ButtonAlign int type ButtonIconPlacement int // ButtonImportance represents how prominent the button should appear +// +// Since: 1.4 type ButtonImportance int // ButtonStyle determines the behaviour and rendering of a button. @@ -68,6 +70,8 @@ type Button struct { Style ButtonStyle Icon fyne.Resource // Specify how prominent the button should be, High will highlight the button and Low will remove some decoration. + // + // Since: 1.4 Importance ButtonImportance Alignment ButtonAlign IconPlacement ButtonIconPlacement diff --git a/widget/card.go b/widget/card.go index 6ad1e9ded3..71900000ca 100644 --- a/widget/card.go +++ b/widget/card.go @@ -8,6 +8,8 @@ import ( ) // Card widget groups title, subtitle with content and a header image +// +// Since: 1.4 type Card struct { BaseWidget Title, Subtitle string @@ -16,6 +18,8 @@ type Card struct { } // NewCard creates a new card widget with the specified title, subtitle and content (all optional). +// +// Since: 1.4 func NewCard(title, subtitle string, content fyne.CanvasObject) *Card { card := &Card{ Title: title, diff --git a/widget/entry.go b/widget/entry.go index 5baed82af7..4ba9b31c32 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -41,6 +41,8 @@ type Entry struct { MultiLine bool Wrapping fyne.TextWrap + // Set a validator that this entry will check against + // Since: 1.4 Validator fyne.StringValidator validationStatus *validationStatus onValidationChanged func(error) diff --git a/widget/fileicon.go b/widget/fileicon.go index 01fbfdda79..3905d5b766 100644 --- a/widget/fileicon.go +++ b/widget/fileicon.go @@ -17,6 +17,8 @@ const ( ) // FileIcon is an adaption of widget.Icon for showing files and folders +// +// Since: 1.4 type FileIcon struct { BaseWidget @@ -29,6 +31,8 @@ type FileIcon struct { } // NewFileIcon takes a filepath and creates an icon with an overlayed label using the detected mimetype and extension +// +// Since: 1.4 func NewFileIcon(uri fyne.URI) *FileIcon { i := &FileIcon{URI: uri} i.ExtendBaseWidget(i) diff --git a/widget/list.go b/widget/list.go index 057bd6e48e..129ab8a4a2 100644 --- a/widget/list.go +++ b/widget/list.go @@ -21,6 +21,8 @@ var _ fyne.Widget = (*List)(nil) // List is a widget that pools list items for performance and // lays the items out in a vertical direction inside of a scroller. // List requires that all items are the same size. +// +// Since: 1.4 type List struct { BaseWidget @@ -38,6 +40,8 @@ type List struct { // NewList creates and returns a list widget for displaying items in // a vertical layout with scrolling and caching for performance. +// +// Since: 1.4 func NewList(length func() int, createItem func() fyne.CanvasObject, updateItem func(ListItemID, fyne.CanvasObject)) *List { list := &List{BaseWidget: BaseWidget{}, Length: length, CreateItem: createItem, UpdateItem: updateItem} list.ExtendBaseWidget(list) diff --git a/widget/progressbar.go b/widget/progressbar.go index 187319ebd6..cd670edea8 100644 --- a/widget/progressbar.go +++ b/widget/progressbar.go @@ -85,6 +85,8 @@ type ProgressBar struct { // TextFormatter can be used to have a custom format of progress text. // If set, it overrides the percentage readout and runs each time the value updates. + // + // Since: 1.4 TextFormatter func() string } diff --git a/widget/radio_group.go b/widget/radio_group.go index 5cb0ec3fd2..4465abd5e9 100644 --- a/widget/radio_group.go +++ b/widget/radio_group.go @@ -8,6 +8,8 @@ import ( // RadioGroup widget has a list of text labels and radio check icons next to each. // Changing the selection (only one can be selected) will trigger the changed func. +// +// Since: 1.4 type RadioGroup struct { DisableableWidget Horizontal bool @@ -22,6 +24,8 @@ type RadioGroup struct { var _ fyne.Widget = (*RadioGroup)(nil) // NewRadioGroup creates a new radio widget with the set options and change handler +// +// Since: 1.4 func NewRadioGroup(options []string, changed func(string)) *RadioGroup { r := &RadioGroup{ DisableableWidget: DisableableWidget{}, diff --git a/widget/separator.go b/widget/separator.go index 0b3a575d37..28d9bc9877 100644 --- a/widget/separator.go +++ b/widget/separator.go @@ -10,11 +10,15 @@ import ( var _ fyne.Widget = (*Separator)(nil) // Separator is a widget for displaying a separator with themeable color. +// +// Since: 1.4 type Separator struct { widget.Base } // NewSeparator creates a new separator. +// +// Since: 1.4 func NewSeparator() *Separator { return &Separator{} } diff --git a/widget/table.go b/widget/table.go index 67f1da7297..d7f83b0d0d 100644 --- a/widget/table.go +++ b/widget/table.go @@ -24,6 +24,8 @@ type TableCellID struct { // Table widget is a grid of items that can be scrolled and a cell selected. // It's performance is provided by caching cell templates created with CreateCell and re-using them with UpdateCell. // The size of the content rows/columns is returned by the Length callback. +// +// Since: 1.4 type Table struct { BaseWidget @@ -45,6 +47,8 @@ type Table struct { // The first returns the data size in rows and columns, second parameter is a function that returns cell // template objects that can be cached and the third is used to apply data at specified data location to the // passed template CanvasObject. +// +// Since: 1.4 func NewTable(length func() (int, int), create func() fyne.CanvasObject, update func(TableCellID, fyne.CanvasObject)) *Table { t := &Table{Length: length, CreateCell: create, UpdateCell: update} t.ExtendBaseWidget(t) @@ -103,6 +107,8 @@ func (t *Table) Select(id TableCellID) { // SetColumnWidth supports changing the width of the specified column. Columns normally take the width of the template // cell returned from the CreateCell callback. The width parameter uses the same units as a fyne.Size type and refers // to the internal content width not including any standard padding or divider size. +// +// Since: 1.4.1 func (t *Table) SetColumnWidth(id, width int) { if t.columnWidths == nil { t.columnWidths = make(map[int]int) diff --git a/widget/tree.go b/widget/tree.go index 86a12d73d7..aa06da7a05 100644 --- a/widget/tree.go +++ b/widget/tree.go @@ -18,6 +18,8 @@ var _ fyne.Widget = (*Tree)(nil) // Tree widget displays hierarchical data. // Each node of the tree must be identified by a Unique TreeNodeID. +// +// Since: 1.4 type Tree struct { BaseWidget Root TreeNodeID @@ -44,6 +46,8 @@ type Tree struct { // isBranch returns true if the given node is a branch, false if it is a leaf. // create returns a new template object that can be cached. // update is used to apply data at specified data location to the passed template CanvasObject. +// +// Since: 1.4 func NewTree(childUIDs func(TreeNodeID) []TreeNodeID, isBranch func(TreeNodeID) bool, create func(bool) fyne.CanvasObject, update func(TreeNodeID, bool, fyne.CanvasObject)) *Tree { t := &Tree{ChildUIDs: childUIDs, IsBranch: isBranch, CreateNode: create, UpdateNode: update} t.ExtendBaseWidget(t) @@ -52,6 +56,8 @@ func NewTree(childUIDs func(TreeNodeID) []TreeNodeID, isBranch func(TreeNodeID) // NewTreeWithStrings creates a new tree with the given string map. // Data must contain a mapping for the root, which defaults to empty string (""). +// +// Since: 1.4 func NewTreeWithStrings(data map[string][]string) (t *Tree) { t = &Tree{ ChildUIDs: func(uid string) (c []string) { diff --git a/window.go b/window.go index bea673b44d..fc5f812374 100644 --- a/window.go +++ b/window.go @@ -66,6 +66,8 @@ type Window interface { // SetCloseIntercept sets a function that runs instead of closing if defined. // Close() should be called explicitly in the interceptor to close the window. + // + // Since: 1.4 SetCloseIntercept(func()) // Show the window on screen. From e0232b1c3a77341c254a5ed460fc981e73d256c6 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 18 Nov 2020 16:37:05 +0000 Subject: [PATCH 03/33] Add 1.4.1 'Since:' doc --- canvas/raster.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/canvas/raster.go b/canvas/raster.go index 8e955167e4..0c9bb2bbb3 100644 --- a/canvas/raster.go +++ b/canvas/raster.go @@ -15,10 +15,14 @@ var _ fyne.CanvasObject = (*Raster)(nil) type Raster struct { baseObject - Generator func(w, h int) image.Image // Render the raster image from code - - Translucency float64 // Set a translucency value > 0.0 to fade the raster - ScaleMode ImageScale // Specify the type of scaling interpolation applied to the raster if it is not full-size + // Render the raster image from code + Generator func(w, h int) image.Image + + // Set a translucency value > 0.0 to fade the raster + Translucency float64 + // Specify the type of scaling interpolation applied to the raster if it is not full-size + // Since: 1.4.1 + ScaleMode ImageScale } // Alpha is a convenience function that returns the alpha value for a raster From 4584a57ca179bb5be27ce56d21652de622eae4d7 Mon Sep 17 00:00:00 2001 From: lucor Date: Thu, 19 Nov 2020 20:02:51 +0100 Subject: [PATCH 04/33] [fyne-cli] Android: allow to specify an inline password for the signer's private key --- cmd/fyne/commands/release.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index e6dbbe41f1..5115ae086e 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -23,6 +23,7 @@ type releaser struct { keyStore string keyStorePass string + keyPass string developer string password string } @@ -41,6 +42,7 @@ func (r *releaser) AddFlags() { flag.IntVar(&r.appBuild, "appBuild", 0, "Build number, should be greater than 0 and incremented for each build") flag.StringVar(&r.keyStore, "keyStore", "", "Android: location of .keystore file containing signing information") flag.StringVar(&r.keyStorePass, "keyStorePass", "", "Android: password for the .keystore file, default take the password from stdin") + flag.StringVar(&r.keyPass, "keyPass", "", "Android: password for the signer's private key, which is needed if the private key is password-protected. Default take the password from stdin") flag.StringVar(&r.certificate, "certificate", "", "iOS/macOS/Windows: name of the certificate to sign the build") flag.StringVar(&r.profile, "profile", "", "iOS/macOS: name of the provisioning profile for this release build") flag.StringVar(&r.developer, "developer", "", "Windows: the developer identity for your Microsoft store account") @@ -195,12 +197,16 @@ func (r *releaser) packageWindowsRelease(outFile string) error { func (r *releaser) signAndroid(path string) error { signer := filepath.Join(util.AndroidBuildToolsPath(), "/apksigner") - keyStorePass := "stdin" + args := []string{"sign", "--ks", r.keyStore} if r.keyStorePass != "" { - keyStorePass = "pass:" + r.keyStorePass + args = append(args, "--ks-pass", "pass:"+r.keyStorePass) } + if r.keyPass != "" { + args = append(args, "--key-pass", "pass:"+r.keyPass) + } + args = append(args, path) - cmd := exec.Command(signer, "sign", "--ks", r.keyStore, "--ks-pass", keyStorePass, path) + cmd := exec.Command(signer, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin From 6813d05d4950b0d422b5b67337166dc5ef81f9eb Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 20 Nov 2020 11:46:55 +0000 Subject: [PATCH 05/33] Fix the content minsize for Card There were a number of small issues here. Also reduce calls to child MinSize(). Update tests to use rectangles with border so we can see for sure --- widget/card.go | 88 ++++++++++-------- widget/card_test.go | 33 +++++-- widget/testdata/card/layout_all_items.png | Bin 9065 -> 8761 bytes widget/testdata/card/layout_image_content.png | Bin 3375 -> 3020 bytes widget/testdata/card/layout_just_content.png | Bin 647 -> 263 bytes widget/testdata/card/layout_subtitle.png | Bin 1308 -> 1332 bytes widget/testdata/card/layout_title.png | Bin 1115 -> 1138 bytes widget/testdata/card/layout_title_content.png | Bin 1678 -> 1354 bytes widget/testdata/card/layout_titles.png | Bin 2198 -> 2207 bytes widget/testdata/card/layout_titles_image.png | Bin 4908 -> 4925 bytes 10 files changed, 77 insertions(+), 44 deletions(-) diff --git a/widget/card.go b/widget/card.go index 71900000ca..6c04c9fabd 100644 --- a/widget/card.go +++ b/widget/card.go @@ -110,33 +110,41 @@ func (c *cardRenderer) Layout(size fyne.Size) { pos.Y += cardMediaHeight } - titlePad := theme.Padding() * 2 contentPad := theme.Padding() - size.Width -= titlePad * 2 - pos.X += titlePad - pos.Y += theme.Padding() - - if c.card.Title != "" { - height := c.header.MinSize().Height - c.header.Move(pos) - c.header.Resize(fyne.NewSize(size.Width, height)) - pos.Y += height + theme.Padding() - } + if c.card.Title != "" || c.card.Subtitle != "" { + titlePad := theme.Padding() * 2 + size.Width -= titlePad * 2 + pos.X += titlePad + pos.Y += titlePad + + if c.card.Title != "" { + height := c.header.MinSize().Height + c.header.Move(pos) + c.header.Resize(fyne.NewSize(size.Width, height)) + pos.Y += height + theme.Padding() + } - if c.card.Subtitle != "" { - height := c.subHeader.MinSize().Height - c.subHeader.Move(pos) - c.subHeader.Resize(fyne.NewSize(size.Width, height)) - pos.Y += height + theme.Padding() - } + if c.card.Subtitle != "" { + height := c.subHeader.MinSize().Height + c.subHeader.Move(pos) + c.subHeader.Resize(fyne.NewSize(size.Width, height)) + pos.Y += height + theme.Padding() + } - size.Width += titlePad - pos.X -= contentPad - pos.Y += contentPad + size.Width = size.Width + titlePad*2 + pos.X = pos.X - titlePad + pos.Y += titlePad + } + size.Width -= contentPad*2 + pos.X += contentPad if c.card.Content != nil { - height := size.Height - pos.Y - titlePad - contentPad - c.card.Content.Move(pos) + height := size.Height - contentPad*2 - (pos.Y - theme.Padding()/2) // adjust for content and initial offset + if c.card.Title != "" || c.card.Subtitle != "" { + height += contentPad + pos.Y -= contentPad + } + c.card.Content.Move(pos.Add(fyne.NewPos(0, contentPad))) c.card.Content.Resize(fyne.NewSize(size.Width, height)) } } @@ -149,37 +157,41 @@ func (c *cardRenderer) MinSize() fyne.Size { hasImage := c.card.Image != nil hasContent := c.card.Content != nil - if !hasHeader && !hasSubHeader && !hasContent { + if !hasHeader && !hasSubHeader && !hasContent { // just image, or nothing if c.card.Image == nil { return fyne.NewSize(theme.Padding(), theme.Padding()) // empty, just space for border } return fyne.NewSize(c.card.Image.MinSize().Width+theme.Padding(), cardMediaHeight+theme.Padding()) } - titlePad := theme.Padding() * 2 contentPad := theme.Padding() - min := fyne.NewSize(titlePad*2+theme.Padding(), titlePad*2+theme.Padding()) + min := fyne.NewSize(theme.Padding(), theme.Padding()) if hasImage { min = fyne.NewSize(min.Width, min.Height+cardMediaHeight) } - if hasHeader { - min = fyne.NewSize(fyne.Max(min.Width, c.header.MinSize().Width+titlePad*2+theme.Padding()), - min.Height+c.header.MinSize().Height) - if !hasSubHeader && !hasContent { - min.Height -= titlePad + if hasHeader || hasSubHeader { + titlePad := theme.Padding() * 2 + min = min.Add(fyne.NewSize(0, titlePad*2)) + if hasHeader { + headerMin := c.header.MinSize() + min = fyne.NewSize(fyne.Max(min.Width, headerMin.Width+titlePad*2+theme.Padding()), + min.Height+headerMin.Height) + if hasSubHeader { + min.Height += theme.Padding() + } } - } - if hasSubHeader { - min = fyne.NewSize(fyne.Max(min.Width, c.subHeader.MinSize().Width+titlePad*2+theme.Padding()), - min.Height+c.subHeader.MinSize().Height) - if !hasHeader && !hasContent { - min.Height -= titlePad + if hasSubHeader { + subHeaderMin := c.subHeader.MinSize() + min = fyne.NewSize(fyne.Max(min.Width, subHeaderMin.Width+titlePad*2+theme.Padding()), + min.Height+subHeaderMin.Height) } } + if hasContent { - min = fyne.NewSize(fyne.Max(min.Width, c.card.Content.MinSize().Width+contentPad*2+theme.Padding()), - min.Height+c.card.Content.MinSize().Height) + contentMin := c.card.Content.MinSize() + min = fyne.NewSize(fyne.Max(min.Width, contentMin.Width+contentPad*2+theme.Padding()), + min.Height+contentMin.Height+contentPad*2) } return min diff --git a/widget/card_test.go b/widget/card_test.go index 5e1f9070e0..4eb9b79a74 100644 --- a/widget/card_test.go +++ b/widget/card_test.go @@ -1,14 +1,16 @@ package widget_test import ( + "image/color" "testing" + "github.com/stretchr/testify/assert" + "fyne.io/fyne" "fyne.io/fyne/canvas" "fyne.io/fyne/test" "fyne.io/fyne/theme" "fyne.io/fyne/widget" - "github.com/stretchr/testify/assert" ) func TestCard_SetImage(t *testing.T) { @@ -74,25 +76,25 @@ func TestCard_Layout(t *testing.T) { title: "", subtitle: "", icon: nil, - content: widget.NewHyperlink("link", nil), + content: newContentRect(), }, "title_content": { title: "Hello", subtitle: "", icon: nil, - content: widget.NewHyperlink("link", nil), + content: newContentRect(), }, "image_content": { title: "", subtitle: "", icon: canvas.NewImageFromResource(theme.FyneLogo()), - content: widget.NewHyperlink("link", nil), + content: newContentRect(), }, "all_items": { title: "Longer title", subtitle: "subtitle with length", icon: canvas.NewImageFromResource(theme.FyneLogo()), - content: widget.NewHyperlink("link", nil), + content: newContentRect(), }, } { t.Run(name, func(t *testing.T) { @@ -106,10 +108,29 @@ func TestCard_Layout(t *testing.T) { window := test.NewWindow(card) size := card.MinSize().Max(fyne.NewSize(80, 0)) // give a little width for image only tests window.Resize(size.Add(fyne.NewSize(theme.Padding()*2, theme.Padding()*2))) - + if tt.content != nil { + assert.Equal(t, 10, tt.content.Size().Height) + } test.AssertImageMatches(t, "card/layout_"+name+".png", window.Canvas().Capture()) window.Close() }) } } + +func TestCard_MinSize(t *testing.T) { + content := widget.NewLabel("simple") + card := &widget.Card{Content: content} + + inner := card.MinSize().Subtract(fyne.NewSize(theme.Padding()*3, theme.Padding()*3)) // shadow + content pad + assert.Equal(t, content.MinSize(), inner) +} + +func newContentRect() *canvas.Rectangle { + rect := canvas.NewRectangle(color.Gray{0x66}) + rect.StrokeColor = color.Black + rect.StrokeWidth = 2 + rect.SetMinSize(fyne.NewSize(10, 10)) + + return rect +} \ No newline at end of file diff --git a/widget/testdata/card/layout_all_items.png b/widget/testdata/card/layout_all_items.png index 19222a02a93a79dd81c9e70d344f90d28c80508f..775311a45570510c5282c29c4167ba36e132c585 100644 GIT binary patch literal 8761 zcmbW7cR1DY|M!orlX21^Ax8EI5UdD!87Vc7*UN7_H6Ll5oZ1UXlha7bpi~H1pFKn&)y_ThmCEA1w_+Jy zsJO(foWJtfwaQXt#ieNoS2pCPYjt7c36Jf#?1$bkMqU{LDLPJ6FM@#ZDvG9LY<5rd z^|rF_Pl_`ElHE(xX{pYuV)&T};lJM9yOl117!*0NRIZ6F;@d-iRe#HX|8-?7`K+$3 zC3Vc2m{OQ-8^y$>Fh;vjs3`dy8LpAdf$9Fk_(nq+8JVlsu3ckeBPAp2Ur?VIR7m2zB7%Jwk`iX|ARgi%)wM$u9S-;BViJ~G!-1pB_0>zp~gBk{J#JuR5_;lKfNjQRy z?xLQ_W*QZ1=H=zR6hD|>{#okk{Fp02IwKmF<>TXHRi>TUha#T(^XIE6|81tIoE-M> z<{w@o7kG8C9_y2}UVHO*BMzv45N7d-@=;tNXXWL!J3iPcE-uDAFlNXU?Pw+s`>wk_T?@?)o0Clw0(qCE&6?U+yg5 zc+V}Dfg;XO&1hkG6zKYh5M&urq3?-_ik{$m{IcJ__m9uc z&W0(@h2MA9*8HpIRgN$x?CV0E^6s}1EbloI+Q+Ni-CbN1MK3kTTg4gDw-^_HvH2;z zh>(hoV}CGFQ9f?OsoAdavB=L-{aUrMRNF}l0QjwS~cu9et4X( z{!uqC)pvF5c81D4IT6B*5GTbFDSMug@$j$2sh04=Jhe12FE>JsGb+e~Nv!yjAMY*F zJX^ZDl!T94A{h${3o|8ju&*RJkEr=XYo6{bLV;=vVq<9%aI-2`q_0rLe?66aD8S8a zvoc!tbiuf|B0JmM_&=kWnwc%wvJg2dOJ|^Pjasm;N-cVn6%_?Kxo+HOb@Vnar&2*` zlLw~vFLWf`7~Y~Ic>MVBd3~~J9i*XW+jDfV(a82f|LNN4Ne^FsZEbC7sk5>B6@qD} z2I7i?si`S6GOMm`VppB1=~H|>nvbCH{-a0z4GsRc29VPakm*0ugzfb$Ept`#3JMF$ z9wH678*`IjniLemr8ANZxB6r+TI?`~y|c5k3%_t9yU#L-SMMud=PrLh6FmciRq{R5 zHzA;9xvm(lMA=MOgcslF($mu?uLnh3oz4tEbW53< zn##x!zwKFDUCr)aNIzyPf2XZi5+1Igs2I_w8!X*7F`=BHQg9OHIAaJ&*Eacaj}h-q`y(}+qb_vQ*K4h?e6X64_XPO+TQz4EJZ;@ z6^OUX?_yM9(nA_@K6G*_(d6d6ex0bgtI>}!87+symCWjAaxgG5T7OsI%)$wQ198ykyiHgO5*)jM zc;%oYn2v;_KIT@o~{>OWH`yIOZUj5wUu__zw>gsY(XTZ>fS65eq z6w*>tH}REe7baEMjo;x-I^1Yw5t-ZcBugMvA$p@+R9KiGclE`K7a$Iik&&jKxB@Y{ zdU_g#+Ja-J+T$xv=tC}EG9|94t}fCpLoUZMe%wf}OW`*Q(?2-EZ#g?VOB~E+hJ_*T zJ73x+dmzIaliBP+szXD^tDCFB(caM!P(;Q?wY&1`@9eDL5GhqElmSGS4vqHDc2Kmz zI?X&!t6xs93*;4GP|8!IqovJL`w+_fw5_X)a$v-e!lIzCl$0)fXS3r*{rcCl&?BR! z<)Vl<{Uhhm$k~IPC74)wW#!$iEg~z2T%=nCw_cS1E9+Nf=3-jx$D(wyU}+;h`ugMD zR2f!z9PW<;*4EZ`dhe1YCuf6?H@0h#h&i38&&GAVs{7(kK_p|sEDQFlahYdc=j*mWT|lp+l(0Ekb{GR27bq7 zw&tvTeSKA`(cewq`s`{M8C}+VY;7`iC93J7>1D%##>Eb)mjZlzy#r@pbzr{6x~6eT zp)g#GDXb`RCue6^>hu&LCdxW5H8@AerBEOb=H@J;qoaHjjCrTyAQip`3psjvdK9Eh zMqXknNZAI*nw*^0U3&uD!NF2d{o$%emg<6KcK~zubrQO8GaT~AWt)PQJT)r|i@%3! z^#*Ec#DCmJRYy4{=XZae`PAMvK0a<~XJGI)QWa6y5I{sGsdhiq7VY9Fb86<2EM)sC zk2_C|D@M+yfYyO&ZE1;U`u&&qTUOXSG z_pz#QL$2C~6w-HvgSMrO(sn?~{h@7~Y#E?8HlZIwE zIf;o6e1r(Rk%H`ErwgY=lE8l@vsAk}#a&!or8u!9>4yk1TE!{g-0DwVa`4nmPh1gM z>k{#}thgG=7PRtq$C*IB(yGTDCMt^< zLULjouC{7Zatk-~YdPecH3^8FS8~EeROyjNAf~3aR!K?5)y-{`S;wSinp+|bde@oU z-jR{{88LbGSi(Szl$4Zgzavxmv2DwF1PmA~og(g2)mLzGauO0k3LiR}aO9ksRhG1? zYgt@P_=KqPWfG{fkB<_GT5fKxL$^QjDK;Dph^on*Xq2ePmjCf%$Q=hdPD6Sj+fji` zvG3WJnIr}lIruiR48_|HvlNozao1p??;%%LS3!nCv|uoeBK_dUgbkeU`G6qS*BzP) zod0&ay0~ERm@D7E)t|*ig+6;mZxgHzkcntw;I_$tof4gyb=<8iQ0$HpFek{3dc=IIy!CuQ(dJwGZ1i* z4afv=*m&Vb){VM-*5ueBO94+$&-*W#ALprkTCz+#6eh9(S%{|)VKzLoE;ocO?-=M{<`C2@+jgw1Vs~cY_u_>+Hs>qNAe$Qxg*t|Lwl0sEG-E7jmZ7078H9d6zq> zT~tWqAE(OFP)vD!+2_wpVo$fnDxD|wCO`4h)0wb=a}r>n3~$yhHg1O2(n$BEtxc}v z0v{GTBK!=OMc7vYCMvvnb8{2=$j6T#tD0nB#&eY4aQ&zKyWF{?PO8o)q}mXY3{Vk5 z$@u5bpKT{jbl4I~UtfQ&<6-__LP7#m8(4g4X~~3-UWHiw)~G6CT0&f0+!}sb`?M@i zDPm6Qp&AA?R^d4PBTE6AGFL(v7=jc2|PmM*o5e@s+Q+ID*!Ve{>xh+F{E7LguS^Y2?t~bie0DntpzMzfjNx zVSK^>Nwzr71RPfa6wXkGuLR!2Qb60w>kvdCMKL=yHFXUIh32LM1kD|^ij>V%&o|>w zad{pPKro1+59zZM=ne9B^?yTeYY>3TQsqEL%JvTrv&YCSE-p4q(zKC`OCW;@m5F*6 zT(C)4WP}uTAd~7dg|nBC`+OMfbo75;5!;yVHzLAxiITFkF>>#d2(3w;({cR&T)}zRgzYC{uPN{v)Y;%4i?}U6KY24ZXMUI>yiD8k>x(T22Wcx*u_Q?TeB9jJTv7cA zgH$xs7eIv}QqTsSrOFxiy`fmoAVJiIlbo1P6^Rmi>g7evA|8Qh3!}XbeCJv^Ha-sR z&LfeD>i*i-ATsLq*-hYt`1trfLA)PUCO7g-(~I-$z?($xi00*u+T%G7cUMGQ7vsyz z_WLBXGW}9ww4XzvxEc*A;I}^&`r*Te ziHQmMIJV$t&;AjQpy1;hX^RW}ISM!&idd`K&DO@o#?uqumwDgX%1Vvvv81G=tZd6G zL2HV;*78?l|M_^(1pX9m492iIj5c4r@I!8HTTjn@lkKX_d|e zkTF-Rt-!kM>gg%U&tFcczzUM6MI9G-dxdSMe zg+7uaY;I--p%D+3oJ&H&?`Me_m;k0#aT5_YHUP)FVwa-V@kcpnPhlHfGzYVxs6keh zsznY+nZ-%&~$WxmJ?4Wu_v9kdZO>FZ*RXAw5A(Ld^zo*tlSODfU>B{ zVd`sXk9hte4_I#@(Zc+E1r4&qEdV`jN7~7_2jZ7q8%+6|nwr>^UJ;7}kJlWoRyXnV z>Z?LrHFG6J;E5`PFGfaF<-dJXqoWZtYh#rr+bIM-He(gVpFVv`Pd9|JnGW?xoGLOW z#mB2XejH%p?!HGYzMl@i>q!#}2nb+^Z22^Do?RKFjEKp?%q$@>5jxE7*Wk17oy$#H zshU1&>*>9b#DEbSD$u&F@lm(fICv^N6h(Z7ib~w)U^`nWwJm-a@OXP|UfuVp_ujZW z?3ybQ;+t((W**DdB4eSQ9YZ2O&t1&f5)ntdtE) z;zgP5q0s~9hfwc~6q`&oG&N0k3I8VEsR5Il$fJ`6yiP2ot)l~TMD!(^^aB^|6_Jh4_n+D};VlVdGGT*vGf4+@@ z>KTWPt?e}lCoEH*8q&A>Q~T#6^c@kAMuO0$%fI;iS4)9r1mXkJBRCBy1Y zN~j7yOVs3MdkIMjWl`Bx}AXz~sq(SHC=*;!-x6C^c z)3>e4s;a8A_edV@?Cd;c?_bzXPsdEUB8daRZ;V{|l4Qhfb*R@o>l9F(u9|1cpAy`i z?P+6$k!e8`ZeDpQDxLPldYHFl{EqiN-@-J2oX)Xan=)r0rn0hf2GtDZwI0x8U0GON zov8B>2{EdwgvxQ;n_J?2P_HkuZ_P~GdL5*hl~tOX?rgC1%7y-g>@i^l&0^zw zc6Pk;k96z2Z(q9>+&W$M<%^J@;6*VB5fKpy2^I>vOXA)Y@84hL<&A2Zdfxm8=mF>w zvcS)u1@c#U1Vm65>D#K8+5X(*+M{_N;bV2$yA*bR9I%v6R- za!SgRb`}|wDR^Xgd3i&ZnwlC>F)<(b(7wLDK--WpKvo8bKrV_U6r- zh7=7BG^8e{hw68HU=KRabrx5xgVxrc94tYHCSs`$LEOE73(Q z>+tvK$*|DY%I)>#g$4Za-tYSD9|~1By)RP8T3IbZ3)`R1d^xK5uji(vrk<5<3961u zOY@y+JNHQ6!o|e}B(eX2M4|A}-#>q1V`EFqyBHW@s%Ex&B!*MXAnjuR{m?M%g1*OP z5fPp8Lf8p^ohs*wHn+D$-Ihn7Yf>6~l>nLgo91O#(eh|p7Z7J=ZB1fKwev1Y#@*fB z%d0v+-&#c_`kK$Zjz-5CNS`xQh)GBSPUIj5r|*gg3%ld^=h;IqSgd#M+>v|)Q4zM} zW}ugsmy`(Bbx}=1LgH)@0~3>togFh16U4=7Af=xso^i&=!Tpe4S66!(8e)Fd@&`=? zF-Pto(MYp))Go(sT-Ku7T^ZJMy##@n{%oaNW<3L!myM|Bs~J|VriL~fYmJ{U%NwxzbPo_8d1QQ6d_AwL=F1zxBJamt6+bB#Ja)A z$cS9`BZtZ{K;wq_^=$f7(yt!@UYVqYZ$b=vdUC8n)?{3R3+OUm8!cOEPq+>U(O~jU zH4nf806-y;TMO3lK%>LOB1+dm)VC#-qX_hx$>+0`{TdZC>CIWEY*PEH`u6u2x4mLzw#cUpy48e3*pW1qNmrZ zzjuHOfYBoD$N-#d?d{nm03*f=%b`AoNyYW`5|x(Kxw&#|aRer9N`f#xSHdR#sHH{r ztS~3NpkkqV(2lce-u7sjHRNi2*KHjfqI>>osHvrMd{Ec)DZ19 zR#w`dEgu5eLh5O1IsZ==ay4Tp^sg4Wj7uF$npQli9{-lQm% zLBbvXPMF98qvfu4B=UGI7q?0d>t< zPl?D0R)vD98zIzB=_#LuheHeD(uGi(eltE{XHw$bOAY9YI^ z`Kc*_#8$EO1|smCU+8z2OM4g+)%EpxQRMo*c(YIYK2u+V&3Ah=jS^-lOlafk>-`|E z_gbq3sxEh18C_nsIeXzI87XOOt6`J3wRQgB+4RN}c0G%B%eQ>DZ{uO*rV80|adF|G z0Vyc_s`VTkZY;!9ht$NlZz* zQ%HHbEuihiix(kN5cgO&1V;g+SfEw9-Q7p|oS=6+{rNi%%~Y$h=E>0q631%p-(O9A ziJO_3F=>tZKD!BrnJeSfNv+d(JpPS@UtLKF|K-b#Uu$1AY16tJG({wuR|K?L&fLf^ zEO~8IWDA+z@ifb6h0|=iSx4dPBec?rq&jh|T0(M4jL_SbCe?Irw9L`U3vCnk7fV$#6?Gc zvivZkjgcrn)43XLC>62g?Oh2aR2>hYAi-gl1h@AZB{|OI_WBArc zR#sMBeF#|Iyz5n&H-59TQ*pe7LMj@NuN{52{?3AfNo(^Ooh} z#XJ!T1go6Q&yrc_-+wneW|*~Nfj~AqYFe4SxLH|Qg@oK%qb|v^=;LrVJlKG|k=8SxYeK>8%f^>$8+u8&?{&^Z2)+<+D!a07m zSAQoDgJVeTA1!XWd^Iiu1A|&R1xRR{jhkG?Vw)kheK~6h7D6gLrJcL13dm> ziz7)Bzj5(MQg35^gnfA4Ub^8IFtNN5C>jEafRk8qpzzw@8}BM+)43Qc~EynffV zA>i+s5Ih;O{2P{Yo#!Sh?%!WT%s;qa{L>~zPC&LrQkJ?YiFWA_iOL}nLZNt6kpKHS ey@5cSo>p+Y5A6>jZ-GAvLCD`zmiZ`c82CTBOx!8} literal 9065 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 D9N)9L literal 3375 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 delta 635 zcmZo?YG<7wUT?|4#K6E{8(%$#fq}`-)5S5QV$PdejvgX`GRHrDPkWww+wSHHo;wSg zG`8>^b1GZq?Z^^1{X+z&kelo$g)3{Lm#?UfYx;0u;o|5L0e{h}j*k3}Y(gJ77Urbh zkStG&Yxy4{*RhKyU+%~6IoFQf{rO(}*;xbQeb;6&Cdb`l-oaF_$l)Z=qOk8{`QnQl zO$y5s-%Jb&)0+DA{S3t>g%x3|%a)&N3_8Wp7~8DC;>gh?zyeXv;V96AB5<4g<16pg zcH-;z#PNK+^yyjn0sB=cC0RS~etdH?uH#pXk>UI`d*rHw`+Qtx*QNYQH!_pnZavTT zS-t40wbH9PH=Q?@Rr7z_{=zok!@u$$8>f_c%4M5vp73i<>HF_q(k8#IUP)ZUUuLo0 zY^(gEe<@qGACaGb|ER?7ADb*|qI&$c*Yuk!>9SVW?JQZeIicpsW-qp5huhP;|Jt5w zJ(05@J$UU#?cMid_3L*8zMFLKvcK+Q`84rK2dgZK>X+TPue|A2Mw=0L;o4}K``_Q+ zw(9zG>Efa5_g~&Jv-rJj#yuH+cK^=CIC1S1$ww#VZFP0zx))Qvz{6zsS1S>@{jtSc zoTe!rId=cc-idLx&yKIG`*QEDFqd@qwTE5h>(~Ey;`H*U&z>r~XHwOxzwdNzwKn~j zU^MIh0^X5n!sna z{wYD4Q!g8Q^U&-qKcgLDEmp=0iKPkq85tP<|G#r$#?mQ9U!;JEjKR~@&t;ucLK6U# CZY2!> diff --git a/widget/testdata/card/layout_subtitle.png b/widget/testdata/card/layout_subtitle.png index 2e1d8b00abc9f9e5615c4c70fd0f59e1092693be..429bec1091aef1ac635467d6c8c1379a160266a4 100644 GIT binary patch delta 1326 zcmV+}1=0GP3bYE47k@Db0ssI2(G23Nl)hP+X06wGyFlW3Bq27HQ=|!af!i5(P#D>0P8; zy=htGSBh8d_?XUlV%KS&I**wLo!{!7^FQa@|M_{&(d(sJt$!9E05H7N3H)CmA}~Y* zhKRsWqH?KJs#GdVl+5BGlgU=DT-jM87E!5G)~;Q85rH8hFhm4~ zh`fUGJfxfAH(P2`}gmW zNW|@S@87>4)$H514_y?CML`fICMMdAd7d91A78$FIe#ijB$8^i8jHoGQmIm@lt?51 z00?0q5D)|bZHIO1){Tse7z_rAn$0Sc$-H>+!fZD4JilVaim|aVQ9cmD_wV0VDiwu7 zA$q1BfIe2l=;-LOWy^B8TzAOp^&UBLq_ak=)jodwxLu4!qZ*CoZ6@fT(=#bfLe)QELP7|qA`uzEGH0RFHrcIl+Zr#c-Of(v;*XxBsA%7eW zfBpJ(K_*(ilF4LRzaf!GXfzu6Kj?J2P$+~#5JHAwXqujyno_A$*RNmSy?b{s7(`K} zQW*}1bvhkQ({j1oX0zqT)XdDx z>C>lMt=8eghtWl=)yn7dCr+H$uzz7gJDGVh@20zPA0iONVv*yxa=F|cs?}=gbXpLE zd2avh+c!}q`UY*Q5m7Fe)9G}h(U>z@tyVdX`(598=$__~XcK0$*+1k3k7%0YF&slg zV2B6|5rH8hFhm4~h`<3Y-d%7k?=T0ssI2K8bk;000EzNklv8a$JFe*rAkuo}I zS>#uWqjr3`oq5H^+kMsha_lel|qFSwby>1R5h9Uj z*|KG&QfW983 zlUl8oPJgG3M&qYXpVH~H&1UO#I$p2WYPDXua)mQvCX=yPEKaA>G%69m5R&dTC--&=zSkPe0cBPJ-J+7sZ<;e$C)!{Zr{Fr;lc$7Ax+aa zZrni4`WZ*9R!1U{?c2A9LZK~Nws1y+5W3xNjekbt_xmvnyLs~_K@fVqe*OCOqf6p2 zUXD0>_U!rd=cCc+jvYIWA3vVWW=HI3wOZwJIRHQ+ksLdA?B&asU%q^qNH9Q|g(S&S zr%s_mbnxIo48s1NZOW@8`C882qeo97joH_3G8* z3xA&F!-o$5fWa)wFwC51c67!zVzv*4SuB>FJ9qBdwJRJBdpsUagW*>@KYsk^KX<#` z*{wJ|`4tBBy?ptyP$=wIu3EKf;sGZ#0wEHKq*7_C)dB#_%*+ffe)!gaK0`z*m71EG zLi=cXdKyAF=lE!~bN<_)QmFs{?RI*r24dQ*y`u3fuEl4Pw``}px=AP^u) za_`=~0050flg(xyJa_;hq$uj*#fzN2ckkYP_Uu`=+a*ad7z~=tX7q(8lgUVuER{+S z!ogjGvWZYAeE$47TJvCN)22;Zw{9f}BAHCK+wDrF5|78fe*L;2Cwjk9C=`0XA%By} z7z_r*KbTCWSS*G@5JG|=a2!`El{%g7`t|F(ckhlyqbRD?YUA;^$z;NDT%l07T&{At zj6$D3f8Mia502w1l`5CZy?OISp-|-Wc@zzWLQ17ltyZ5teY)4{9X@;*J@k6La=Cos z#EA_XHuS~JqkNd*#$ydNSO5S3 M07*qoM6N<$f~?Gk)Bpeg diff --git a/widget/testdata/card/layout_title.png b/widget/testdata/card/layout_title.png index 7622bdf47cc5f06ee2c07098ab9bde6339bfa3ee..2a5212660634053efd73603b0580329b2bfa52fd 100644 GIT binary patch delta 1130 zcmV-w1eN>S2=WM!7k@qo0ssI2AX-Z#000CzNkl>}%sFR{Vl zl)#|0w3KZuD=XvXoS&cD?REfw!C=VG&yT0zR1t@Wc$u7>EGQ`OdcE!K?JAXu`;pmf zw%Kd|fRT}r%oEYs*;!Ll!){tE7MIHfl7z`edhi$pKx^g%itE;OkD=RTh#-EYabp%P0Tnlj#2n2?P zhFA*#InVU>{Gbh=jSgxCn>CFfJ@C+}qn@KVsLc z6h+)*AEU3ewbEK zQGb!}Ap{Ts?|G0IuVHm{H5*@FUn`Z$AFoP)p}{W30RU%bXE1nrdir7)xm>PRt6^-j z*|?J>wCQv@Ns>&aDgk;#U0od;>-GA^#zvZ^FE1}ilFZ5Zv>v0;I505q^6~-zn3$N@ z*w|31R3eec>-D-^F2CPzGMO408WOHb0Dlo$t#)~NnW89o^K&|#vFz2{+&nioH#0K> z@0b5Z`N66L7#dQk)MByJ*4ASouCAh@B5u1_Ebi&)X>Dyyrm8I7 zbmjB;()PxT$K&z){dswLN~JQcpN}+6-`?H^0)g!8?DFz*xm+Iag7W=o3MoQB-eaF; zW-O@E02YD3A`n;v0*gRk5eO^-fkhy&2m}^^z#1OkgdU=axZ6Doord_JE*#iS2{ wAb2hO=MldxcxWK72m}^^z#o3Aw(TI7<9=)9bVMIq9}NX1a|XL*$M?gbWt%W zYDKYas|U`!W!e7uC*7a?=5zY)_+9tApPiYV(VVxpH-G^^Br$XWzY16c0*gRk5r`b# zF-1|KP)ML+(g#5hVzHRp!WR(=h2(O1daDuupU=k=frkc@9RwJEq)-G&lHJ|iEiElZ zqw)FqImWZ>cKcudv%S5Yy7GAN_ZnaDca(3_2!eoVYinz6w;KRpwOVyLokpXHc}Wt72*2MCZ|rMIN=jf*T3X6BmX(!pbI#At?RGl=z+f=s=jX>$aH@zy zM7&H+P8Jjtc)i|#_V#v_O2z%iY&P3$HUPlL$Vldi=r>Eb4&)wbK(a}+IW&b>Ji1;%Kdw6(w$cpIb=#a@|y!`$B{o~_f7#od7 zm=FvGO(qk=FtB}gb{2}0NF-BJQ{UDQ4u^MlckOn&*Xw0}7^bqaQlruI_4Vo{o=?2Lb^$$7;30K%r24E5hw|8w>`I$HTTpFrYNv?&s2m}H{Lqn_ug+ftPRh5;M1ps(_d>k7aySceZrnVIJi1%o< z+NP$ag@pxwhr-GA@xzJvfG;5!cz<1?(Tu4d!w>uaS_`QudyFf`c3 zH~`@6>}EW4&JA*w{$Z^yTFx zNs>8#IiJ>JG#Up623}rX000vc6B`>FDwRqk5_!E|m&@h%`%NZOLqkKtRS6(MtJN+q zFH;l+Uw%%fGnTWOo15q6=4NJQ;QR95C_h-007FA6m0B#8+S*!fBYeDHpV;5uzq7N` z)zwv0RK#r;i^V-XJ*};+$yAlao34C5U)uhE4fl9Fe!o92FHfmd#MMZNWnWfkhy&2m}^^_%8qe|NlnLe8N!zyc7Tc002ovPDHK) GLSTZ5qW=p3 diff --git a/widget/testdata/card/layout_title_content.png b/widget/testdata/card/layout_title_content.png index 7f06af5797637c9aa2c9a9b3dddfdbb3d7781b3d..56a5ca6d628eb3dcb82be88b836f92ce2aa3c2c6 100644 GIT binary patch delta 1348 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 diff --git a/widget/testdata/card/layout_titles.png b/widget/testdata/card/layout_titles.png index 7c7854d4ff80c1631487be816c293e372c8743d9..100e29a0dd1560f158c78be446f51a9821f9122f 100644 GIT binary patch delta 1800 zcmV+j2lx1v5uXu|7k^g>0ssI251|#d000PPNklJgrYMBZ- zt#l|q|44_HW>{&UMGmr1nn-D8R5ZbwhD2dRiBSq+w6V=~_XW@ST=v=2_K@x?-}CzG>^yki_qB7*y*uYfH98uN00V%lvjg~V0gFIj z5eO^-K{flVR4UbKwUdHbKInA1mzS4mj=2c6S{)D&u)I+@fr*I;GZA=blSTv{lTQc* zBrKr_fk1HJzyTJE#pQBmXJ@T!)!EtkfB*3G>C>eP&kXbRh?5Qh9Tim!27^kaf@!^8 zZ+&XV0Fkudin^nXay`QmM4Rzh5Skm6w-CMMc>i zl@mmyrKR1vbxWyK!iQf^PmeXNVq;^kT)9$KRtBG!|3AlHjLHc^!`IihW45+7EG*14 z6MnsmH#~CWNJ~pgdV2cm)vHbOy}Y~*9Xb>j7w1S+E@so!#Kgq1otPOPAD78wG#V`^ zD9EOtk9xg+a&mHNYKlUktY5!AARxfj7fQ?9bfyR=VtJb@}tBnuTaHa3#`U4I?hL?{%Bl9Cb@i?wy@Ru+qumzOs>I{L>}_wU~qiA2`? z{qFAW#Kc6QP&jXCdwV-PXR{R8CZe#g@ZGz2rKP2hA3wfy>C)Oc9Jzd7U!UnFMPy_o zkH;ey?>QWfl`EQ#W5eR@uV25qf4jRYDk{>`(_v0pS{h6!6bhYA=kM=NR+dO4K0ZF= z;v$7Y(P%V6p^!$SF_}yXg#rK|2%@Q}NvG4n;jn4bCUKdn;mnycY&JV3B}FV20{}`(OP@V^HZU-dF^5vA92y!*OicX#{rk|+5Sz`O zot-TyDapvlxOeZK*%gO}hf`BiIUG(=QBho6Tw`OS?f3pKZ0Hdb3WdYrR8&;Ra$BrE} zH8tec4hcaJg@uI?5fK#?6;vwq(W6H^9*@OhIkE$0+Z=J>!iBQ3vbMIiojZ4)I(2Gf zWW>sb85tSD!NKsHVSax8$B!TFJ~{(u7LiDF{``43h>jjTN~KaAf1F2c-r&i~%F4{l zU2?q9U^jmj6@@x9TA9NS)nBTgbL|?%bi#Xk@0{CnF&CZ~1w6c=-7E zz>^E^?(U{HZ~4{$f4@VBP$+b9ae@8F)zy_CheVZPAjD$vwQJYR+BP>gcXf3c z3ezWB9Ulva*`kj(_RB-6B>;MPimSSf69)Eii(Ym?d`CLAP63h$6zo*Lqj7YBkSwy zckkZa*473~nM`I!M@MpUGK0Yg2?@!`$(fm%fkiTzY|oxO35~aJe++3J28jUkEGpA3V4hst-gIOeUODrqfAOfOLD8yp1 zN~N+a(rUG1V`DmJgrYMBZ- zt#l|qAEZM|GpsbwA_rM0O{6q4Dw<$TL!vOE#3+TZ@_`mf<=?`>mPCd`{?K&N9FaDi zvuWx6w6V=~_XW@ST=v=2_9xv}zUTGm?3{DG@B6yvoO|y%M?R|2XapDlT%8@je+yUy z0*gRk5eTZ;Z>3VHR;!&9%<@5})4jaBOmoadsMYF#fPm$V$_Y$NOqhwlT?2tdkX}w-= zeRvLHg9w>S1}~FI0ZlGvZEbCTe?LrLy?T{w2&-1Df(dVL?~4~NTK=7%KYzY``_{3r z|2{T|*ft0G^OM8@N(QcH2TRyBlN16x0UVQ20xba+lYasi0Y{UU0w@V53&X?1&E^j0 zlgI)h0UML+0w8~-B&7p`jsxKtQD~7!Q}r&C1I9 z{rfin;OyD6_4V~kCezi`RVtPC_xHFKfN zsMy%pD_5?Rm6gHg<^Rv|7o&1Q*YNfAt*xyM3kx&NgtvF`1CJaz($dnBo}RvX^=i|6 zFE6h{hYm)?#l<-im5bSMH8C-oZ-Xh>VQn@p$CqJ%_`waz@i}Y?!?L_3Kx6 ze|L99MMZjgI?PE+OM?l8LZQ>?{QdpO$`Xmh$H#}9T%=Ga8jVIM6w+ukCX-2_Pyhe~ zK{Pcr>2x~S9X4&+sVXiErM#A%FJv_9i4GoH=ub&1R>hq=?00 z06=MJ>9c3g1_lN)=1?k?LqkJ}iHYC8e;*neVzb$^v$G{7B^enR_wL;@JLB;1aB6BQ zhr=lQ~yii!%kT%MDYW7GQD>({SaT3UjGgXMC0e|C0u zadB}&LqmCaIYAH-iR9tKhp-ws;)I8XH#Ifw*s-IgriNVFAt4B&u&^*9BBG+Af=Z=6 zdi03L`F#HE+qVxMJlNXWYPvAF5T^Hv z!C=5a#B%?cm3;mB6#!s5%Ib8wdHbyO*t60_rBYK-}59e~ZMx!w| zHy0+1M&r!P%<0po!@|PIU>1qo63faqh=3>*3b9zMQmHJ9v|8=h*qBbITjcc9)6-^| z@Ciz)F+-(Njg5`X&d$zTs?lh~V(~)9E`sG{; z1OkgdU=au`0%1NMIzgw?CnhGG6wLBLr_;@H%s;yRXTe*PSq!XfdJ%!8=3`B3h7$GJ14|=p~3wF#3(rM+-xAq67(v-g}8&LSE5( z7-f=(Nz~wX-}SBa-M{X-Gv_|fJ!hYN_I@gPJ9u9)1G6v^2m}I$U-N)KZbCIw6paFM z33-8fH=Q<5&^S6+h6MsP^iL;ym65Bl;N9|>Aeu&F$CBHO?1RN$zjA!8LEajCKBzPJ zRL;clX+`6w7xe+3Y26uj!^J{Tr78V{JPS6!b z?)*9P+yB}kZNlz#_)UWf9`g0gI`Z=Y!Z`pg0fvsYMdL{!Z}_o18ZI!Xq8(;_2$j4YL~);kW_UQ*?796d~iq z#l=gtvk)ojbJw!7vsZwtQ1-zB2RKv_N>2XKtZq9UWmOYEiOC$_=2lB`mSC+hmEW!l zXoXStrQ&c@R8%+|PL1-#Mt|JG!c$LAPc@xyQwTBY967Xyx3{;K*MYk2-rk-LQ1Iyc z*4EZqi#!S%ZCmF!zR-sDeEb-K;R+26wY0Ph>aaqj^!N8i#>DgqZWJoVh*1aIA?cuS zW@eOy1v?$x=g*(LF8`iJN0UeNKp=E5D197{q@>^0NV>GgQZsPX8IeV@5r=?4=;KP> zys-iIgP$x=2>M-aRdsxLhyl>hR2~Wn3eTlxZ{qe7s3N-n*L*+`48!&HqviSUFS;lr zqqMX%E|}e~f?|F_rueKffwJ6xH#usqV=|@OpITYvD;1uc?NoiVRiF=|25R@IOwHvX*f$(xCFfZTG=RY@Q`eu z=H{|P6+M<)XTE&7Z&2z*#=(Q(83sQ+A%PmI=;G?SyhMgKLokV22{XmtqjvT1@OSb# z;DSS5UcbpZR-nMCNEfA4Xe3BR(ljt`r~=ldzP`S^oFA&Vu(OPOvA zv!@u#+1c5^J6QPRSJ~N=O~!)hR#lwIW~5AXadB~8s1GJ=i35CkP{PY<@Wpf-92{U* zq0i6G#vF+_UhrEoGg&w}IoU)Ykg2ID?Q=~4P~ZbL7cKZnAZvKMw9^DTh?7NxoxOe5 zGKhA*Cs3sRm(nNudwaE^w*1(EPoM6!xilB>XQzqzPV7Gxzbm&wz%+x`t5;(zRu1zy?;MqBi7s-MMPGQsu${&>+uH# z1*wi4$s|qYKg?+ni|ElaH?J^w7Y#IxtjTn`%)BQM2!>@k58kQ`lJHfKLA0|at|O?^0s;5dMClnNL68)(Aeg{2-*pzhdfBg`jlq8iiK9Sf+M1oDu%*=-yp3{Kbz6Djx zBq33xE1rT;1e-?j41>G=vp?IXcz+_Xg?K;5LL@mhwpyX+Ca<I?M5U#qWLrPF*_*-hli<}Z@VtfDukjLyoE7&h~GgSiGk$& z*gfA?`@tkzmZJcPu>?wgtQZTm6f3I=Vrsb!4S2Jor(pL*458Q}CV^g6PG)QoOLWV} zi`SzJ;YIv%$Q@tVMM>8TDdLOQ;A-?RD1qUgjLeX+L-QmncpHX{{bXltZS9DvnDJ?D zzn)>HEX-7wlj$pan=dbvE(ux9x9{C%K{{v_k%y4Eb+5ns8TOSrk2Xyz&+xAt$-ltG zMOG_r-c5>ydebNpMEQ#?UflDNB)jA88kpm(vxKa8;k>uZ1nbzxVTWGt+=?MDf!?A4 z$uPr6Br#2=?1klx*oOhw*q$CmnNP_TLjjs!0~~HI&3JK>(6-sHO4?x8c*N-@3?kKe z>`)K=WN)MHg$L+i*Q#Hx8TMcGn6Y7PW}62*u`D8(MOm2)L`Z0876&DDpEmCo85|dk z5!jSKn#x=E4ZuFyk*o_N=T_(O9P$VxH7%`=`JZnFkx0(j0ETOL?`p$HlZrbUKJtz< z;g7p@;4Tf>IOpnh)kq|E%>~QN=AmM0^l4?|YpJDJFi8opbWQV5?p1t|Y;c0PDoB@jW8GxBspaMI(=Taiu>s#& zDSw3L)Mh{2ZK$im5zWb^5g?GRUk_hYEv{*63(m!Y^YA90PUIqGRBxOi)9s#R#F|ZO zb+uUY;=;ln?#A`IfV=y50^xTg2_~m9B`powRAt@ud@sa4f4BO6f;>XGc9`fKV&6%1tpccOne0*vEKf~*cjMbJGgT<*4=PEWV zM})db5wlvALcNfyi(}eOi!nx-Cy|N9I%3rEadCmi%V;?Cf$z?%oK;#IzKNDZWilQO z5{L={PV^*&z%c6S>ii-i`SO8>=+#h^rRDdfE!y0un=0KIqwXv14ahR}4D~iWn589)fb#nKv=76@UKmiqycV^lwSLp)yF0zIVwI)sD4s<^N@{O! zzuxv0R29EY@de6q6S0j%ZzE{ZriO-woIl}Z8%em$G#x>#>*8qf^5UF^JOVGTcVnnBMt&T5ETAmyC?;s7vMD`}Zyb zUAYRtir-Y74a0{?r|19&F$Dz$7Q$SOePUuF3}ewAaF36VkDI$Mzb{Y|(%mthN{8`V~IErhi(S1?AgrYy{0{*j|n3SBHY$0M@Z4-_J zu6EY@VnA|+L+6{lH#hn0P7k*TXtmo4VeOrr93H^mUxV68HmY%C6coV8dQ2Zs*41@& zyb7R&7bct-5UJ5N{=ns_lWKpwXy?!v()MJxtl*<{7i|+2C8f>Fo}Ql2^P_vBRC8@; zQ3hsq_VyR}3AKS98!?N{ke2uFH35-~obm10*jP|-fG~-#lqR>xlmxZwM4lW)leFiG zy!S@`Vv{Gxy!#y;9om`k%%Z)C<>lpSSZ6o4rABviG+LTC435e76%}1)dljjv^m0_2 zDPH?8B8>!}nX@p0QGtPh2~l87bF+-h+T-FWx8>G`j*jJ&=9UJ4C?zKsd_z_EaB!y*g6xNk@gJ4@1N&poikw|>Pi?gay2st@$DhQR@Zf-GF8KNV2 zs}2tjbJNJ#*^6fh3JR|IJ38_b5oHfvY*(7qmDblYD83pQ(S&qo@=-tHSU!F7`HyHCkyy5JZ zI-GD7IQsgom)E|R@BliAl2)afVt)RVvvxJ%WUVJ+XUDm05F1h1V8e+S8}q_mV0O44FsWo=z$BzXLNG2``XsclnlE`*%iIau<~E)56UD06ey$)@dz zyz?nF&hPVe6f2^hH0%AQ-mfHkdwY{O74kDPhc4+ZI~u!A_A08ZT792`4uW7D0f!o1 zr>3@OaG3$6GkYAPi@wFfkP|U+@#z%n`hp)nJl+}zFvS-a7pobEf?F&rD{E>(@iRn6 zN2{u;CLM+QoILXpz$iysZ*Ts3yhZ+hCd~?GNyP?$9k@vgr?|mU-=(O}i%aw^udGbi z{pllHe6w)M+5h`OdVc<8!PQ^BhYv%+9OUKYCI9_8Rjg+I^eN%=0#rqnm6fHXycKFf zU`b`zP-3!h5QbO8Nd@%JmC)_6tc{J0>&h}dXW-L1Ie}8$0xKhb~B-zN~KXEMXp=$mbRelu_gnh40>J2s4$H zmi8JmKp@N_7TsdhjxobHzVnk4Ve>}n#%H5jhhPr~NlT-6ai{0!H#|p4Axj;>sH)kr zl9IVEIJX@A5?J$lw65;tf%2U@z?~c^cRL_8J^fSuT~ib)BP*)~lqtEnxo@>H{C$17 zV70-=KRClq3JVKu|Ij`C(Ad)QKuAcdP)|Zy8vpGZ9kj-E_9Ljv0OGhblT*mST2Jk> z(L*8;^q%@u8`;$N3P(KKwTGhP0F_GSQ3%zf(bFQ3^1 z{q*;x79!YI=SSa3Awv$eppfmg(T>CA=7y~IM&a{=e+;E?YtPb>LTtdlfI=V47+su7 znNA+qPMW&9=n@Jy-)H?4oFUatllg~-hxh{EGEsWP+10g<7+-;^N{WjM-=uExSPmj? zkKenI7k)?s(=#|26Z)&KfOQRkJ$G?Y z(q|~;4u32*EjV=G^1(l&Pd^E?Ex8X~jQwho&%02Rlakw`LmD1;xZg1UO9tl!@6-7mViGBsZ7y@!WB0TPmue@4=U;+gJ( zKgT8~uU6YeXuie7q-kz#0H5M-($j<1MOIF3e}8{-b93F53{)sS--iBuX9%8Nfa8H5 zyU^^-z4V4(^Q}S0>2?n2bG04Z`a@*;NRySID#cU2zP{b)Tjn<6S*@+DV$^lsXCO_+ z-&nt$rf=V~wq}DuF)PxUB(qXSCnY7Nbh<{YXAB>QP9My8vEpXvxg|~xpXqWCjwh9b pg)BFj9=ZPiK~DA+GX!#V!0(V-(0n#MWW9*i9ca<5D0`EelrjPIZxBY zXqX3PujD*5W*eGq2uOy*(ri$$Z$i%tOp9;7ugJGpzB+7?k?3zu;7zz=9eksm<1X)8 zJ{3OqRjZ79#iJa(eKQ&=Uv9rT)A?m4AFh>8wh0yUHG0Oe=iAxay;Ya;Sq9jwClr5%*Mi@2re#4(Dst0-NV)yahQ`r7OQ|-QJ-6j z)8@P0nMITglfI#$6dJ8#Xvip&3*77MOYR5LncVEz_r=Ak z50;22X=!N@3tKh_uBe`LS?Atd)l;WV!AO60cKrSQm$rjqFz4CW*!cNb3Zu`k^0&yW zd}7ytV{B|}OiWB}+_(`MdQ|1Ru(Z6)%s>yhAqdwIPWtuh7yBg(oBFV$$=YBR+_`8m zG6VwNA08fpc=A*N*1jcP462>%>SCNk5OtDx!H&X?_Tw&GgF}5@g}cngpkO4cGF;D3 zBXwIlJ3AYjr-IR~#Q2x*tR!){Z?f;3CIq*L!kju&#H*^R&PC2Fm(;&O>!Fc%m}6LG zifBR4VdR&_NZU%U94kq+;2jTd?-HGV-^efjgX+f7%#2jGn;50v4J@f2?=^1{gC89Q zK7*w%l$Dhspj8iPxPX9NLPiric$p*&b`Eri71X(PD=w>g`nrD0OKfb5lWdgZty{O& z3|RPu=^!#*l@R9l!s(k*+};D=N#(EX0tF~EIrEAu z%ea@P=V=H1`t*y5*<FvGF#V!PgnVOkVEA(FXFK;``x;N0FWMvU+9|rIReS2Kwa6Y&KsHmpq z=8GuQv=`X>h)38s=9w@z8{6#ctaI~eh@i4^<~{qx<>gtI5MmZ176Jj%;CeFWR#!c( zF&-Y0Wn)uQCzP0cG#;FBPEJmRG!wRuLQ%w77F$%S+f$68x=D$Ni4aJt-rZR{9g`Fw z%sCiTL!PH+_9E#eI#CD7$vHGQC<=$Yqn?5U1_wWhijtceaFgHQESez?Yufa~8LT<> z_xBBmqRHUcbc98dJMdoxb>$=_CDG{U5fR<~p`jr>BcE(^Y;JkBG#vyEp7ZBXsd|x` zLK^U&Z*DcqbmK{4x^fZ{ z9pP`^%(&tz$BC2S!sGGg5(7Uhh}^vGmLF|0Qd1vn{j2--&u^<~mvTt>SvJvp^yt)7 zuMNL$(mZvOMsu!gf5o8KHE2s67O z2y>F>p*pY@f>} zOvqtH@M=o{0D!y$p_VjQJ!tgm>?%8J_QL03BJ~!Z0;Y_ z1n+v8nkJb`i0Iy*X^G+H=C-)VY^Gv%N*gXLCwG71>jSz+4sKMuLRMbLmM$gd`SS{o zk41FQP5+MKDJ>(Q!0zP`SNg@wVv!8rp< z>q$@8UKj_iPu509!=$C9lZ0)3$fc#F zgW7aMoaD`6UdG3>#9-*o98*YUZw-|`9W<9SU)f!oh$SW@1hh&I{rY8YZm#&LdOWg# z6$E5aSo@InX2hc+Qv(74ZdGVe?DWBkQ`*iPjkM@ePZAcpmH8#)?|mx~CI1yJ4LC5) zbPZra?(Xiz{8zJjbaizJypWn2+CuLMtykTmFjq0&6^GMAq)FN0-P{O+zr~e57#?0O zY#>r+ELdNld638!-d3M%L72C7q zp{pBX`aYxxV~m_zU+-O!W9@6E&drIW>Jg8&EiIYEXRM$q*x%bh7idhz$bm&a?F9Z- znUy}bbZ*27(ou%XLtZ`_^AZ^0v?6isB?4#j28P65HhmnYCWXYxGWpsbTuu|G!hgF|@XH$vW3@Nk8Q21tLy$~Q8-6<$R<@51xoRn z?4qBtq4I$sZ>)pS;H-ZYLwp&73YH+}6#b|RDU_&_&Lgawd_*^LKDyHtKF^k_ca_5ov~Aw@t2}WBoKH)`FCZo(8f+sP8wOVF6~?2V=?FiC zrRueMmWVyRfLO8CvbPslxNVdG?;99s{rfXTJ38?9*K=!+vOZ_3E|wP*M9{1mu7Px6 zK701jm{!53!b10_WH<~u+n(@b>|A71j2Q=CBl84m+Tm+ysSIVTzkenfarQFt-o3@& zzc(J!k+O;sQ&OOnCAQV`XM0oNmE`b&%ZiIrE^@bT-+ri5N2ml{NX#Jp*|TTig5Rcy zCliB%^Fn_~^oXBtjh=X#-MxDk0%7go^kP4C=82?LDMa+i=;)mQsmI60<6?A%;bHR` zu4uBd&kS_I)|!K&3$@uqsi;^J(a7hisS|afV+BbO2N(ygot3g)DZ3i07smgg21}hy zH@o7k$8om}Wtd`PVjk{J1R$VFfgAZ*Q!EZ*->c$oo)*@ngJ4hynm0WJM$*yIK}$$v z0wxNW3bnj_dv1J=B|DN0(~#EXIr>FhUj9#K>ZO47$*UO#5XcK-E+P^sPdq-%&gKn# z_v+Q-;*J6W3C7g?{IWHJeSWn|M^bJse}(~0E`yGq-r3oiT0QvDzW(^{Lf%c4@6i=B zA9HB@EU59ZO7ADtz~7n#S7hpscE;*L511Gt7Ooq!w!TPD6z1mQvNASy*k%uwX?Sn; zR!>h4M%r*;WQhr9Z|0p0TE4u)3nwZyKr6KgQu8F7YHQjKc% zf8d#Xmyw;=7KwUgx~MN*o06NGo0sQ(!e}aS>C)SyE`VA#oT`jkKR){fJ$u4HqtPN7 z&Zr-_OJ3P4eU1fc5Z|~dO)?eC!^&es=ud?5}moMowo-togxE_Q8y0nE! zcYktjUs_t4-f0&gb_+vsP#pqc?(488{rHJ>s)J7BO@a(FDYjs2?+@) zDHeZGynNxwVs z>ev~3BajWrX=$!<8DJ=Qar24V!AhA)drvV+lff}T=s*7U(m8b@xx?Jfj-~R7oLqX^ zm+s7~?jX4UslZ5}-$5W+s@%W(et&TH@Q~*M4u(oR+?!44CJN1G+%6p0+1xxf=481z3y_68)55CyqBDyMRqvp&AR3tML!hfB0wcvGO-jSaM)zZv7wrq^m()ylxmC?)6+`N=g->vM;8!d@c<@1+V zOj}aK&C*wUh*{T+^3?d+H{ZMw9b=o=qS1zm{-Ng-3p!Y>Ob}4d&CHa5!~VVh(AGA` z^!<2sfcKp{qwkzsA4L}x6-n3aX%-GNW!VE_R-MXJ4c^ff2>k*eC9u9mDVoi>Rbvpw z$f)AKV&&w7I=H#FJ9<1*SW*|XInxS;hEhu?7A|ZcBSV<$O!b}b_7S#thxOT>ZjAW$ zO-DPdFYN2ruYj?wB;(`b`AxPF?VD?BYrrdjr2yr*xt03QbiPRIcnxFW4$4Sqqffms zos4JXP4;Gl5#v-ayo!W|V+L%7fx`F;fIx5RyB41sJk}~0sq%FV3fgBgx}KPuTL)ks zEdL~I8H_1CJv}>zVGkZWz~OMt&IJPnb8~Zq?6^x@8PT3&6-U64s{L1$L-+kmO!_Dq zyh=yK)|JCKNWeIkB_&;W)@fT?D;|A**$8>!Potm1OewtLI=g9r4 zLy-NQ9UX}sF2~2mH^;Uhkbt%EzU6Ikaq*o$!ecn7INitLv55)QKgK>jn{9E#3nO_h zINWDfx`Dw#oQsRcRGq4dN^nP#$m;4UjI=UZz6@&lT}g@k)o6=CPdvV}yBp9Jm~%!( zMxYui<5j)`A8t>D(BfLT*Qe_1{TBOcYHCO%l9KOy%Jb*(hodLWFw@7z=i+eYB~%57Z^5r*oCxsr6qS1?3J33I{+E0?9D&pJ_SE^;Fy^DLJ_}PyJ-v zx0g>XBzT=J^D~z~ayXzntv|2udK_y1a{f<@% z94z`LIXT(P#KdP~x-rc@>@V=2mG};-!-*v!Mge4r-(g11moHxgVNFtZWtqw{T~}S@ zRc%p;Zj1e|Y4bf<>cp^n_wH$EJi>;*@P@e7YeQMy`?};bT}_}YNf5{kHe7$W#R$o-tvyOMQv0;G208$6 zylx!8c3&WRl8F8^v-I`rHDFAxCRSg7IBf1@03#APiz`Wd&eF=Hb@Apri7u zhlMnfP6G(paKq!5=DN~2rEI`wxPSoAJ}6c1G^==OCpMNtL|B+8EF$v2&+iwo=Jxhx zk!EqSa>(8WP!&9&kBO5*O>6(oXT`+C7`S+}grINIC)|Ky3i`fORyOaZ z+;Nc0P*za^V)*PIABV-VQu$I$oEyQg0k=rtVT#(>*`e0CM*tt#4ej3;Ab^V* zaHo^Je4bzacRwaUU?o6bQ}U9nGspkCyvaOagg{PCe1ATz+xo5^0B)opx>!TZM@ Date: Fri, 20 Nov 2020 11:52:11 +0000 Subject: [PATCH 06/33] Fix missed goimports run --- widget/card.go | 2 +- widget/card_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widget/card.go b/widget/card.go index 6c04c9fabd..9c75042bc9 100644 --- a/widget/card.go +++ b/widget/card.go @@ -136,7 +136,7 @@ func (c *cardRenderer) Layout(size fyne.Size) { pos.Y += titlePad } - size.Width -= contentPad*2 + size.Width -= contentPad * 2 pos.X += contentPad if c.card.Content != nil { height := size.Height - contentPad*2 - (pos.Y - theme.Padding()/2) // adjust for content and initial offset diff --git a/widget/card_test.go b/widget/card_test.go index 4eb9b79a74..1b38c5406b 100644 --- a/widget/card_test.go +++ b/widget/card_test.go @@ -133,4 +133,4 @@ func newContentRect() *canvas.Rectangle { rect.SetMinSize(fyne.NewSize(10, 10)) return rect -} \ No newline at end of file +} From b5aa434e0b32b5c13403c2d3786d7052a29387d0 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 20 Nov 2020 20:14:02 +0000 Subject: [PATCH 07/33] Add date for release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90369e9638..684ffbafd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 1.4.1 - Ongoing +## 1.4.1 - 20 November 2020 ### Changed From 67b762f56dc0bf54ffeb93c42b5b5c40d3a9b244 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 22 Nov 2020 13:21:19 +0000 Subject: [PATCH 08/33] Fix missing tags on build --- cmd/fyne/commands/build.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cmd/fyne/commands/build.go b/cmd/fyne/commands/build.go index 5e83cba1bf..1c63559b6f 100644 --- a/cmd/fyne/commands/build.go +++ b/cmd/fyne/commands/build.go @@ -18,20 +18,24 @@ func (b *builder) build() error { goos = targetOS() } - var cmd *exec.Cmd + args := []string{} if goos == "windows" { if b.release { - cmd = exec.Command("go", "build", "-ldflags", "-s -w -H=windowsgui", ".") + args = append(args, "build", "-ldflags", "-s -w -H=windowsgui") } else { - cmd = exec.Command("go", "build", "-ldflags", "-H=windowsgui", ".") + args = append(args, "build", "-ldflags", "-H=windowsgui") } } else { if b.release { - cmd = exec.Command("go", "build", "-ldflags", "-s -w", ".") + args = append(args, "build", "-ldflags", "-s -w") } else { - cmd = exec.Command("go", "build", ".") + args = append(args, "build") } } + if b.release { + args = append(args, "-tags", "release") + } + cmd := exec.Command("go", args...) cmd.Dir = b.srcdir env := os.Environ() env = append(env, "CGO_ENABLED=1") // in case someone is trying to cross-compile... From 9dcefbb396629163614497466fac3baeb3e66d63 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 23 Nov 2020 14:36:44 +0000 Subject: [PATCH 09/33] Updating to latest GLFW fixes --- go.mod | 2 +- go.sum | 4 +- .../go-gl/glfw/v3.3/glfw/c_glfw_freebsd.go | 7 +- .../go-gl/glfw/v3.3/glfw/c_glfw_lin.go | 7 +- ...idle-inhibit-unstable-v1-client-protocol.c | 68 + ...idle-inhibit-unstable-v1-client-protocol.h | 230 ++ ...-constraints-unstable-v1-client-protocol.c | 108 + ...-constraints-unstable-v1-client-protocol.h | 649 ++++++ ...tive-pointer-unstable-v1-client-protocol.c | 79 + ...tive-pointer-unstable-v1-client-protocol.h | 295 +++ .../src/wayland-viewporter-client-protocol.c | 74 + .../src/wayland-viewporter-client-protocol.h | 408 ++++ ...g-decoration-unstable-v1-client-protocol.c | 75 + ...g-decoration-unstable-v1-client-protocol.h | 376 ++++ .../src/wayland-xdg-shell-client-protocol.c | 181 ++ .../src/wayland-xdg-shell-client-protocol.h | 1988 +++++++++++++++++ .../glfw/v3.3/glfw/glfw/src/wl_platform.h | 2 +- vendor/modules.txt | 2 +- 18 files changed, 4548 insertions(+), 7 deletions(-) create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.c create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.h create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.c create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.h create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.c create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.h create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.c create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.h create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.c create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.h create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.c create mode 100644 vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.h diff --git a/go.mod b/go.mod index 05abb37291..de56ba37b2 100644 --- a/go.mod +++ b/go.mod @@ -30,4 +30,4 @@ require ( gopkg.in/yaml.v2 v2.2.8 // indirect ) -replace github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 => github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201114140358-a39598fbf952 +replace github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 => github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d diff --git a/go.sum b/go.sum index a99519ed67..67a15c4d9b 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201114140358-a39598fbf952 h1:1pyMDnz/IX1u87CttHdQN0NiO091lKnLRzCvD9Kj61g= -github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201114140358-a39598fbf952/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d h1:WfVxpuVm+5Gr3ipAoWrxV8lJFYkaBWoEwFRrWThWRSU= +github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/fyne-io/mobile v0.1.1 h1:Snu9tKaVgu81314egPeqMC09z/k4D/bts0n1O2MfPbk= github.com/fyne-io/mobile v0.1.1/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_freebsd.go b/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_freebsd.go index 0b3a339b40..011227399e 100644 --- a/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_freebsd.go +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_freebsd.go @@ -7,7 +7,12 @@ package glfw #include "glfw/src/wl_init.c" #include "glfw/src/wl_monitor.c" #include "glfw/src/wl_window.c" - #include "glfw/src/wl_platform.h" + #include "glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-viewporter-client-protocol.c" + #include "glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-xdg-shell-client-protocol.c" #endif #ifdef _GLFW_X11 #include "glfw/src/x11_init.c" diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_lin.go b/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_lin.go index b1918fc366..67eb054c23 100644 --- a/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_lin.go +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/c_glfw_lin.go @@ -7,7 +7,12 @@ package glfw #include "glfw/src/wl_init.c" #include "glfw/src/wl_monitor.c" #include "glfw/src/wl_window.c" - #include "glfw/src/wl_platform.h" + #include "glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-viewporter-client-protocol.c" + #include "glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.c" + #include "glfw/src/wayland-xdg-shell-client-protocol.c" #endif #ifdef _GLFW_X11 #include "glfw/src/x11_init.c" diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.c b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.c new file mode 100644 index 0000000000..8ac3c12699 --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.c @@ -0,0 +1,68 @@ +/* Generated by wayland-scanner 1.18.0 */ + +/* + * Copyright © 2015 Samsung Electronics Co., Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface zwp_idle_inhibitor_v1_interface; + +static const struct wl_interface *idle_inhibit_unstable_v1_wl_ii_types[] = { + &zwp_idle_inhibitor_v1_interface, + &wl_surface_interface, +}; + +static const struct wl_message zwp_idle_inhibit_manager_v1_requests[] = { + { "destroy", "", idle_inhibit_unstable_v1_wl_ii_types + 0 }, + { "create_inhibitor", "no", idle_inhibit_unstable_v1_wl_ii_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_idle_inhibit_manager_v1_interface = { + "zwp_idle_inhibit_manager_v1", 1, + 2, zwp_idle_inhibit_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message zwp_idle_inhibitor_v1_requests[] = { + { "destroy", "", idle_inhibit_unstable_v1_wl_ii_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_idle_inhibitor_v1_interface = { + "zwp_idle_inhibitor_v1", 1, + 1, zwp_idle_inhibitor_v1_requests, + 0, NULL, +}; + diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.h new file mode 100644 index 0000000000..65ece1f4e7 --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-idle-inhibit-unstable-v1-client-protocol.h @@ -0,0 +1,230 @@ +/* Generated by wayland-scanner 1.18.0 */ + +#ifndef IDLE_INHIBIT_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define IDLE_INHIBIT_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_idle_inhibit_unstable_v1 The idle_inhibit_unstable_v1 protocol + * @section page_ifaces_idle_inhibit_unstable_v1 Interfaces + * - @subpage page_iface_zwp_idle_inhibit_manager_v1 - control behavior when display idles + * - @subpage page_iface_zwp_idle_inhibitor_v1 - context object for inhibiting idle behavior + * @section page_copyright_idle_inhibit_unstable_v1 Copyright + *
+ *
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_surface; +struct zwp_idle_inhibit_manager_v1; +struct zwp_idle_inhibitor_v1; + +/** + * @page page_iface_zwp_idle_inhibit_manager_v1 zwp_idle_inhibit_manager_v1 + * @section page_iface_zwp_idle_inhibit_manager_v1_desc Description + * + * This interface permits inhibiting the idle behavior such as screen + * blanking, locking, and screensaving. The client binds the idle manager + * globally, then creates idle-inhibitor objects for each surface. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zwp_idle_inhibit_manager_v1_api API + * See @ref iface_zwp_idle_inhibit_manager_v1. + */ +/** + * @defgroup iface_zwp_idle_inhibit_manager_v1 The zwp_idle_inhibit_manager_v1 interface + * + * This interface permits inhibiting the idle behavior such as screen + * blanking, locking, and screensaving. The client binds the idle manager + * globally, then creates idle-inhibitor objects for each surface. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zwp_idle_inhibit_manager_v1_interface; +/** + * @page page_iface_zwp_idle_inhibitor_v1 zwp_idle_inhibitor_v1 + * @section page_iface_zwp_idle_inhibitor_v1_desc Description + * + * An idle inhibitor prevents the output that the associated surface is + * visible on from being set to a state where it is not visually usable due + * to lack of user interaction (e.g. blanked, dimmed, locked, set to power + * save, etc.) Any screensaver processes are also blocked from displaying. + * + * If the surface is destroyed, unmapped, becomes occluded, loses + * visibility, or otherwise becomes not visually relevant for the user, the + * idle inhibitor will not be honored by the compositor; if the surface + * subsequently regains visibility the inhibitor takes effect once again. + * Likewise, the inhibitor isn't honored if the system was already idled at + * the time the inhibitor was established, although if the system later + * de-idles and re-idles the inhibitor will take effect. + * @section page_iface_zwp_idle_inhibitor_v1_api API + * See @ref iface_zwp_idle_inhibitor_v1. + */ +/** + * @defgroup iface_zwp_idle_inhibitor_v1 The zwp_idle_inhibitor_v1 interface + * + * An idle inhibitor prevents the output that the associated surface is + * visible on from being set to a state where it is not visually usable due + * to lack of user interaction (e.g. blanked, dimmed, locked, set to power + * save, etc.) Any screensaver processes are also blocked from displaying. + * + * If the surface is destroyed, unmapped, becomes occluded, loses + * visibility, or otherwise becomes not visually relevant for the user, the + * idle inhibitor will not be honored by the compositor; if the surface + * subsequently regains visibility the inhibitor takes effect once again. + * Likewise, the inhibitor isn't honored if the system was already idled at + * the time the inhibitor was established, although if the system later + * de-idles and re-idles the inhibitor will take effect. + */ +extern const struct wl_interface zwp_idle_inhibitor_v1_interface; + +#define ZWP_IDLE_INHIBIT_MANAGER_V1_DESTROY 0 +#define ZWP_IDLE_INHIBIT_MANAGER_V1_CREATE_INHIBITOR 1 + + +/** + * @ingroup iface_zwp_idle_inhibit_manager_v1 + */ +#define ZWP_IDLE_INHIBIT_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_idle_inhibit_manager_v1 + */ +#define ZWP_IDLE_INHIBIT_MANAGER_V1_CREATE_INHIBITOR_SINCE_VERSION 1 + +/** @ingroup iface_zwp_idle_inhibit_manager_v1 */ +static inline void +zwp_idle_inhibit_manager_v1_set_user_data(struct zwp_idle_inhibit_manager_v1 *zwp_idle_inhibit_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_idle_inhibit_manager_v1, user_data); +} + +/** @ingroup iface_zwp_idle_inhibit_manager_v1 */ +static inline void * +zwp_idle_inhibit_manager_v1_get_user_data(struct zwp_idle_inhibit_manager_v1 *zwp_idle_inhibit_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_idle_inhibit_manager_v1); +} + +static inline uint32_t +zwp_idle_inhibit_manager_v1_get_version(struct zwp_idle_inhibit_manager_v1 *zwp_idle_inhibit_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_idle_inhibit_manager_v1); +} + +/** + * @ingroup iface_zwp_idle_inhibit_manager_v1 + * + * Destroy the inhibit manager. + */ +static inline void +zwp_idle_inhibit_manager_v1_destroy(struct zwp_idle_inhibit_manager_v1 *zwp_idle_inhibit_manager_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_idle_inhibit_manager_v1, + ZWP_IDLE_INHIBIT_MANAGER_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_idle_inhibit_manager_v1); +} + +/** + * @ingroup iface_zwp_idle_inhibit_manager_v1 + * + * Create a new inhibitor object associated with the given surface. + */ +static inline struct zwp_idle_inhibitor_v1 * +zwp_idle_inhibit_manager_v1_create_inhibitor(struct zwp_idle_inhibit_manager_v1 *zwp_idle_inhibit_manager_v1, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_idle_inhibit_manager_v1, + ZWP_IDLE_INHIBIT_MANAGER_V1_CREATE_INHIBITOR, &zwp_idle_inhibitor_v1_interface, NULL, surface); + + return (struct zwp_idle_inhibitor_v1 *) id; +} + +#define ZWP_IDLE_INHIBITOR_V1_DESTROY 0 + + +/** + * @ingroup iface_zwp_idle_inhibitor_v1 + */ +#define ZWP_IDLE_INHIBITOR_V1_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_idle_inhibitor_v1 */ +static inline void +zwp_idle_inhibitor_v1_set_user_data(struct zwp_idle_inhibitor_v1 *zwp_idle_inhibitor_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_idle_inhibitor_v1, user_data); +} + +/** @ingroup iface_zwp_idle_inhibitor_v1 */ +static inline void * +zwp_idle_inhibitor_v1_get_user_data(struct zwp_idle_inhibitor_v1 *zwp_idle_inhibitor_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_idle_inhibitor_v1); +} + +static inline uint32_t +zwp_idle_inhibitor_v1_get_version(struct zwp_idle_inhibitor_v1 *zwp_idle_inhibitor_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_idle_inhibitor_v1); +} + +/** + * @ingroup iface_zwp_idle_inhibitor_v1 + * + * Remove the inhibitor effect from the associated wl_surface. + */ +static inline void +zwp_idle_inhibitor_v1_destroy(struct zwp_idle_inhibitor_v1 *zwp_idle_inhibitor_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_idle_inhibitor_v1, + ZWP_IDLE_INHIBITOR_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_idle_inhibitor_v1); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.c b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.c new file mode 100644 index 0000000000..3779b8c6ff --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.c @@ -0,0 +1,108 @@ +/* Generated by wayland-scanner 1.18.0 */ + +/* + * Copyright © 2014 Jonas Ådahl + * Copyright © 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_pointer_interface; +extern const struct wl_interface wl_region_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface zwp_confined_pointer_v1_interface; +extern const struct wl_interface zwp_locked_pointer_v1_interface; + +static const struct wl_interface *pointer_constraints_unstable_v1_wl_pc_types[] = { + NULL, + NULL, + &zwp_locked_pointer_v1_interface, + &wl_surface_interface, + &wl_pointer_interface, + &wl_region_interface, + NULL, + &zwp_confined_pointer_v1_interface, + &wl_surface_interface, + &wl_pointer_interface, + &wl_region_interface, + NULL, + &wl_region_interface, + &wl_region_interface, +}; + +static const struct wl_message zwp_pointer_constraints_v1_requests[] = { + { "destroy", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, + { "lock_pointer", "noo?ou", pointer_constraints_unstable_v1_wl_pc_types + 2 }, + { "confine_pointer", "noo?ou", pointer_constraints_unstable_v1_wl_pc_types + 7 }, +}; + +WL_PRIVATE const struct wl_interface zwp_pointer_constraints_v1_interface = { + "zwp_pointer_constraints_v1", 1, + 3, zwp_pointer_constraints_v1_requests, + 0, NULL, +}; + +static const struct wl_message zwp_locked_pointer_v1_requests[] = { + { "destroy", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, + { "set_cursor_position_hint", "ff", pointer_constraints_unstable_v1_wl_pc_types + 0 }, + { "set_region", "?o", pointer_constraints_unstable_v1_wl_pc_types + 12 }, +}; + +static const struct wl_message zwp_locked_pointer_v1_events[] = { + { "locked", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, + { "unlocked", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_locked_pointer_v1_interface = { + "zwp_locked_pointer_v1", 1, + 3, zwp_locked_pointer_v1_requests, + 2, zwp_locked_pointer_v1_events, +}; + +static const struct wl_message zwp_confined_pointer_v1_requests[] = { + { "destroy", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, + { "set_region", "?o", pointer_constraints_unstable_v1_wl_pc_types + 13 }, +}; + +static const struct wl_message zwp_confined_pointer_v1_events[] = { + { "confined", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, + { "unconfined", "", pointer_constraints_unstable_v1_wl_pc_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_confined_pointer_v1_interface = { + "zwp_confined_pointer_v1", 1, + 2, zwp_confined_pointer_v1_requests, + 2, zwp_confined_pointer_v1_events, +}; + diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.h new file mode 100644 index 0000000000..f66f8d75dd --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-pointer-constraints-unstable-v1-client-protocol.h @@ -0,0 +1,649 @@ +/* Generated by wayland-scanner 1.18.0 */ + +#ifndef POINTER_CONSTRAINTS_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define POINTER_CONSTRAINTS_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_pointer_constraints_unstable_v1 The pointer_constraints_unstable_v1 protocol + * protocol for constraining pointer motions + * + * @section page_desc_pointer_constraints_unstable_v1 Description + * + * This protocol specifies a set of interfaces used for adding constraints to + * the motion of a pointer. Possible constraints include confining pointer + * motions to a given region, or locking it to its current position. + * + * In order to constrain the pointer, a client must first bind the global + * interface "wp_pointer_constraints" which, if a compositor supports pointer + * constraints, is exposed by the registry. Using the bound global object, the + * client uses the request that corresponds to the type of constraint it wants + * to make. See wp_pointer_constraints for more details. + * + * Warning! The protocol described in this file is experimental and backward + * incompatible changes may be made. Backward compatible changes may be added + * together with the corresponding interface version bump. Backward + * incompatible changes are done by bumping the version number in the protocol + * and interface names and resetting the interface version. Once the protocol + * is to be declared stable, the 'z' prefix and the version number in the + * protocol and interface names are removed and the interface version number is + * reset. + * + * @section page_ifaces_pointer_constraints_unstable_v1 Interfaces + * - @subpage page_iface_zwp_pointer_constraints_v1 - constrain the movement of a pointer + * - @subpage page_iface_zwp_locked_pointer_v1 - receive relative pointer motion events + * - @subpage page_iface_zwp_confined_pointer_v1 - confined pointer object + * @section page_copyright_pointer_constraints_unstable_v1 Copyright + *
+ *
+ * Copyright © 2014      Jonas Ådahl
+ * Copyright © 2015      Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_pointer; +struct wl_region; +struct wl_surface; +struct zwp_confined_pointer_v1; +struct zwp_locked_pointer_v1; +struct zwp_pointer_constraints_v1; + +/** + * @page page_iface_zwp_pointer_constraints_v1 zwp_pointer_constraints_v1 + * @section page_iface_zwp_pointer_constraints_v1_desc Description + * + * The global interface exposing pointer constraining functionality. It + * exposes two requests: lock_pointer for locking the pointer to its + * position, and confine_pointer for locking the pointer to a region. + * + * The lock_pointer and confine_pointer requests create the objects + * wp_locked_pointer and wp_confined_pointer respectively, and the client can + * use these objects to interact with the lock. + * + * For any surface, only one lock or confinement may be active across all + * wl_pointer objects of the same seat. If a lock or confinement is requested + * when another lock or confinement is active or requested on the same surface + * and with any of the wl_pointer objects of the same seat, an + * 'already_constrained' error will be raised. + * @section page_iface_zwp_pointer_constraints_v1_api API + * See @ref iface_zwp_pointer_constraints_v1. + */ +/** + * @defgroup iface_zwp_pointer_constraints_v1 The zwp_pointer_constraints_v1 interface + * + * The global interface exposing pointer constraining functionality. It + * exposes two requests: lock_pointer for locking the pointer to its + * position, and confine_pointer for locking the pointer to a region. + * + * The lock_pointer and confine_pointer requests create the objects + * wp_locked_pointer and wp_confined_pointer respectively, and the client can + * use these objects to interact with the lock. + * + * For any surface, only one lock or confinement may be active across all + * wl_pointer objects of the same seat. If a lock or confinement is requested + * when another lock or confinement is active or requested on the same surface + * and with any of the wl_pointer objects of the same seat, an + * 'already_constrained' error will be raised. + */ +extern const struct wl_interface zwp_pointer_constraints_v1_interface; +/** + * @page page_iface_zwp_locked_pointer_v1 zwp_locked_pointer_v1 + * @section page_iface_zwp_locked_pointer_v1_desc Description + * + * The wp_locked_pointer interface represents a locked pointer state. + * + * While the lock of this object is active, the wl_pointer objects of the + * associated seat will not emit any wl_pointer.motion events. + * + * This object will send the event 'locked' when the lock is activated. + * Whenever the lock is activated, it is guaranteed that the locked surface + * will already have received pointer focus and that the pointer will be + * within the region passed to the request creating this object. + * + * To unlock the pointer, send the destroy request. This will also destroy + * the wp_locked_pointer object. + * + * If the compositor decides to unlock the pointer the unlocked event is + * sent. See wp_locked_pointer.unlock for details. + * + * When unlocking, the compositor may warp the cursor position to the set + * cursor position hint. If it does, it will not result in any relative + * motion events emitted via wp_relative_pointer. + * + * If the surface the lock was requested on is destroyed and the lock is not + * yet activated, the wp_locked_pointer object is now defunct and must be + * destroyed. + * @section page_iface_zwp_locked_pointer_v1_api API + * See @ref iface_zwp_locked_pointer_v1. + */ +/** + * @defgroup iface_zwp_locked_pointer_v1 The zwp_locked_pointer_v1 interface + * + * The wp_locked_pointer interface represents a locked pointer state. + * + * While the lock of this object is active, the wl_pointer objects of the + * associated seat will not emit any wl_pointer.motion events. + * + * This object will send the event 'locked' when the lock is activated. + * Whenever the lock is activated, it is guaranteed that the locked surface + * will already have received pointer focus and that the pointer will be + * within the region passed to the request creating this object. + * + * To unlock the pointer, send the destroy request. This will also destroy + * the wp_locked_pointer object. + * + * If the compositor decides to unlock the pointer the unlocked event is + * sent. See wp_locked_pointer.unlock for details. + * + * When unlocking, the compositor may warp the cursor position to the set + * cursor position hint. If it does, it will not result in any relative + * motion events emitted via wp_relative_pointer. + * + * If the surface the lock was requested on is destroyed and the lock is not + * yet activated, the wp_locked_pointer object is now defunct and must be + * destroyed. + */ +extern const struct wl_interface zwp_locked_pointer_v1_interface; +/** + * @page page_iface_zwp_confined_pointer_v1 zwp_confined_pointer_v1 + * @section page_iface_zwp_confined_pointer_v1_desc Description + * + * The wp_confined_pointer interface represents a confined pointer state. + * + * This object will send the event 'confined' when the confinement is + * activated. Whenever the confinement is activated, it is guaranteed that + * the surface the pointer is confined to will already have received pointer + * focus and that the pointer will be within the region passed to the request + * creating this object. It is up to the compositor to decide whether this + * requires some user interaction and if the pointer will warp to within the + * passed region if outside. + * + * To unconfine the pointer, send the destroy request. This will also destroy + * the wp_confined_pointer object. + * + * If the compositor decides to unconfine the pointer the unconfined event is + * sent. The wp_confined_pointer object is at this point defunct and should + * be destroyed. + * @section page_iface_zwp_confined_pointer_v1_api API + * See @ref iface_zwp_confined_pointer_v1. + */ +/** + * @defgroup iface_zwp_confined_pointer_v1 The zwp_confined_pointer_v1 interface + * + * The wp_confined_pointer interface represents a confined pointer state. + * + * This object will send the event 'confined' when the confinement is + * activated. Whenever the confinement is activated, it is guaranteed that + * the surface the pointer is confined to will already have received pointer + * focus and that the pointer will be within the region passed to the request + * creating this object. It is up to the compositor to decide whether this + * requires some user interaction and if the pointer will warp to within the + * passed region if outside. + * + * To unconfine the pointer, send the destroy request. This will also destroy + * the wp_confined_pointer object. + * + * If the compositor decides to unconfine the pointer the unconfined event is + * sent. The wp_confined_pointer object is at this point defunct and should + * be destroyed. + */ +extern const struct wl_interface zwp_confined_pointer_v1_interface; + +#ifndef ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM +#define ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM +/** + * @ingroup iface_zwp_pointer_constraints_v1 + * wp_pointer_constraints error values + * + * These errors can be emitted in response to wp_pointer_constraints + * requests. + */ +enum zwp_pointer_constraints_v1_error { + /** + * pointer constraint already requested on that surface + */ + ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED = 1, +}; +#endif /* ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM */ + +#ifndef ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM +#define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM +/** + * @ingroup iface_zwp_pointer_constraints_v1 + * the pointer constraint may reactivate + * + * A persistent pointer constraint may again reactivate once it has + * been deactivated. See the corresponding deactivation event + * (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for + * details. + */ +enum zwp_pointer_constraints_v1_lifetime { + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT = 1, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT = 2, +}; +#endif /* ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM */ + +#define ZWP_POINTER_CONSTRAINTS_V1_DESTROY 0 +#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER 1 +#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER 2 + + +/** + * @ingroup iface_zwp_pointer_constraints_v1 + */ +#define ZWP_POINTER_CONSTRAINTS_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_pointer_constraints_v1 + */ +#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_pointer_constraints_v1 + */ +#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER_SINCE_VERSION 1 + +/** @ingroup iface_zwp_pointer_constraints_v1 */ +static inline void +zwp_pointer_constraints_v1_set_user_data(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_pointer_constraints_v1, user_data); +} + +/** @ingroup iface_zwp_pointer_constraints_v1 */ +static inline void * +zwp_pointer_constraints_v1_get_user_data(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_pointer_constraints_v1); +} + +static inline uint32_t +zwp_pointer_constraints_v1_get_version(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1); +} + +/** + * @ingroup iface_zwp_pointer_constraints_v1 + * + * Used by the client to notify the server that it will no longer use this + * pointer constraints object. + */ +static inline void +zwp_pointer_constraints_v1_destroy(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_pointer_constraints_v1, + ZWP_POINTER_CONSTRAINTS_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_pointer_constraints_v1); +} + +/** + * @ingroup iface_zwp_pointer_constraints_v1 + * + * The lock_pointer request lets the client request to disable movements of + * the virtual pointer (i.e. the cursor), effectively locking the pointer + * to a position. This request may not take effect immediately; in the + * future, when the compositor deems implementation-specific constraints + * are satisfied, the pointer lock will be activated and the compositor + * sends a locked event. + * + * The protocol provides no guarantee that the constraints are ever + * satisfied, and does not require the compositor to send an error if the + * constraints cannot ever be satisfied. It is thus possible to request a + * lock that will never activate. + * + * There may not be another pointer constraint of any kind requested or + * active on the surface for any of the wl_pointer objects of the seat of + * the passed pointer when requesting a lock. If there is, an error will be + * raised. See general pointer lock documentation for more details. + * + * The intersection of the region passed with this request and the input + * region of the surface is used to determine where the pointer must be + * in order for the lock to activate. It is up to the compositor whether to + * warp the pointer or require some kind of user interaction for the lock + * to activate. If the region is null the surface input region is used. + * + * A surface may receive pointer focus without the lock being activated. + * + * The request creates a new object wp_locked_pointer which is used to + * interact with the lock as well as receive updates about its state. See + * the the description of wp_locked_pointer for further information. + * + * Note that while a pointer is locked, the wl_pointer objects of the + * corresponding seat will not emit any wl_pointer.motion events, but + * relative motion events will still be emitted via wp_relative_pointer + * objects of the same seat. wl_pointer.axis and wl_pointer.button events + * are unaffected. + */ +static inline struct zwp_locked_pointer_v1 * +zwp_pointer_constraints_v1_lock_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_pointer_constraints_v1, + ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER, &zwp_locked_pointer_v1_interface, NULL, surface, pointer, region, lifetime); + + return (struct zwp_locked_pointer_v1 *) id; +} + +/** + * @ingroup iface_zwp_pointer_constraints_v1 + * + * The confine_pointer request lets the client request to confine the + * pointer cursor to a given region. This request may not take effect + * immediately; in the future, when the compositor deems implementation- + * specific constraints are satisfied, the pointer confinement will be + * activated and the compositor sends a confined event. + * + * The intersection of the region passed with this request and the input + * region of the surface is used to determine where the pointer must be + * in order for the confinement to activate. It is up to the compositor + * whether to warp the pointer or require some kind of user interaction for + * the confinement to activate. If the region is null the surface input + * region is used. + * + * The request will create a new object wp_confined_pointer which is used + * to interact with the confinement as well as receive updates about its + * state. See the the description of wp_confined_pointer for further + * information. + */ +static inline struct zwp_confined_pointer_v1 * +zwp_pointer_constraints_v1_confine_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_pointer_constraints_v1, + ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER, &zwp_confined_pointer_v1_interface, NULL, surface, pointer, region, lifetime); + + return (struct zwp_confined_pointer_v1 *) id; +} + +/** + * @ingroup iface_zwp_locked_pointer_v1 + * @struct zwp_locked_pointer_v1_listener + */ +struct zwp_locked_pointer_v1_listener { + /** + * lock activation event + * + * Notification that the pointer lock of the seat's pointer is + * activated. + */ + void (*locked)(void *data, + struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1); + /** + * lock deactivation event + * + * Notification that the pointer lock of the seat's pointer is no + * longer active. If this is a oneshot pointer lock (see + * wp_pointer_constraints.lifetime) this object is now defunct and + * should be destroyed. If this is a persistent pointer lock (see + * wp_pointer_constraints.lifetime) this pointer lock may again + * reactivate in the future. + */ + void (*unlocked)(void *data, + struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1); +}; + +/** + * @ingroup iface_zwp_locked_pointer_v1 + */ +static inline int +zwp_locked_pointer_v1_add_listener(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, + const struct zwp_locked_pointer_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_locked_pointer_v1, + (void (**)(void)) listener, data); +} + +#define ZWP_LOCKED_POINTER_V1_DESTROY 0 +#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT 1 +#define ZWP_LOCKED_POINTER_V1_SET_REGION 2 + +/** + * @ingroup iface_zwp_locked_pointer_v1 + */ +#define ZWP_LOCKED_POINTER_V1_LOCKED_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_locked_pointer_v1 + */ +#define ZWP_LOCKED_POINTER_V1_UNLOCKED_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_locked_pointer_v1 + */ +#define ZWP_LOCKED_POINTER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_locked_pointer_v1 + */ +#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_locked_pointer_v1 + */ +#define ZWP_LOCKED_POINTER_V1_SET_REGION_SINCE_VERSION 1 + +/** @ingroup iface_zwp_locked_pointer_v1 */ +static inline void +zwp_locked_pointer_v1_set_user_data(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_locked_pointer_v1, user_data); +} + +/** @ingroup iface_zwp_locked_pointer_v1 */ +static inline void * +zwp_locked_pointer_v1_get_user_data(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_locked_pointer_v1); +} + +static inline uint32_t +zwp_locked_pointer_v1_get_version(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1); +} + +/** + * @ingroup iface_zwp_locked_pointer_v1 + * + * Destroy the locked pointer object. If applicable, the compositor will + * unlock the pointer. + */ +static inline void +zwp_locked_pointer_v1_destroy(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_locked_pointer_v1, + ZWP_LOCKED_POINTER_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_locked_pointer_v1); +} + +/** + * @ingroup iface_zwp_locked_pointer_v1 + * + * Set the cursor position hint relative to the top left corner of the + * surface. + * + * If the client is drawing its own cursor, it should update the position + * hint to the position of its own cursor. A compositor may use this + * information to warp the pointer upon unlock in order to avoid pointer + * jumps. + * + * The cursor position hint is double buffered. The new hint will only take + * effect when the associated surface gets it pending state applied. See + * wl_surface.commit for details. + */ +static inline void +zwp_locked_pointer_v1_set_cursor_position_hint(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, wl_fixed_t surface_x, wl_fixed_t surface_y) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_locked_pointer_v1, + ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT, surface_x, surface_y); +} + +/** + * @ingroup iface_zwp_locked_pointer_v1 + * + * Set a new region used to lock the pointer. + * + * The new lock region is double-buffered. The new lock region will + * only take effect when the associated surface gets its pending state + * applied. See wl_surface.commit for details. + * + * For details about the lock region, see wp_locked_pointer. + */ +static inline void +zwp_locked_pointer_v1_set_region(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, struct wl_region *region) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_locked_pointer_v1, + ZWP_LOCKED_POINTER_V1_SET_REGION, region); +} + +/** + * @ingroup iface_zwp_confined_pointer_v1 + * @struct zwp_confined_pointer_v1_listener + */ +struct zwp_confined_pointer_v1_listener { + /** + * pointer confined + * + * Notification that the pointer confinement of the seat's + * pointer is activated. + */ + void (*confined)(void *data, + struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1); + /** + * pointer unconfined + * + * Notification that the pointer confinement of the seat's + * pointer is no longer active. If this is a oneshot pointer + * confinement (see wp_pointer_constraints.lifetime) this object is + * now defunct and should be destroyed. If this is a persistent + * pointer confinement (see wp_pointer_constraints.lifetime) this + * pointer confinement may again reactivate in the future. + */ + void (*unconfined)(void *data, + struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1); +}; + +/** + * @ingroup iface_zwp_confined_pointer_v1 + */ +static inline int +zwp_confined_pointer_v1_add_listener(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, + const struct zwp_confined_pointer_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_confined_pointer_v1, + (void (**)(void)) listener, data); +} + +#define ZWP_CONFINED_POINTER_V1_DESTROY 0 +#define ZWP_CONFINED_POINTER_V1_SET_REGION 1 + +/** + * @ingroup iface_zwp_confined_pointer_v1 + */ +#define ZWP_CONFINED_POINTER_V1_CONFINED_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_confined_pointer_v1 + */ +#define ZWP_CONFINED_POINTER_V1_UNCONFINED_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_confined_pointer_v1 + */ +#define ZWP_CONFINED_POINTER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_confined_pointer_v1 + */ +#define ZWP_CONFINED_POINTER_V1_SET_REGION_SINCE_VERSION 1 + +/** @ingroup iface_zwp_confined_pointer_v1 */ +static inline void +zwp_confined_pointer_v1_set_user_data(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_confined_pointer_v1, user_data); +} + +/** @ingroup iface_zwp_confined_pointer_v1 */ +static inline void * +zwp_confined_pointer_v1_get_user_data(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_confined_pointer_v1); +} + +static inline uint32_t +zwp_confined_pointer_v1_get_version(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1); +} + +/** + * @ingroup iface_zwp_confined_pointer_v1 + * + * Destroy the confined pointer object. If applicable, the compositor will + * unconfine the pointer. + */ +static inline void +zwp_confined_pointer_v1_destroy(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_confined_pointer_v1, + ZWP_CONFINED_POINTER_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_confined_pointer_v1); +} + +/** + * @ingroup iface_zwp_confined_pointer_v1 + * + * Set a new region used to confine the pointer. + * + * The new confine region is double-buffered. The new confine region will + * only take effect when the associated surface gets its pending state + * applied. See wl_surface.commit for details. + * + * If the confinement is active when the new confinement region is applied + * and the pointer ends up outside of newly applied region, the pointer may + * warped to a position within the new confinement region. If warped, a + * wl_pointer.motion event will be emitted, but no + * wp_relative_pointer.relative_motion event. + * + * The compositor may also, instead of using the new region, unconfine the + * pointer. + * + * For details about the confine region, see wp_confined_pointer. + */ +static inline void +zwp_confined_pointer_v1_set_region(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, struct wl_region *region) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_confined_pointer_v1, + ZWP_CONFINED_POINTER_V1_SET_REGION, region); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.c b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.c new file mode 100644 index 0000000000..de60756936 --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.c @@ -0,0 +1,79 @@ +/* Generated by wayland-scanner 1.18.0 */ + +/* + * Copyright © 2014 Jonas Ådahl + * Copyright © 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_pointer_interface; +extern const struct wl_interface zwp_relative_pointer_v1_interface; + +static const struct wl_interface *relative_pointer_unstable_v1_wl_rp_types[] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &zwp_relative_pointer_v1_interface, + &wl_pointer_interface, +}; + +static const struct wl_message zwp_relative_pointer_manager_v1_requests[] = { + { "destroy", "", relative_pointer_unstable_v1_wl_rp_types + 0 }, + { "get_relative_pointer", "no", relative_pointer_unstable_v1_wl_rp_types + 6 }, +}; + +WL_PRIVATE const struct wl_interface zwp_relative_pointer_manager_v1_interface = { + "zwp_relative_pointer_manager_v1", 1, + 2, zwp_relative_pointer_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message zwp_relative_pointer_v1_requests[] = { + { "destroy", "", relative_pointer_unstable_v1_wl_rp_types + 0 }, +}; + +static const struct wl_message zwp_relative_pointer_v1_events[] = { + { "relative_motion", "uuffff", relative_pointer_unstable_v1_wl_rp_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_relative_pointer_v1_interface = { + "zwp_relative_pointer_v1", 1, + 1, zwp_relative_pointer_v1_requests, + 1, zwp_relative_pointer_v1_events, +}; + diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.h new file mode 100644 index 0000000000..633d084ded --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-relative-pointer-unstable-v1-client-protocol.h @@ -0,0 +1,295 @@ +/* Generated by wayland-scanner 1.18.0 */ + +#ifndef RELATIVE_POINTER_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define RELATIVE_POINTER_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_relative_pointer_unstable_v1 The relative_pointer_unstable_v1 protocol + * protocol for relative pointer motion events + * + * @section page_desc_relative_pointer_unstable_v1 Description + * + * This protocol specifies a set of interfaces used for making clients able to + * receive relative pointer events not obstructed by barriers (such as the + * monitor edge or other pointer barriers). + * + * To start receiving relative pointer events, a client must first bind the + * global interface "wp_relative_pointer_manager" which, if a compositor + * supports relative pointer motion events, is exposed by the registry. After + * having created the relative pointer manager proxy object, the client uses + * it to create the actual relative pointer object using the + * "get_relative_pointer" request given a wl_pointer. The relative pointer + * motion events will then, when applicable, be transmitted via the proxy of + * the newly created relative pointer object. See the documentation of the + * relative pointer interface for more details. + * + * Warning! The protocol described in this file is experimental and backward + * incompatible changes may be made. Backward compatible changes may be added + * together with the corresponding interface version bump. Backward + * incompatible changes are done by bumping the version number in the protocol + * and interface names and resetting the interface version. Once the protocol + * is to be declared stable, the 'z' prefix and the version number in the + * protocol and interface names are removed and the interface version number is + * reset. + * + * @section page_ifaces_relative_pointer_unstable_v1 Interfaces + * - @subpage page_iface_zwp_relative_pointer_manager_v1 - get relative pointer objects + * - @subpage page_iface_zwp_relative_pointer_v1 - relative pointer object + * @section page_copyright_relative_pointer_unstable_v1 Copyright + *
+ *
+ * Copyright © 2014      Jonas Ådahl
+ * Copyright © 2015      Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_pointer; +struct zwp_relative_pointer_manager_v1; +struct zwp_relative_pointer_v1; + +/** + * @page page_iface_zwp_relative_pointer_manager_v1 zwp_relative_pointer_manager_v1 + * @section page_iface_zwp_relative_pointer_manager_v1_desc Description + * + * A global interface used for getting the relative pointer object for a + * given pointer. + * @section page_iface_zwp_relative_pointer_manager_v1_api API + * See @ref iface_zwp_relative_pointer_manager_v1. + */ +/** + * @defgroup iface_zwp_relative_pointer_manager_v1 The zwp_relative_pointer_manager_v1 interface + * + * A global interface used for getting the relative pointer object for a + * given pointer. + */ +extern const struct wl_interface zwp_relative_pointer_manager_v1_interface; +/** + * @page page_iface_zwp_relative_pointer_v1 zwp_relative_pointer_v1 + * @section page_iface_zwp_relative_pointer_v1_desc Description + * + * A wp_relative_pointer object is an extension to the wl_pointer interface + * used for emitting relative pointer events. It shares the same focus as + * wl_pointer objects of the same seat and will only emit events when it has + * focus. + * @section page_iface_zwp_relative_pointer_v1_api API + * See @ref iface_zwp_relative_pointer_v1. + */ +/** + * @defgroup iface_zwp_relative_pointer_v1 The zwp_relative_pointer_v1 interface + * + * A wp_relative_pointer object is an extension to the wl_pointer interface + * used for emitting relative pointer events. It shares the same focus as + * wl_pointer objects of the same seat and will only emit events when it has + * focus. + */ +extern const struct wl_interface zwp_relative_pointer_v1_interface; + +#define ZWP_RELATIVE_POINTER_MANAGER_V1_DESTROY 0 +#define ZWP_RELATIVE_POINTER_MANAGER_V1_GET_RELATIVE_POINTER 1 + + +/** + * @ingroup iface_zwp_relative_pointer_manager_v1 + */ +#define ZWP_RELATIVE_POINTER_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_relative_pointer_manager_v1 + */ +#define ZWP_RELATIVE_POINTER_MANAGER_V1_GET_RELATIVE_POINTER_SINCE_VERSION 1 + +/** @ingroup iface_zwp_relative_pointer_manager_v1 */ +static inline void +zwp_relative_pointer_manager_v1_set_user_data(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_relative_pointer_manager_v1, user_data); +} + +/** @ingroup iface_zwp_relative_pointer_manager_v1 */ +static inline void * +zwp_relative_pointer_manager_v1_get_user_data(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_relative_pointer_manager_v1); +} + +static inline uint32_t +zwp_relative_pointer_manager_v1_get_version(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_manager_v1); +} + +/** + * @ingroup iface_zwp_relative_pointer_manager_v1 + * + * Used by the client to notify the server that it will no longer use this + * relative pointer manager object. + */ +static inline void +zwp_relative_pointer_manager_v1_destroy(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_relative_pointer_manager_v1, + ZWP_RELATIVE_POINTER_MANAGER_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_relative_pointer_manager_v1); +} + +/** + * @ingroup iface_zwp_relative_pointer_manager_v1 + * + * Create a relative pointer interface given a wl_pointer object. See the + * wp_relative_pointer interface for more details. + */ +static inline struct zwp_relative_pointer_v1 * +zwp_relative_pointer_manager_v1_get_relative_pointer(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1, struct wl_pointer *pointer) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_relative_pointer_manager_v1, + ZWP_RELATIVE_POINTER_MANAGER_V1_GET_RELATIVE_POINTER, &zwp_relative_pointer_v1_interface, NULL, pointer); + + return (struct zwp_relative_pointer_v1 *) id; +} + +/** + * @ingroup iface_zwp_relative_pointer_v1 + * @struct zwp_relative_pointer_v1_listener + */ +struct zwp_relative_pointer_v1_listener { + /** + * relative pointer motion + * + * Relative x/y pointer motion from the pointer of the seat + * associated with this object. + * + * A relative motion is in the same dimension as regular wl_pointer + * motion events, except they do not represent an absolute + * position. For example, moving a pointer from (x, y) to (x', y') + * would have the equivalent relative motion (x' - x, y' - y). If a + * pointer motion caused the absolute pointer position to be + * clipped by for example the edge of the monitor, the relative + * motion is unaffected by the clipping and will represent the + * unclipped motion. + * + * This event also contains non-accelerated motion deltas. The + * non-accelerated delta is, when applicable, the regular pointer + * motion delta as it was before having applied motion acceleration + * and other transformations such as normalization. + * + * Note that the non-accelerated delta does not represent 'raw' + * events as they were read from some device. Pointer motion + * acceleration is device- and configuration-specific and + * non-accelerated deltas and accelerated deltas may have the same + * value on some devices. + * + * Relative motions are not coupled to wl_pointer.motion events, + * and can be sent in combination with such events, but also + * independently. There may also be scenarios where + * wl_pointer.motion is sent, but there is no relative motion. The + * order of an absolute and relative motion event originating from + * the same physical motion is not guaranteed. + * + * If the client needs button events or focus state, it can receive + * them from a wl_pointer object of the same seat that the + * wp_relative_pointer object is associated with. + * @param utime_hi high 32 bits of a 64 bit timestamp with microsecond granularity + * @param utime_lo low 32 bits of a 64 bit timestamp with microsecond granularity + * @param dx the x component of the motion vector + * @param dy the y component of the motion vector + * @param dx_unaccel the x component of the unaccelerated motion vector + * @param dy_unaccel the y component of the unaccelerated motion vector + */ + void (*relative_motion)(void *data, + struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, + uint32_t utime_hi, + uint32_t utime_lo, + wl_fixed_t dx, + wl_fixed_t dy, + wl_fixed_t dx_unaccel, + wl_fixed_t dy_unaccel); +}; + +/** + * @ingroup iface_zwp_relative_pointer_v1 + */ +static inline int +zwp_relative_pointer_v1_add_listener(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, + const struct zwp_relative_pointer_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_relative_pointer_v1, + (void (**)(void)) listener, data); +} + +#define ZWP_RELATIVE_POINTER_V1_DESTROY 0 + +/** + * @ingroup iface_zwp_relative_pointer_v1 + */ +#define ZWP_RELATIVE_POINTER_V1_RELATIVE_MOTION_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_relative_pointer_v1 + */ +#define ZWP_RELATIVE_POINTER_V1_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_relative_pointer_v1 */ +static inline void +zwp_relative_pointer_v1_set_user_data(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_relative_pointer_v1, user_data); +} + +/** @ingroup iface_zwp_relative_pointer_v1 */ +static inline void * +zwp_relative_pointer_v1_get_user_data(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_relative_pointer_v1); +} + +static inline uint32_t +zwp_relative_pointer_v1_get_version(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_v1); +} + +/** + * @ingroup iface_zwp_relative_pointer_v1 + */ +static inline void +zwp_relative_pointer_v1_destroy(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_relative_pointer_v1, + ZWP_RELATIVE_POINTER_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_relative_pointer_v1); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.c b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.c new file mode 100644 index 0000000000..cee474e442 --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.c @@ -0,0 +1,74 @@ +/* Generated by wayland-scanner 1.18.0 */ + +/* + * Copyright © 2013-2016 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wp_viewport_interface; + +static const struct wl_interface *viewporter_types[] = { + NULL, + NULL, + NULL, + NULL, + &wp_viewport_interface, + &wl_surface_interface, +}; + +static const struct wl_message wp_viewporter_requests[] = { + { "destroy", "", viewporter_types + 0 }, + { "get_viewport", "no", viewporter_types + 4 }, +}; + +WL_PRIVATE const struct wl_interface wp_viewporter_interface = { + "wp_viewporter", 1, + 2, wp_viewporter_requests, + 0, NULL, +}; + +static const struct wl_message wp_viewport_requests[] = { + { "destroy", "", viewporter_types + 0 }, + { "set_source", "ffff", viewporter_types + 0 }, + { "set_destination", "ii", viewporter_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface wp_viewport_interface = { + "wp_viewport", 1, + 3, wp_viewport_requests, + 0, NULL, +}; + diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.h new file mode 100644 index 0000000000..90a4407d80 --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-viewporter-client-protocol.h @@ -0,0 +1,408 @@ +/* Generated by wayland-scanner 1.18.0 */ + +#ifndef VIEWPORTER_CLIENT_PROTOCOL_H +#define VIEWPORTER_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_viewporter The viewporter protocol + * @section page_ifaces_viewporter Interfaces + * - @subpage page_iface_wp_viewporter - surface cropping and scaling + * - @subpage page_iface_wp_viewport - crop and scale interface to a wl_surface + * @section page_copyright_viewporter Copyright + *
+ *
+ * Copyright © 2013-2016 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_surface; +struct wp_viewport; +struct wp_viewporter; + +/** + * @page page_iface_wp_viewporter wp_viewporter + * @section page_iface_wp_viewporter_desc Description + * + * The global interface exposing surface cropping and scaling + * capabilities is used to instantiate an interface extension for a + * wl_surface object. This extended interface will then allow + * cropping and scaling the surface contents, effectively + * disconnecting the direct relationship between the buffer and the + * surface size. + * @section page_iface_wp_viewporter_api API + * See @ref iface_wp_viewporter. + */ +/** + * @defgroup iface_wp_viewporter The wp_viewporter interface + * + * The global interface exposing surface cropping and scaling + * capabilities is used to instantiate an interface extension for a + * wl_surface object. This extended interface will then allow + * cropping and scaling the surface contents, effectively + * disconnecting the direct relationship between the buffer and the + * surface size. + */ +extern const struct wl_interface wp_viewporter_interface; +/** + * @page page_iface_wp_viewport wp_viewport + * @section page_iface_wp_viewport_desc Description + * + * An additional interface to a wl_surface object, which allows the + * client to specify the cropping and scaling of the surface + * contents. + * + * This interface works with two concepts: the source rectangle (src_x, + * src_y, src_width, src_height), and the destination size (dst_width, + * dst_height). The contents of the source rectangle are scaled to the + * destination size, and content outside the source rectangle is ignored. + * This state is double-buffered, and is applied on the next + * wl_surface.commit. + * + * The two parts of crop and scale state are independent: the source + * rectangle, and the destination size. Initially both are unset, that + * is, no scaling is applied. The whole of the current wl_buffer is + * used as the source, and the surface size is as defined in + * wl_surface.attach. + * + * If the destination size is set, it causes the surface size to become + * dst_width, dst_height. The source (rectangle) is scaled to exactly + * this size. This overrides whatever the attached wl_buffer size is, + * unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface + * has no content and therefore no size. Otherwise, the size is always + * at least 1x1 in surface local coordinates. + * + * If the source rectangle is set, it defines what area of the wl_buffer is + * taken as the source. If the source rectangle is set and the destination + * size is not set, then src_width and src_height must be integers, and the + * surface size becomes the source rectangle size. This results in cropping + * without scaling. If src_width or src_height are not integers and + * destination size is not set, the bad_size protocol error is raised when + * the surface state is applied. + * + * The coordinate transformations from buffer pixel coordinates up to + * the surface-local coordinates happen in the following order: + * 1. buffer_transform (wl_surface.set_buffer_transform) + * 2. buffer_scale (wl_surface.set_buffer_scale) + * 3. crop and scale (wp_viewport.set*) + * This means, that the source rectangle coordinates of crop and scale + * are given in the coordinates after the buffer transform and scale, + * i.e. in the coordinates that would be the surface-local coordinates + * if the crop and scale was not applied. + * + * If src_x or src_y are negative, the bad_value protocol error is raised. + * Otherwise, if the source rectangle is partially or completely outside of + * the non-NULL wl_buffer, then the out_of_buffer protocol error is raised + * when the surface state is applied. A NULL wl_buffer does not raise the + * out_of_buffer error. + * + * The x, y arguments of wl_surface.attach are applied as normal to + * the surface. They indicate how many pixels to remove from the + * surface size from the left and the top. In other words, they are + * still in the surface-local coordinate system, just like dst_width + * and dst_height are. + * + * If the wl_surface associated with the wp_viewport is destroyed, + * all wp_viewport requests except 'destroy' raise the protocol error + * no_surface. + * + * If the wp_viewport object is destroyed, the crop and scale + * state is removed from the wl_surface. The change will be applied + * on the next wl_surface.commit. + * @section page_iface_wp_viewport_api API + * See @ref iface_wp_viewport. + */ +/** + * @defgroup iface_wp_viewport The wp_viewport interface + * + * An additional interface to a wl_surface object, which allows the + * client to specify the cropping and scaling of the surface + * contents. + * + * This interface works with two concepts: the source rectangle (src_x, + * src_y, src_width, src_height), and the destination size (dst_width, + * dst_height). The contents of the source rectangle are scaled to the + * destination size, and content outside the source rectangle is ignored. + * This state is double-buffered, and is applied on the next + * wl_surface.commit. + * + * The two parts of crop and scale state are independent: the source + * rectangle, and the destination size. Initially both are unset, that + * is, no scaling is applied. The whole of the current wl_buffer is + * used as the source, and the surface size is as defined in + * wl_surface.attach. + * + * If the destination size is set, it causes the surface size to become + * dst_width, dst_height. The source (rectangle) is scaled to exactly + * this size. This overrides whatever the attached wl_buffer size is, + * unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface + * has no content and therefore no size. Otherwise, the size is always + * at least 1x1 in surface local coordinates. + * + * If the source rectangle is set, it defines what area of the wl_buffer is + * taken as the source. If the source rectangle is set and the destination + * size is not set, then src_width and src_height must be integers, and the + * surface size becomes the source rectangle size. This results in cropping + * without scaling. If src_width or src_height are not integers and + * destination size is not set, the bad_size protocol error is raised when + * the surface state is applied. + * + * The coordinate transformations from buffer pixel coordinates up to + * the surface-local coordinates happen in the following order: + * 1. buffer_transform (wl_surface.set_buffer_transform) + * 2. buffer_scale (wl_surface.set_buffer_scale) + * 3. crop and scale (wp_viewport.set*) + * This means, that the source rectangle coordinates of crop and scale + * are given in the coordinates after the buffer transform and scale, + * i.e. in the coordinates that would be the surface-local coordinates + * if the crop and scale was not applied. + * + * If src_x or src_y are negative, the bad_value protocol error is raised. + * Otherwise, if the source rectangle is partially or completely outside of + * the non-NULL wl_buffer, then the out_of_buffer protocol error is raised + * when the surface state is applied. A NULL wl_buffer does not raise the + * out_of_buffer error. + * + * The x, y arguments of wl_surface.attach are applied as normal to + * the surface. They indicate how many pixels to remove from the + * surface size from the left and the top. In other words, they are + * still in the surface-local coordinate system, just like dst_width + * and dst_height are. + * + * If the wl_surface associated with the wp_viewport is destroyed, + * all wp_viewport requests except 'destroy' raise the protocol error + * no_surface. + * + * If the wp_viewport object is destroyed, the crop and scale + * state is removed from the wl_surface. The change will be applied + * on the next wl_surface.commit. + */ +extern const struct wl_interface wp_viewport_interface; + +#ifndef WP_VIEWPORTER_ERROR_ENUM +#define WP_VIEWPORTER_ERROR_ENUM +enum wp_viewporter_error { + /** + * the surface already has a viewport object associated + */ + WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS = 0, +}; +#endif /* WP_VIEWPORTER_ERROR_ENUM */ + +#define WP_VIEWPORTER_DESTROY 0 +#define WP_VIEWPORTER_GET_VIEWPORT 1 + + +/** + * @ingroup iface_wp_viewporter + */ +#define WP_VIEWPORTER_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_viewporter + */ +#define WP_VIEWPORTER_GET_VIEWPORT_SINCE_VERSION 1 + +/** @ingroup iface_wp_viewporter */ +static inline void +wp_viewporter_set_user_data(struct wp_viewporter *wp_viewporter, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_viewporter, user_data); +} + +/** @ingroup iface_wp_viewporter */ +static inline void * +wp_viewporter_get_user_data(struct wp_viewporter *wp_viewporter) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_viewporter); +} + +static inline uint32_t +wp_viewporter_get_version(struct wp_viewporter *wp_viewporter) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_viewporter); +} + +/** + * @ingroup iface_wp_viewporter + * + * Informs the server that the client will not be using this + * protocol object anymore. This does not affect any other objects, + * wp_viewport objects included. + */ +static inline void +wp_viewporter_destroy(struct wp_viewporter *wp_viewporter) +{ + wl_proxy_marshal((struct wl_proxy *) wp_viewporter, + WP_VIEWPORTER_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) wp_viewporter); +} + +/** + * @ingroup iface_wp_viewporter + * + * Instantiate an interface extension for the given wl_surface to + * crop and scale its content. If the given wl_surface already has + * a wp_viewport object associated, the viewport_exists + * protocol error is raised. + */ +static inline struct wp_viewport * +wp_viewporter_get_viewport(struct wp_viewporter *wp_viewporter, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) wp_viewporter, + WP_VIEWPORTER_GET_VIEWPORT, &wp_viewport_interface, NULL, surface); + + return (struct wp_viewport *) id; +} + +#ifndef WP_VIEWPORT_ERROR_ENUM +#define WP_VIEWPORT_ERROR_ENUM +enum wp_viewport_error { + /** + * negative or zero values in width or height + */ + WP_VIEWPORT_ERROR_BAD_VALUE = 0, + /** + * destination size is not integer + */ + WP_VIEWPORT_ERROR_BAD_SIZE = 1, + /** + * source rectangle extends outside of the content area + */ + WP_VIEWPORT_ERROR_OUT_OF_BUFFER = 2, + /** + * the wl_surface was destroyed + */ + WP_VIEWPORT_ERROR_NO_SURFACE = 3, +}; +#endif /* WP_VIEWPORT_ERROR_ENUM */ + +#define WP_VIEWPORT_DESTROY 0 +#define WP_VIEWPORT_SET_SOURCE 1 +#define WP_VIEWPORT_SET_DESTINATION 2 + + +/** + * @ingroup iface_wp_viewport + */ +#define WP_VIEWPORT_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_viewport + */ +#define WP_VIEWPORT_SET_SOURCE_SINCE_VERSION 1 +/** + * @ingroup iface_wp_viewport + */ +#define WP_VIEWPORT_SET_DESTINATION_SINCE_VERSION 1 + +/** @ingroup iface_wp_viewport */ +static inline void +wp_viewport_set_user_data(struct wp_viewport *wp_viewport, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_viewport, user_data); +} + +/** @ingroup iface_wp_viewport */ +static inline void * +wp_viewport_get_user_data(struct wp_viewport *wp_viewport) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_viewport); +} + +static inline uint32_t +wp_viewport_get_version(struct wp_viewport *wp_viewport) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_viewport); +} + +/** + * @ingroup iface_wp_viewport + * + * The associated wl_surface's crop and scale state is removed. + * The change is applied on the next wl_surface.commit. + */ +static inline void +wp_viewport_destroy(struct wp_viewport *wp_viewport) +{ + wl_proxy_marshal((struct wl_proxy *) wp_viewport, + WP_VIEWPORT_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) wp_viewport); +} + +/** + * @ingroup iface_wp_viewport + * + * Set the source rectangle of the associated wl_surface. See + * wp_viewport for the description, and relation to the wl_buffer + * size. + * + * If all of x, y, width and height are -1.0, the source rectangle is + * unset instead. Any other set of values where width or height are zero + * or negative, or x or y are negative, raise the bad_value protocol + * error. + * + * The crop and scale state is double-buffered state, and will be + * applied on the next wl_surface.commit. + */ +static inline void +wp_viewport_set_source(struct wp_viewport *wp_viewport, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) +{ + wl_proxy_marshal((struct wl_proxy *) wp_viewport, + WP_VIEWPORT_SET_SOURCE, x, y, width, height); +} + +/** + * @ingroup iface_wp_viewport + * + * Set the destination size of the associated wl_surface. See + * wp_viewport for the description, and relation to the wl_buffer + * size. + * + * If width is -1 and height is -1, the destination size is unset + * instead. Any other pair of values for width and height that + * contains zero or negative values raises the bad_value protocol + * error. + * + * The crop and scale state is double-buffered state, and will be + * applied on the next wl_surface.commit. + */ +static inline void +wp_viewport_set_destination(struct wp_viewport *wp_viewport, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) wp_viewport, + WP_VIEWPORT_SET_DESTINATION, width, height); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.c b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.c new file mode 100644 index 0000000000..1aadb23c3a --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.c @@ -0,0 +1,75 @@ +/* Generated by wayland-scanner 1.18.0 */ + +/* + * Copyright © 2018 Simon Ser + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface xdg_toplevel_interface; +extern const struct wl_interface zxdg_toplevel_decoration_v1_interface; + +static const struct wl_interface *xdg_decoration_unstable_v1_types[] = { + NULL, + &zxdg_toplevel_decoration_v1_interface, + &xdg_toplevel_interface, +}; + +static const struct wl_message zxdg_decoration_manager_v1_requests[] = { + { "destroy", "", xdg_decoration_unstable_v1_types + 0 }, + { "get_toplevel_decoration", "no", xdg_decoration_unstable_v1_types + 1 }, +}; + +WL_PRIVATE const struct wl_interface zxdg_decoration_manager_v1_interface = { + "zxdg_decoration_manager_v1", 1, + 2, zxdg_decoration_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message zxdg_toplevel_decoration_v1_requests[] = { + { "destroy", "", xdg_decoration_unstable_v1_types + 0 }, + { "set_mode", "u", xdg_decoration_unstable_v1_types + 0 }, + { "unset_mode", "", xdg_decoration_unstable_v1_types + 0 }, +}; + +static const struct wl_message zxdg_toplevel_decoration_v1_events[] = { + { "configure", "u", xdg_decoration_unstable_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zxdg_toplevel_decoration_v1_interface = { + "zxdg_toplevel_decoration_v1", 1, + 3, zxdg_toplevel_decoration_v1_requests, + 1, zxdg_toplevel_decoration_v1_events, +}; + diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.h new file mode 100644 index 0000000000..88378542bc --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-decoration-unstable-v1-client-protocol.h @@ -0,0 +1,376 @@ +/* Generated by wayland-scanner 1.18.0 */ + +#ifndef XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_xdg_decoration_unstable_v1 The xdg_decoration_unstable_v1 protocol + * @section page_ifaces_xdg_decoration_unstable_v1 Interfaces + * - @subpage page_iface_zxdg_decoration_manager_v1 - window decoration manager + * - @subpage page_iface_zxdg_toplevel_decoration_v1 - decoration object for a toplevel surface + * @section page_copyright_xdg_decoration_unstable_v1 Copyright + *
+ *
+ * Copyright © 2018 Simon Ser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct xdg_toplevel; +struct zxdg_decoration_manager_v1; +struct zxdg_toplevel_decoration_v1; + +/** + * @page page_iface_zxdg_decoration_manager_v1 zxdg_decoration_manager_v1 + * @section page_iface_zxdg_decoration_manager_v1_desc Description + * + * This interface allows a compositor to announce support for server-side + * decorations. + * + * A window decoration is a set of window controls as deemed appropriate by + * the party managing them, such as user interface components used to move, + * resize and change a window's state. + * + * A client can use this protocol to request being decorated by a supporting + * compositor. + * + * If compositor and client do not negotiate the use of a server-side + * decoration using this protocol, clients continue to self-decorate as they + * see fit. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zxdg_decoration_manager_v1_api API + * See @ref iface_zxdg_decoration_manager_v1. + */ +/** + * @defgroup iface_zxdg_decoration_manager_v1 The zxdg_decoration_manager_v1 interface + * + * This interface allows a compositor to announce support for server-side + * decorations. + * + * A window decoration is a set of window controls as deemed appropriate by + * the party managing them, such as user interface components used to move, + * resize and change a window's state. + * + * A client can use this protocol to request being decorated by a supporting + * compositor. + * + * If compositor and client do not negotiate the use of a server-side + * decoration using this protocol, clients continue to self-decorate as they + * see fit. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zxdg_decoration_manager_v1_interface; +/** + * @page page_iface_zxdg_toplevel_decoration_v1 zxdg_toplevel_decoration_v1 + * @section page_iface_zxdg_toplevel_decoration_v1_desc Description + * + * The decoration object allows the compositor to toggle server-side window + * decorations for a toplevel surface. The client can request to switch to + * another mode. + * + * The xdg_toplevel_decoration object must be destroyed before its + * xdg_toplevel. + * @section page_iface_zxdg_toplevel_decoration_v1_api API + * See @ref iface_zxdg_toplevel_decoration_v1. + */ +/** + * @defgroup iface_zxdg_toplevel_decoration_v1 The zxdg_toplevel_decoration_v1 interface + * + * The decoration object allows the compositor to toggle server-side window + * decorations for a toplevel surface. The client can request to switch to + * another mode. + * + * The xdg_toplevel_decoration object must be destroyed before its + * xdg_toplevel. + */ +extern const struct wl_interface zxdg_toplevel_decoration_v1_interface; + +#define ZXDG_DECORATION_MANAGER_V1_DESTROY 0 +#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION 1 + + +/** + * @ingroup iface_zxdg_decoration_manager_v1 + */ +#define ZXDG_DECORATION_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zxdg_decoration_manager_v1 + */ +#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION_SINCE_VERSION 1 + +/** @ingroup iface_zxdg_decoration_manager_v1 */ +static inline void +zxdg_decoration_manager_v1_set_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zxdg_decoration_manager_v1, user_data); +} + +/** @ingroup iface_zxdg_decoration_manager_v1 */ +static inline void * +zxdg_decoration_manager_v1_get_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zxdg_decoration_manager_v1); +} + +static inline uint32_t +zxdg_decoration_manager_v1_get_version(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1); +} + +/** + * @ingroup iface_zxdg_decoration_manager_v1 + * + * Destroy the decoration manager. This doesn't destroy objects created + * with the manager. + */ +static inline void +zxdg_decoration_manager_v1_destroy(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zxdg_decoration_manager_v1, + ZXDG_DECORATION_MANAGER_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zxdg_decoration_manager_v1); +} + +/** + * @ingroup iface_zxdg_decoration_manager_v1 + * + * Create a new decoration object associated with the given toplevel. + * + * Creating an xdg_toplevel_decoration from an xdg_toplevel which has a + * buffer attached or committed is a client error, and any attempts by a + * client to attach or manipulate a buffer prior to the first + * xdg_toplevel_decoration.configure event must also be treated as + * errors. + */ +static inline struct zxdg_toplevel_decoration_v1 * +zxdg_decoration_manager_v1_get_toplevel_decoration(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, struct xdg_toplevel *toplevel) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zxdg_decoration_manager_v1, + ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION, &zxdg_toplevel_decoration_v1_interface, NULL, toplevel); + + return (struct zxdg_toplevel_decoration_v1 *) id; +} + +#ifndef ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM +#define ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM +enum zxdg_toplevel_decoration_v1_error { + /** + * xdg_toplevel has a buffer attached before configure + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER = 0, + /** + * xdg_toplevel already has a decoration object + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ALREADY_CONSTRUCTED = 1, + /** + * xdg_toplevel destroyed before the decoration object + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ORPHANED = 2, +}; +#endif /* ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM */ + +#ifndef ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM +#define ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * window decoration modes + * + * These values describe window decoration modes. + */ +enum zxdg_toplevel_decoration_v1_mode { + /** + * no server-side window decoration + */ + ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE = 1, + /** + * server-side window decoration + */ + ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE = 2, +}; +#endif /* ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM */ + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * @struct zxdg_toplevel_decoration_v1_listener + */ +struct zxdg_toplevel_decoration_v1_listener { + /** + * suggest a surface change + * + * The configure event asks the client to change its decoration + * mode. The configured state should not be applied immediately. + * Clients must send an ack_configure in response to this event. + * See xdg_surface.configure and xdg_surface.ack_configure for + * details. + * + * A configure event can be sent at any time. The specified mode + * must be obeyed by the client. + * @param mode the decoration mode + */ + void (*configure)(void *data, + struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, + uint32_t mode); +}; + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +static inline int +zxdg_toplevel_decoration_v1_add_listener(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, + const struct zxdg_toplevel_decoration_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zxdg_toplevel_decoration_v1, + (void (**)(void)) listener, data); +} + +#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY 0 +#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE 1 +#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE 2 + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_CONFIGURE_SINCE_VERSION 1 + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE_SINCE_VERSION 1 +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE_SINCE_VERSION 1 + +/** @ingroup iface_zxdg_toplevel_decoration_v1 */ +static inline void +zxdg_toplevel_decoration_v1_set_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1, user_data); +} + +/** @ingroup iface_zxdg_toplevel_decoration_v1 */ +static inline void * +zxdg_toplevel_decoration_v1_get_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1); +} + +static inline uint32_t +zxdg_toplevel_decoration_v1_get_version(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1); +} + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * + * Switch back to a mode without any server-side decorations at the next + * commit. + */ +static inline void +zxdg_toplevel_decoration_v1_destroy(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_decoration_v1, + ZXDG_TOPLEVEL_DECORATION_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zxdg_toplevel_decoration_v1); +} + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * + * Set the toplevel surface decoration mode. This informs the compositor + * that the client prefers the provided decoration mode. + * + * After requesting a decoration mode, the compositor will respond by + * emitting an xdg_surface.configure event. The client should then update + * its content, drawing it without decorations if the received mode is + * server-side decorations. The client must also acknowledge the configure + * when committing the new content (see xdg_surface.ack_configure). + * + * The compositor can decide not to use the client's mode and enforce a + * different mode instead. + * + * Clients whose decoration mode depend on the xdg_toplevel state may send + * a set_mode request in response to an xdg_surface.configure event and wait + * for the next xdg_surface.configure event to prevent unwanted state. + * Such clients are responsible for preventing configure loops and must + * make sure not to send multiple successive set_mode requests with the + * same decoration mode. + */ +static inline void +zxdg_toplevel_decoration_v1_set_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode) +{ + wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_decoration_v1, + ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE, mode); +} + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * + * Unset the toplevel surface decoration mode. This informs the compositor + * that the client doesn't prefer a particular decoration mode. + * + * This request has the same semantics as set_mode. + */ +static inline void +zxdg_toplevel_decoration_v1_unset_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_decoration_v1, + ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.c b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.c new file mode 100644 index 0000000000..6bcc9fd165 --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.c @@ -0,0 +1,181 @@ +/* Generated by wayland-scanner 1.18.0 */ + +/* + * Copyright © 2008-2013 Kristian Høgsberg + * Copyright © 2013 Rafael Antognolli + * Copyright © 2013 Jasper St. Pierre + * Copyright © 2010-2013 Intel Corporation + * Copyright © 2015-2017 Samsung Electronics Co., Ltd + * Copyright © 2015-2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_seat_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface xdg_popup_interface; +extern const struct wl_interface xdg_positioner_interface; +extern const struct wl_interface xdg_surface_interface; +extern const struct wl_interface xdg_toplevel_interface; + +static const struct wl_interface *xdg_shell_types[] = { + NULL, + NULL, + NULL, + NULL, + &xdg_positioner_interface, + &xdg_surface_interface, + &wl_surface_interface, + &xdg_toplevel_interface, + &xdg_popup_interface, + &xdg_surface_interface, + &xdg_positioner_interface, + &xdg_toplevel_interface, + &wl_seat_interface, + NULL, + NULL, + NULL, + &wl_seat_interface, + NULL, + &wl_seat_interface, + NULL, + NULL, + &wl_output_interface, + &wl_seat_interface, + NULL, + &xdg_positioner_interface, + NULL, +}; + +static const struct wl_message xdg_wm_base_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "create_positioner", "n", xdg_shell_types + 4 }, + { "get_xdg_surface", "no", xdg_shell_types + 5 }, + { "pong", "u", xdg_shell_types + 0 }, +}; + +static const struct wl_message xdg_wm_base_events[] = { + { "ping", "u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_wm_base_interface = { + "xdg_wm_base", 3, + 4, xdg_wm_base_requests, + 1, xdg_wm_base_events, +}; + +static const struct wl_message xdg_positioner_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "set_size", "ii", xdg_shell_types + 0 }, + { "set_anchor_rect", "iiii", xdg_shell_types + 0 }, + { "set_anchor", "u", xdg_shell_types + 0 }, + { "set_gravity", "u", xdg_shell_types + 0 }, + { "set_constraint_adjustment", "u", xdg_shell_types + 0 }, + { "set_offset", "ii", xdg_shell_types + 0 }, + { "set_reactive", "3", xdg_shell_types + 0 }, + { "set_parent_size", "3ii", xdg_shell_types + 0 }, + { "set_parent_configure", "3u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_positioner_interface = { + "xdg_positioner", 3, + 10, xdg_positioner_requests, + 0, NULL, +}; + +static const struct wl_message xdg_surface_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "get_toplevel", "n", xdg_shell_types + 7 }, + { "get_popup", "n?oo", xdg_shell_types + 8 }, + { "set_window_geometry", "iiii", xdg_shell_types + 0 }, + { "ack_configure", "u", xdg_shell_types + 0 }, +}; + +static const struct wl_message xdg_surface_events[] = { + { "configure", "u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_surface_interface = { + "xdg_surface", 3, + 5, xdg_surface_requests, + 1, xdg_surface_events, +}; + +static const struct wl_message xdg_toplevel_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "set_parent", "?o", xdg_shell_types + 11 }, + { "set_title", "s", xdg_shell_types + 0 }, + { "set_app_id", "s", xdg_shell_types + 0 }, + { "show_window_menu", "ouii", xdg_shell_types + 12 }, + { "move", "ou", xdg_shell_types + 16 }, + { "resize", "ouu", xdg_shell_types + 18 }, + { "set_max_size", "ii", xdg_shell_types + 0 }, + { "set_min_size", "ii", xdg_shell_types + 0 }, + { "set_maximized", "", xdg_shell_types + 0 }, + { "unset_maximized", "", xdg_shell_types + 0 }, + { "set_fullscreen", "?o", xdg_shell_types + 21 }, + { "unset_fullscreen", "", xdg_shell_types + 0 }, + { "set_minimized", "", xdg_shell_types + 0 }, +}; + +static const struct wl_message xdg_toplevel_events[] = { + { "configure", "iia", xdg_shell_types + 0 }, + { "close", "", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_toplevel_interface = { + "xdg_toplevel", 3, + 14, xdg_toplevel_requests, + 2, xdg_toplevel_events, +}; + +static const struct wl_message xdg_popup_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "grab", "ou", xdg_shell_types + 22 }, + { "reposition", "3ou", xdg_shell_types + 24 }, +}; + +static const struct wl_message xdg_popup_events[] = { + { "configure", "iiii", xdg_shell_types + 0 }, + { "popup_done", "", xdg_shell_types + 0 }, + { "repositioned", "3u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_popup_interface = { + "xdg_popup", 3, + 3, xdg_popup_requests, + 3, xdg_popup_events, +}; + diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.h new file mode 100644 index 0000000000..14aa30527c --- /dev/null +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wayland-xdg-shell-client-protocol.h @@ -0,0 +1,1988 @@ +/* Generated by wayland-scanner 1.18.0 */ + +#ifndef XDG_SHELL_CLIENT_PROTOCOL_H +#define XDG_SHELL_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_xdg_shell The xdg_shell protocol + * @section page_ifaces_xdg_shell Interfaces + * - @subpage page_iface_xdg_wm_base - create desktop-style surfaces + * - @subpage page_iface_xdg_positioner - child surface positioner + * - @subpage page_iface_xdg_surface - desktop user interface surface base interface + * - @subpage page_iface_xdg_toplevel - toplevel surface + * - @subpage page_iface_xdg_popup - short-lived, popup surfaces for menus + * @section page_copyright_xdg_shell Copyright + *
+ *
+ * Copyright © 2008-2013 Kristian Høgsberg
+ * Copyright © 2013      Rafael Antognolli
+ * Copyright © 2013      Jasper St. Pierre
+ * Copyright © 2010-2013 Intel Corporation
+ * Copyright © 2015-2017 Samsung Electronics Co., Ltd
+ * Copyright © 2015-2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_output; +struct wl_seat; +struct wl_surface; +struct xdg_popup; +struct xdg_positioner; +struct xdg_surface; +struct xdg_toplevel; +struct xdg_wm_base; + +/** + * @page page_iface_xdg_wm_base xdg_wm_base + * @section page_iface_xdg_wm_base_desc Description + * + * The xdg_wm_base interface is exposed as a global object enabling clients + * to turn their wl_surfaces into windows in a desktop environment. It + * defines the basic functionality needed for clients and the compositor to + * create windows that can be dragged, resized, maximized, etc, as well as + * creating transient windows such as popup menus. + * @section page_iface_xdg_wm_base_api API + * See @ref iface_xdg_wm_base. + */ +/** + * @defgroup iface_xdg_wm_base The xdg_wm_base interface + * + * The xdg_wm_base interface is exposed as a global object enabling clients + * to turn their wl_surfaces into windows in a desktop environment. It + * defines the basic functionality needed for clients and the compositor to + * create windows that can be dragged, resized, maximized, etc, as well as + * creating transient windows such as popup menus. + */ +extern const struct wl_interface xdg_wm_base_interface; +/** + * @page page_iface_xdg_positioner xdg_positioner + * @section page_iface_xdg_positioner_desc Description + * + * The xdg_positioner provides a collection of rules for the placement of a + * child surface relative to a parent surface. Rules can be defined to ensure + * the child surface remains within the visible area's borders, and to + * specify how the child surface changes its position, such as sliding along + * an axis, or flipping around a rectangle. These positioner-created rules are + * constrained by the requirement that a child surface must intersect with or + * be at least partially adjacent to its parent surface. + * + * See the various requests for details about possible rules. + * + * At the time of the request, the compositor makes a copy of the rules + * specified by the xdg_positioner. Thus, after the request is complete the + * xdg_positioner object can be destroyed or reused; further changes to the + * object will have no effect on previous usages. + * + * For an xdg_positioner object to be considered complete, it must have a + * non-zero size set by set_size, and a non-zero anchor rectangle set by + * set_anchor_rect. Passing an incomplete xdg_positioner object when + * positioning a surface raises an error. + * @section page_iface_xdg_positioner_api API + * See @ref iface_xdg_positioner. + */ +/** + * @defgroup iface_xdg_positioner The xdg_positioner interface + * + * The xdg_positioner provides a collection of rules for the placement of a + * child surface relative to a parent surface. Rules can be defined to ensure + * the child surface remains within the visible area's borders, and to + * specify how the child surface changes its position, such as sliding along + * an axis, or flipping around a rectangle. These positioner-created rules are + * constrained by the requirement that a child surface must intersect with or + * be at least partially adjacent to its parent surface. + * + * See the various requests for details about possible rules. + * + * At the time of the request, the compositor makes a copy of the rules + * specified by the xdg_positioner. Thus, after the request is complete the + * xdg_positioner object can be destroyed or reused; further changes to the + * object will have no effect on previous usages. + * + * For an xdg_positioner object to be considered complete, it must have a + * non-zero size set by set_size, and a non-zero anchor rectangle set by + * set_anchor_rect. Passing an incomplete xdg_positioner object when + * positioning a surface raises an error. + */ +extern const struct wl_interface xdg_positioner_interface; +/** + * @page page_iface_xdg_surface xdg_surface + * @section page_iface_xdg_surface_desc Description + * + * An interface that may be implemented by a wl_surface, for + * implementations that provide a desktop-style user interface. + * + * It provides a base set of functionality required to construct user + * interface elements requiring management by the compositor, such as + * toplevel windows, menus, etc. The types of functionality are split into + * xdg_surface roles. + * + * Creating an xdg_surface does not set the role for a wl_surface. In order + * to map an xdg_surface, the client must create a role-specific object + * using, e.g., get_toplevel, get_popup. The wl_surface for any given + * xdg_surface can have at most one role, and may not be assigned any role + * not based on xdg_surface. + * + * A role must be assigned before any other requests are made to the + * xdg_surface object. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_surface state to take effect. + * + * Creating an xdg_surface from a wl_surface which has a buffer attached or + * committed is a client error, and any attempts by a client to attach or + * manipulate a buffer prior to the first xdg_surface.configure call must + * also be treated as errors. + * + * After creating a role-specific object and setting it up, the client must + * perform an initial commit without any buffer attached. The compositor + * will reply with an xdg_surface.configure event. The client must + * acknowledge it and is then allowed to attach a buffer to map the surface. + * + * Mapping an xdg_surface-based role surface is defined as making it + * possible for the surface to be shown by the compositor. Note that + * a mapped surface is not guaranteed to be visible once it is mapped. + * + * For an xdg_surface to be mapped by the compositor, the following + * conditions must be met: + * (1) the client has assigned an xdg_surface-based role to the surface + * (2) the client has set and committed the xdg_surface state and the + * role-dependent state to the surface + * (3) the client has committed a buffer to the surface + * + * A newly-unmapped surface is considered to have met condition (1) out + * of the 3 required conditions for mapping a surface if its role surface + * has not been destroyed. + * @section page_iface_xdg_surface_api API + * See @ref iface_xdg_surface. + */ +/** + * @defgroup iface_xdg_surface The xdg_surface interface + * + * An interface that may be implemented by a wl_surface, for + * implementations that provide a desktop-style user interface. + * + * It provides a base set of functionality required to construct user + * interface elements requiring management by the compositor, such as + * toplevel windows, menus, etc. The types of functionality are split into + * xdg_surface roles. + * + * Creating an xdg_surface does not set the role for a wl_surface. In order + * to map an xdg_surface, the client must create a role-specific object + * using, e.g., get_toplevel, get_popup. The wl_surface for any given + * xdg_surface can have at most one role, and may not be assigned any role + * not based on xdg_surface. + * + * A role must be assigned before any other requests are made to the + * xdg_surface object. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_surface state to take effect. + * + * Creating an xdg_surface from a wl_surface which has a buffer attached or + * committed is a client error, and any attempts by a client to attach or + * manipulate a buffer prior to the first xdg_surface.configure call must + * also be treated as errors. + * + * After creating a role-specific object and setting it up, the client must + * perform an initial commit without any buffer attached. The compositor + * will reply with an xdg_surface.configure event. The client must + * acknowledge it and is then allowed to attach a buffer to map the surface. + * + * Mapping an xdg_surface-based role surface is defined as making it + * possible for the surface to be shown by the compositor. Note that + * a mapped surface is not guaranteed to be visible once it is mapped. + * + * For an xdg_surface to be mapped by the compositor, the following + * conditions must be met: + * (1) the client has assigned an xdg_surface-based role to the surface + * (2) the client has set and committed the xdg_surface state and the + * role-dependent state to the surface + * (3) the client has committed a buffer to the surface + * + * A newly-unmapped surface is considered to have met condition (1) out + * of the 3 required conditions for mapping a surface if its role surface + * has not been destroyed. + */ +extern const struct wl_interface xdg_surface_interface; +/** + * @page page_iface_xdg_toplevel xdg_toplevel + * @section page_iface_xdg_toplevel_desc Description + * + * This interface defines an xdg_surface role which allows a surface to, + * among other things, set window-like properties such as maximize, + * fullscreen, and minimize, set application-specific metadata like title and + * id, and well as trigger user interactive operations such as interactive + * resize and move. + * + * Unmapping an xdg_toplevel means that the surface cannot be shown + * by the compositor until it is explicitly mapped again. + * All active operations (e.g., move, resize) are canceled and all + * attributes (e.g. title, state, stacking, ...) are discarded for + * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to + * the state it had right after xdg_surface.get_toplevel. The client + * can re-map the toplevel by perfoming a commit without any buffer + * attached, waiting for a configure event and handling it as usual (see + * xdg_surface description). + * + * Attaching a null buffer to a toplevel unmaps the surface. + * @section page_iface_xdg_toplevel_api API + * See @ref iface_xdg_toplevel. + */ +/** + * @defgroup iface_xdg_toplevel The xdg_toplevel interface + * + * This interface defines an xdg_surface role which allows a surface to, + * among other things, set window-like properties such as maximize, + * fullscreen, and minimize, set application-specific metadata like title and + * id, and well as trigger user interactive operations such as interactive + * resize and move. + * + * Unmapping an xdg_toplevel means that the surface cannot be shown + * by the compositor until it is explicitly mapped again. + * All active operations (e.g., move, resize) are canceled and all + * attributes (e.g. title, state, stacking, ...) are discarded for + * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to + * the state it had right after xdg_surface.get_toplevel. The client + * can re-map the toplevel by perfoming a commit without any buffer + * attached, waiting for a configure event and handling it as usual (see + * xdg_surface description). + * + * Attaching a null buffer to a toplevel unmaps the surface. + */ +extern const struct wl_interface xdg_toplevel_interface; +/** + * @page page_iface_xdg_popup xdg_popup + * @section page_iface_xdg_popup_desc Description + * + * A popup surface is a short-lived, temporary surface. It can be used to + * implement for example menus, popovers, tooltips and other similar user + * interface concepts. + * + * A popup can be made to take an explicit grab. See xdg_popup.grab for + * details. + * + * When the popup is dismissed, a popup_done event will be sent out, and at + * the same time the surface will be unmapped. See the xdg_popup.popup_done + * event for details. + * + * Explicitly destroying the xdg_popup object will also dismiss the popup and + * unmap the surface. Clients that want to dismiss the popup when another + * surface of their own is clicked should dismiss the popup using the destroy + * request. + * + * A newly created xdg_popup will be stacked on top of all previously created + * xdg_popup surfaces associated with the same xdg_toplevel. + * + * The parent of an xdg_popup must be mapped (see the xdg_surface + * description) before the xdg_popup itself. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_popup state to take effect. + * @section page_iface_xdg_popup_api API + * See @ref iface_xdg_popup. + */ +/** + * @defgroup iface_xdg_popup The xdg_popup interface + * + * A popup surface is a short-lived, temporary surface. It can be used to + * implement for example menus, popovers, tooltips and other similar user + * interface concepts. + * + * A popup can be made to take an explicit grab. See xdg_popup.grab for + * details. + * + * When the popup is dismissed, a popup_done event will be sent out, and at + * the same time the surface will be unmapped. See the xdg_popup.popup_done + * event for details. + * + * Explicitly destroying the xdg_popup object will also dismiss the popup and + * unmap the surface. Clients that want to dismiss the popup when another + * surface of their own is clicked should dismiss the popup using the destroy + * request. + * + * A newly created xdg_popup will be stacked on top of all previously created + * xdg_popup surfaces associated with the same xdg_toplevel. + * + * The parent of an xdg_popup must be mapped (see the xdg_surface + * description) before the xdg_popup itself. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_popup state to take effect. + */ +extern const struct wl_interface xdg_popup_interface; + +#ifndef XDG_WM_BASE_ERROR_ENUM +#define XDG_WM_BASE_ERROR_ENUM +enum xdg_wm_base_error { + /** + * given wl_surface has another role + */ + XDG_WM_BASE_ERROR_ROLE = 0, + /** + * xdg_wm_base was destroyed before children + */ + XDG_WM_BASE_ERROR_DEFUNCT_SURFACES = 1, + /** + * the client tried to map or destroy a non-topmost popup + */ + XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP = 2, + /** + * the client specified an invalid popup parent surface + */ + XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT = 3, + /** + * the client provided an invalid surface state + */ + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE = 4, + /** + * the client provided an invalid positioner + */ + XDG_WM_BASE_ERROR_INVALID_POSITIONER = 5, +}; +#endif /* XDG_WM_BASE_ERROR_ENUM */ + +/** + * @ingroup iface_xdg_wm_base + * @struct xdg_wm_base_listener + */ +struct xdg_wm_base_listener { + /** + * check if the client is alive + * + * The ping event asks the client if it's still alive. Pass the + * serial specified in the event back to the compositor by sending + * a "pong" request back with the specified serial. See + * xdg_wm_base.pong. + * + * Compositors can use this to determine if the client is still + * alive. It's unspecified what will happen if the client doesn't + * respond to the ping request, or in what timeframe. Clients + * should try to respond in a reasonable amount of time. + * + * A compositor is free to ping in any way it wants, but a client + * must always respond to any xdg_wm_base object it created. + * @param serial pass this to the pong request + */ + void (*ping)(void *data, + struct xdg_wm_base *xdg_wm_base, + uint32_t serial); +}; + +/** + * @ingroup iface_xdg_wm_base + */ +static inline int +xdg_wm_base_add_listener(struct xdg_wm_base *xdg_wm_base, + const struct xdg_wm_base_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_wm_base, + (void (**)(void)) listener, data); +} + +#define XDG_WM_BASE_DESTROY 0 +#define XDG_WM_BASE_CREATE_POSITIONER 1 +#define XDG_WM_BASE_GET_XDG_SURFACE 2 +#define XDG_WM_BASE_PONG 3 + +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_PING_SINCE_VERSION 1 + +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_CREATE_POSITIONER_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_PONG_SINCE_VERSION 1 + +/** @ingroup iface_xdg_wm_base */ +static inline void +xdg_wm_base_set_user_data(struct xdg_wm_base *xdg_wm_base, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_wm_base, user_data); +} + +/** @ingroup iface_xdg_wm_base */ +static inline void * +xdg_wm_base_get_user_data(struct xdg_wm_base *xdg_wm_base) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_wm_base); +} + +static inline uint32_t +xdg_wm_base_get_version(struct xdg_wm_base *xdg_wm_base) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_wm_base); +} + +/** + * @ingroup iface_xdg_wm_base + * + * Destroy this xdg_wm_base object. + * + * Destroying a bound xdg_wm_base object while there are surfaces + * still alive created by this xdg_wm_base object instance is illegal + * and will result in a protocol error. + */ +static inline void +xdg_wm_base_destroy(struct xdg_wm_base *xdg_wm_base) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) xdg_wm_base); +} + +/** + * @ingroup iface_xdg_wm_base + * + * Create a positioner object. A positioner object is used to position + * surfaces relative to some parent surface. See the interface description + * and xdg_surface.get_popup for details. + */ +static inline struct xdg_positioner * +xdg_wm_base_create_positioner(struct xdg_wm_base *xdg_wm_base) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_CREATE_POSITIONER, &xdg_positioner_interface, NULL); + + return (struct xdg_positioner *) id; +} + +/** + * @ingroup iface_xdg_wm_base + * + * This creates an xdg_surface for the given surface. While xdg_surface + * itself is not a role, the corresponding surface may only be assigned + * a role extending xdg_surface, such as xdg_toplevel or xdg_popup. + * + * This creates an xdg_surface for the given surface. An xdg_surface is + * used as basis to define a role to a given surface, such as xdg_toplevel + * or xdg_popup. It also manages functionality shared between xdg_surface + * based surface roles. + * + * See the documentation of xdg_surface for more details about what an + * xdg_surface is and how it is used. + */ +static inline struct xdg_surface * +xdg_wm_base_get_xdg_surface(struct xdg_wm_base *xdg_wm_base, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_GET_XDG_SURFACE, &xdg_surface_interface, NULL, surface); + + return (struct xdg_surface *) id; +} + +/** + * @ingroup iface_xdg_wm_base + * + * A client must respond to a ping event with a pong request or + * the client may be deemed unresponsive. See xdg_wm_base.ping. + */ +static inline void +xdg_wm_base_pong(struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_PONG, serial); +} + +#ifndef XDG_POSITIONER_ERROR_ENUM +#define XDG_POSITIONER_ERROR_ENUM +enum xdg_positioner_error { + /** + * invalid input provided + */ + XDG_POSITIONER_ERROR_INVALID_INPUT = 0, +}; +#endif /* XDG_POSITIONER_ERROR_ENUM */ + +#ifndef XDG_POSITIONER_ANCHOR_ENUM +#define XDG_POSITIONER_ANCHOR_ENUM +enum xdg_positioner_anchor { + XDG_POSITIONER_ANCHOR_NONE = 0, + XDG_POSITIONER_ANCHOR_TOP = 1, + XDG_POSITIONER_ANCHOR_BOTTOM = 2, + XDG_POSITIONER_ANCHOR_LEFT = 3, + XDG_POSITIONER_ANCHOR_RIGHT = 4, + XDG_POSITIONER_ANCHOR_TOP_LEFT = 5, + XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6, + XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7, + XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8, +}; +#endif /* XDG_POSITIONER_ANCHOR_ENUM */ + +#ifndef XDG_POSITIONER_GRAVITY_ENUM +#define XDG_POSITIONER_GRAVITY_ENUM +enum xdg_positioner_gravity { + XDG_POSITIONER_GRAVITY_NONE = 0, + XDG_POSITIONER_GRAVITY_TOP = 1, + XDG_POSITIONER_GRAVITY_BOTTOM = 2, + XDG_POSITIONER_GRAVITY_LEFT = 3, + XDG_POSITIONER_GRAVITY_RIGHT = 4, + XDG_POSITIONER_GRAVITY_TOP_LEFT = 5, + XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6, + XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7, + XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8, +}; +#endif /* XDG_POSITIONER_GRAVITY_ENUM */ + +#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM +#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM +/** + * @ingroup iface_xdg_positioner + * vertically resize the surface + * + * Resize the surface vertically so that it is completely unconstrained. + */ +enum xdg_positioner_constraint_adjustment { + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, +}; +#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM */ + +#define XDG_POSITIONER_DESTROY 0 +#define XDG_POSITIONER_SET_SIZE 1 +#define XDG_POSITIONER_SET_ANCHOR_RECT 2 +#define XDG_POSITIONER_SET_ANCHOR 3 +#define XDG_POSITIONER_SET_GRAVITY 4 +#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT 5 +#define XDG_POSITIONER_SET_OFFSET 6 +#define XDG_POSITIONER_SET_REACTIVE 7 +#define XDG_POSITIONER_SET_PARENT_SIZE 8 +#define XDG_POSITIONER_SET_PARENT_CONFIGURE 9 + + +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_SIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_ANCHOR_RECT_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_ANCHOR_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_GRAVITY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3 + +/** @ingroup iface_xdg_positioner */ +static inline void +xdg_positioner_set_user_data(struct xdg_positioner *xdg_positioner, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_positioner, user_data); +} + +/** @ingroup iface_xdg_positioner */ +static inline void * +xdg_positioner_get_user_data(struct xdg_positioner *xdg_positioner) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_positioner); +} + +static inline uint32_t +xdg_positioner_get_version(struct xdg_positioner *xdg_positioner) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_positioner); +} + +/** + * @ingroup iface_xdg_positioner + * + * Notify the compositor that the xdg_positioner will no longer be used. + */ +static inline void +xdg_positioner_destroy(struct xdg_positioner *xdg_positioner) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) xdg_positioner); +} + +/** + * @ingroup iface_xdg_positioner + * + * Set the size of the surface that is to be positioned with the positioner + * object. The size is in surface-local coordinates and corresponds to the + * window geometry. See xdg_surface.set_window_geometry. + * + * If a zero or negative size is set the invalid_input error is raised. + */ +static inline void +xdg_positioner_set_size(struct xdg_positioner *xdg_positioner, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_SIZE, width, height); +} + +/** + * @ingroup iface_xdg_positioner + * + * Specify the anchor rectangle within the parent surface that the child + * surface will be placed relative to. The rectangle is relative to the + * window geometry as defined by xdg_surface.set_window_geometry of the + * parent surface. + * + * When the xdg_positioner object is used to position a child surface, the + * anchor rectangle may not extend outside the window geometry of the + * positioned child's parent surface. + * + * If a negative size is set the invalid_input error is raised. + */ +static inline void +xdg_positioner_set_anchor_rect(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_ANCHOR_RECT, x, y, width, height); +} + +/** + * @ingroup iface_xdg_positioner + * + * Defines the anchor point for the anchor rectangle. The specified anchor + * is used derive an anchor point that the child surface will be + * positioned relative to. If a corner anchor is set (e.g. 'top_left' or + * 'bottom_right'), the anchor point will be at the specified corner; + * otherwise, the derived anchor point will be centered on the specified + * edge, or in the center of the anchor rectangle if no edge is specified. + */ +static inline void +xdg_positioner_set_anchor(struct xdg_positioner *xdg_positioner, uint32_t anchor) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_ANCHOR, anchor); +} + +/** + * @ingroup iface_xdg_positioner + * + * Defines in what direction a surface should be positioned, relative to + * the anchor point of the parent surface. If a corner gravity is + * specified (e.g. 'bottom_right' or 'top_left'), then the child surface + * will be placed towards the specified gravity; otherwise, the child + * surface will be centered over the anchor point on any axis that had no + * gravity specified. + */ +static inline void +xdg_positioner_set_gravity(struct xdg_positioner *xdg_positioner, uint32_t gravity) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_GRAVITY, gravity); +} + +/** + * @ingroup iface_xdg_positioner + * + * Specify how the window should be positioned if the originally intended + * position caused the surface to be constrained, meaning at least + * partially outside positioning boundaries set by the compositor. The + * adjustment is set by constructing a bitmask describing the adjustment to + * be made when the surface is constrained on that axis. + * + * If no bit for one axis is set, the compositor will assume that the child + * surface should not change its position on that axis when constrained. + * + * If more than one bit for one axis is set, the order of how adjustments + * are applied is specified in the corresponding adjustment descriptions. + * + * The default adjustment is none. + */ +static inline void +xdg_positioner_set_constraint_adjustment(struct xdg_positioner *xdg_positioner, uint32_t constraint_adjustment) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT, constraint_adjustment); +} + +/** + * @ingroup iface_xdg_positioner + * + * Specify the surface position offset relative to the position of the + * anchor on the anchor rectangle and the anchor on the surface. For + * example if the anchor of the anchor rectangle is at (x, y), the surface + * has the gravity bottom|right, and the offset is (ox, oy), the calculated + * surface position will be (x + ox, y + oy). The offset position of the + * surface is the one used for constraint testing. See + * set_constraint_adjustment. + * + * An example use case is placing a popup menu on top of a user interface + * element, while aligning the user interface element of the parent surface + * with some user interface element placed somewhere in the popup surface. + */ +static inline void +xdg_positioner_set_offset(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_OFFSET, x, y); +} + +/** + * @ingroup iface_xdg_positioner + * + * When set reactive, the surface is reconstrained if the conditions used + * for constraining changed, e.g. the parent window moved. + * + * If the conditions changed and the popup was reconstrained, an + * xdg_popup.configure event is sent with updated geometry, followed by an + * xdg_surface.configure event. + */ +static inline void +xdg_positioner_set_reactive(struct xdg_positioner *xdg_positioner) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_REACTIVE); +} + +/** + * @ingroup iface_xdg_positioner + * + * Set the parent window geometry the compositor should use when + * positioning the popup. The compositor may use this information to + * determine the future state the popup should be constrained using. If + * this doesn't match the dimension of the parent the popup is eventually + * positioned against, the behavior is undefined. + * + * The arguments are given in the surface-local coordinate space. + */ +static inline void +xdg_positioner_set_parent_size(struct xdg_positioner *xdg_positioner, int32_t parent_width, int32_t parent_height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_PARENT_SIZE, parent_width, parent_height); +} + +/** + * @ingroup iface_xdg_positioner + * + * Set the serial of an xdg_surface.configure event this positioner will be + * used in response to. The compositor may use this information together + * with set_parent_size to determine what future state the popup should be + * constrained using. + */ +static inline void +xdg_positioner_set_parent_configure(struct xdg_positioner *xdg_positioner, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_PARENT_CONFIGURE, serial); +} + +#ifndef XDG_SURFACE_ERROR_ENUM +#define XDG_SURFACE_ERROR_ENUM +enum xdg_surface_error { + XDG_SURFACE_ERROR_NOT_CONSTRUCTED = 1, + XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED = 2, + XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER = 3, +}; +#endif /* XDG_SURFACE_ERROR_ENUM */ + +/** + * @ingroup iface_xdg_surface + * @struct xdg_surface_listener + */ +struct xdg_surface_listener { + /** + * suggest a surface change + * + * The configure event marks the end of a configure sequence. A + * configure sequence is a set of one or more events configuring + * the state of the xdg_surface, including the final + * xdg_surface.configure event. + * + * Where applicable, xdg_surface surface roles will during a + * configure sequence extend this event as a latched state sent as + * events before the xdg_surface.configure event. Such events + * should be considered to make up a set of atomically applied + * configuration states, where the xdg_surface.configure commits + * the accumulated state. + * + * Clients should arrange their surface for the new states, and + * then send an ack_configure request with the serial sent in this + * configure event at some point before committing the new surface. + * + * If the client receives multiple configure events before it can + * respond to one, it is free to discard all but the last event it + * received. + * @param serial serial of the configure event + */ + void (*configure)(void *data, + struct xdg_surface *xdg_surface, + uint32_t serial); +}; + +/** + * @ingroup iface_xdg_surface + */ +static inline int +xdg_surface_add_listener(struct xdg_surface *xdg_surface, + const struct xdg_surface_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_surface, + (void (**)(void)) listener, data); +} + +#define XDG_SURFACE_DESTROY 0 +#define XDG_SURFACE_GET_TOPLEVEL 1 +#define XDG_SURFACE_GET_POPUP 2 +#define XDG_SURFACE_SET_WINDOW_GEOMETRY 3 +#define XDG_SURFACE_ACK_CONFIGURE 4 + +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_CONFIGURE_SINCE_VERSION 1 + +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_GET_TOPLEVEL_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_GET_POPUP_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_SET_WINDOW_GEOMETRY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_ACK_CONFIGURE_SINCE_VERSION 1 + +/** @ingroup iface_xdg_surface */ +static inline void +xdg_surface_set_user_data(struct xdg_surface *xdg_surface, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_surface, user_data); +} + +/** @ingroup iface_xdg_surface */ +static inline void * +xdg_surface_get_user_data(struct xdg_surface *xdg_surface) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_surface); +} + +static inline uint32_t +xdg_surface_get_version(struct xdg_surface *xdg_surface) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_surface); +} + +/** + * @ingroup iface_xdg_surface + * + * Destroy the xdg_surface object. An xdg_surface must only be destroyed + * after its role object has been destroyed. + */ +static inline void +xdg_surface_destroy(struct xdg_surface *xdg_surface) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_surface, + XDG_SURFACE_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) xdg_surface); +} + +/** + * @ingroup iface_xdg_surface + * + * This creates an xdg_toplevel object for the given xdg_surface and gives + * the associated wl_surface the xdg_toplevel role. + * + * See the documentation of xdg_toplevel for more details about what an + * xdg_toplevel is and how it is used. + */ +static inline struct xdg_toplevel * +xdg_surface_get_toplevel(struct xdg_surface *xdg_surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) xdg_surface, + XDG_SURFACE_GET_TOPLEVEL, &xdg_toplevel_interface, NULL); + + return (struct xdg_toplevel *) id; +} + +/** + * @ingroup iface_xdg_surface + * + * This creates an xdg_popup object for the given xdg_surface and gives + * the associated wl_surface the xdg_popup role. + * + * If null is passed as a parent, a parent surface must be specified using + * some other protocol, before committing the initial state. + * + * See the documentation of xdg_popup for more details about what an + * xdg_popup is and how it is used. + */ +static inline struct xdg_popup * +xdg_surface_get_popup(struct xdg_surface *xdg_surface, struct xdg_surface *parent, struct xdg_positioner *positioner) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) xdg_surface, + XDG_SURFACE_GET_POPUP, &xdg_popup_interface, NULL, parent, positioner); + + return (struct xdg_popup *) id; +} + +/** + * @ingroup iface_xdg_surface + * + * The window geometry of a surface is its "visible bounds" from the + * user's perspective. Client-side decorations often have invisible + * portions like drop-shadows which should be ignored for the + * purposes of aligning, placing and constraining windows. + * + * The window geometry is double buffered, and will be applied at the + * time wl_surface.commit of the corresponding wl_surface is called. + * + * When maintaining a position, the compositor should treat the (x, y) + * coordinate of the window geometry as the top left corner of the window. + * A client changing the (x, y) window geometry coordinate should in + * general not alter the position of the window. + * + * Once the window geometry of the surface is set, it is not possible to + * unset it, and it will remain the same until set_window_geometry is + * called again, even if a new subsurface or buffer is attached. + * + * If never set, the value is the full bounds of the surface, + * including any subsurfaces. This updates dynamically on every + * commit. This unset is meant for extremely simple clients. + * + * The arguments are given in the surface-local coordinate space of + * the wl_surface associated with this xdg_surface. + * + * The width and height must be greater than zero. Setting an invalid size + * will raise an error. When applied, the effective window geometry will be + * the set window geometry clamped to the bounding rectangle of the + * combined geometry of the surface of the xdg_surface and the associated + * subsurfaces. + */ +static inline void +xdg_surface_set_window_geometry(struct xdg_surface *xdg_surface, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_surface, + XDG_SURFACE_SET_WINDOW_GEOMETRY, x, y, width, height); +} + +/** + * @ingroup iface_xdg_surface + * + * When a configure event is received, if a client commits the + * surface in response to the configure event, then the client + * must make an ack_configure request sometime before the commit + * request, passing along the serial of the configure event. + * + * For instance, for toplevel surfaces the compositor might use this + * information to move a surface to the top left only when the client has + * drawn itself for the maximized or fullscreen state. + * + * If the client receives multiple configure events before it + * can respond to one, it only has to ack the last configure event. + * + * A client is not required to commit immediately after sending + * an ack_configure request - it may even ack_configure several times + * before its next surface commit. + * + * A client may send multiple ack_configure requests before committing, but + * only the last request sent before a commit indicates which configure + * event the client really is responding to. + */ +static inline void +xdg_surface_ack_configure(struct xdg_surface *xdg_surface, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_surface, + XDG_SURFACE_ACK_CONFIGURE, serial); +} + +#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM +#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM +/** + * @ingroup iface_xdg_toplevel + * edge values for resizing + * + * These values are used to indicate which edge of a surface + * is being dragged in a resize operation. + */ +enum xdg_toplevel_resize_edge { + XDG_TOPLEVEL_RESIZE_EDGE_NONE = 0, + XDG_TOPLEVEL_RESIZE_EDGE_TOP = 1, + XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM = 2, + XDG_TOPLEVEL_RESIZE_EDGE_LEFT = 4, + XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT = 5, + XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT = 6, + XDG_TOPLEVEL_RESIZE_EDGE_RIGHT = 8, + XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT = 9, + XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT = 10, +}; +#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM */ + +#ifndef XDG_TOPLEVEL_STATE_ENUM +#define XDG_TOPLEVEL_STATE_ENUM +/** + * @ingroup iface_xdg_toplevel + * the surface is tiled + * + * The window is currently in a tiled layout and the bottom edge is + * considered to be adjacent to another part of the tiling grid. + */ +enum xdg_toplevel_state { + /** + * the surface is maximized + */ + XDG_TOPLEVEL_STATE_MAXIMIZED = 1, + /** + * the surface is fullscreen + */ + XDG_TOPLEVEL_STATE_FULLSCREEN = 2, + /** + * the surface is being resized + */ + XDG_TOPLEVEL_STATE_RESIZING = 3, + /** + * the surface is now activated + */ + XDG_TOPLEVEL_STATE_ACTIVATED = 4, + /** + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_LEFT = 5, + /** + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_RIGHT = 6, + /** + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_TOP = 7, + /** + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_BOTTOM = 8, +}; +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_TOP_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION 2 +#endif /* XDG_TOPLEVEL_STATE_ENUM */ + +/** + * @ingroup iface_xdg_toplevel + * @struct xdg_toplevel_listener + */ +struct xdg_toplevel_listener { + /** + * suggest a surface change + * + * This configure event asks the client to resize its toplevel + * surface or to change its state. The configured state should not + * be applied immediately. See xdg_surface.configure for details. + * + * The width and height arguments specify a hint to the window + * about how its surface should be resized in window geometry + * coordinates. See set_window_geometry. + * + * If the width or height arguments are zero, it means the client + * should decide its own window dimension. This may happen when the + * compositor needs to configure the state of the surface but + * doesn't have any information about any previous or expected + * dimension. + * + * The states listed in the event specify how the width/height + * arguments should be interpreted, and possibly how it should be + * drawn. + * + * Clients must send an ack_configure in response to this event. + * See xdg_surface.configure and xdg_surface.ack_configure for + * details. + */ + void (*configure)(void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *states); + /** + * surface wants to be closed + * + * The close event is sent by the compositor when the user wants + * the surface to be closed. This should be equivalent to the user + * clicking the close button in client-side decorations, if your + * application has any. + * + * This is only a request that the user intends to close the + * window. The client may choose to ignore this request, or show a + * dialog to ask the user to save their data, etc. + */ + void (*close)(void *data, + struct xdg_toplevel *xdg_toplevel); +}; + +/** + * @ingroup iface_xdg_toplevel + */ +static inline int +xdg_toplevel_add_listener(struct xdg_toplevel *xdg_toplevel, + const struct xdg_toplevel_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_toplevel, + (void (**)(void)) listener, data); +} + +#define XDG_TOPLEVEL_DESTROY 0 +#define XDG_TOPLEVEL_SET_PARENT 1 +#define XDG_TOPLEVEL_SET_TITLE 2 +#define XDG_TOPLEVEL_SET_APP_ID 3 +#define XDG_TOPLEVEL_SHOW_WINDOW_MENU 4 +#define XDG_TOPLEVEL_MOVE 5 +#define XDG_TOPLEVEL_RESIZE 6 +#define XDG_TOPLEVEL_SET_MAX_SIZE 7 +#define XDG_TOPLEVEL_SET_MIN_SIZE 8 +#define XDG_TOPLEVEL_SET_MAXIMIZED 9 +#define XDG_TOPLEVEL_UNSET_MAXIMIZED 10 +#define XDG_TOPLEVEL_SET_FULLSCREEN 11 +#define XDG_TOPLEVEL_UNSET_FULLSCREEN 12 +#define XDG_TOPLEVEL_SET_MINIMIZED 13 + +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_CONFIGURE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_CLOSE_SINCE_VERSION 1 + +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_PARENT_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_TITLE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_APP_ID_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SHOW_WINDOW_MENU_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_MOVE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_RESIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MAX_SIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MIN_SIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MAXIMIZED_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_UNSET_MAXIMIZED_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_FULLSCREEN_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_UNSET_FULLSCREEN_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MINIMIZED_SINCE_VERSION 1 + +/** @ingroup iface_xdg_toplevel */ +static inline void +xdg_toplevel_set_user_data(struct xdg_toplevel *xdg_toplevel, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel, user_data); +} + +/** @ingroup iface_xdg_toplevel */ +static inline void * +xdg_toplevel_get_user_data(struct xdg_toplevel *xdg_toplevel) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel); +} + +static inline uint32_t +xdg_toplevel_get_version(struct xdg_toplevel *xdg_toplevel) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_toplevel); +} + +/** + * @ingroup iface_xdg_toplevel + * + * This request destroys the role surface and unmaps the surface; + * see "Unmapping" behavior in interface section for details. + */ +static inline void +xdg_toplevel_destroy(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) xdg_toplevel); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set the "parent" of this surface. This surface should be stacked + * above the parent surface and all other ancestor surfaces. + * + * Parent windows should be set on dialogs, toolboxes, or other + * "auxiliary" surfaces, so that the parent is raised when the dialog + * is raised. + * + * Setting a null parent for a child window removes any parent-child + * relationship for the child. Setting a null parent for a window which + * currently has no parent is a no-op. + * + * If the parent is unmapped then its children are managed as + * though the parent of the now-unmapped parent has become the + * parent of this surface. If no parent exists for the now-unmapped + * parent then the children are managed as though they have no + * parent surface. + */ +static inline void +xdg_toplevel_set_parent(struct xdg_toplevel *xdg_toplevel, struct xdg_toplevel *parent) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_PARENT, parent); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set a short title for the surface. + * + * This string may be used to identify the surface in a task bar, + * window list, or other user interface elements provided by the + * compositor. + * + * The string must be encoded in UTF-8. + */ +static inline void +xdg_toplevel_set_title(struct xdg_toplevel *xdg_toplevel, const char *title) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_TITLE, title); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set an application identifier for the surface. + * + * The app ID identifies the general class of applications to which + * the surface belongs. The compositor can use this to group multiple + * surfaces together, or to determine how to launch a new application. + * + * For D-Bus activatable applications, the app ID is used as the D-Bus + * service name. + * + * The compositor shell will try to group application surfaces together + * by their app ID. As a best practice, it is suggested to select app + * ID's that match the basename of the application's .desktop file. + * For example, "org.freedesktop.FooViewer" where the .desktop file is + * "org.freedesktop.FooViewer.desktop". + * + * Like other properties, a set_app_id request can be sent after the + * xdg_toplevel has been mapped to update the property. + * + * See the desktop-entry specification [0] for more details on + * application identifiers and how they relate to well-known D-Bus + * names and .desktop files. + * + * [0] http://standards.freedesktop.org/desktop-entry-spec/ + */ +static inline void +xdg_toplevel_set_app_id(struct xdg_toplevel *xdg_toplevel, const char *app_id) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_APP_ID, app_id); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Clients implementing client-side decorations might want to show + * a context menu when right-clicking on the decorations, giving the + * user a menu that they can use to maximize or minimize the window. + * + * This request asks the compositor to pop up such a window menu at + * the given position, relative to the local surface coordinates of + * the parent surface. There are no guarantees as to what menu items + * the window menu contains. + * + * This request must be used in response to some sort of user action + * like a button press, key press, or touch down event. + */ +static inline void +xdg_toplevel_show_window_menu(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SHOW_WINDOW_MENU, seat, serial, x, y); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Start an interactive, user-driven move of the surface. + * + * This request must be used in response to some sort of user action + * like a button press, key press, or touch down event. The passed + * serial is used to determine the type of interactive move (touch, + * pointer, etc). + * + * The server may ignore move requests depending on the state of + * the surface (e.g. fullscreen or maximized), or if the passed serial + * is no longer valid. + * + * If triggered, the surface will lose the focus of the device + * (wl_pointer, wl_touch, etc) used for the move. It is up to the + * compositor to visually indicate that the move is taking place, such as + * updating a pointer cursor, during the move. There is no guarantee + * that the device focus will return when the move is completed. + */ +static inline void +xdg_toplevel_move(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_MOVE, seat, serial); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Start a user-driven, interactive resize of the surface. + * + * This request must be used in response to some sort of user action + * like a button press, key press, or touch down event. The passed + * serial is used to determine the type of interactive resize (touch, + * pointer, etc). + * + * The server may ignore resize requests depending on the state of + * the surface (e.g. fullscreen or maximized). + * + * If triggered, the client will receive configure events with the + * "resize" state enum value and the expected sizes. See the "resize" + * enum value for more details about what is required. The client + * must also acknowledge configure events using "ack_configure". After + * the resize is completed, the client will receive another "configure" + * event without the resize state. + * + * If triggered, the surface also will lose the focus of the device + * (wl_pointer, wl_touch, etc) used for the resize. It is up to the + * compositor to visually indicate that the resize is taking place, + * such as updating a pointer cursor, during the resize. There is no + * guarantee that the device focus will return when the resize is + * completed. + * + * The edges parameter specifies how the surface should be resized, + * and is one of the values of the resize_edge enum. The compositor + * may use this information to update the surface position for + * example when dragging the top left corner. The compositor may also + * use this information to adapt its behavior, e.g. choose an + * appropriate cursor image. + */ +static inline void +xdg_toplevel_resize(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, uint32_t edges) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_RESIZE, seat, serial, edges); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set a maximum size for the window. + * + * The client can specify a maximum size so that the compositor does + * not try to configure the window beyond this size. + * + * The width and height arguments are in window geometry coordinates. + * See xdg_surface.set_window_geometry. + * + * Values set in this way are double-buffered. They will get applied + * on the next commit. + * + * The compositor can use this information to allow or disallow + * different states like maximize or fullscreen and draw accurate + * animations. + * + * Similarly, a tiling window manager may use this information to + * place and resize client windows in a more effective way. + * + * The client should not rely on the compositor to obey the maximum + * size. The compositor may decide to ignore the values set by the + * client and request a larger size. + * + * If never set, or a value of zero in the request, means that the + * client has no expected maximum size in the given dimension. + * As a result, a client wishing to reset the maximum size + * to an unspecified state can use zero for width and height in the + * request. + * + * Requesting a maximum size to be smaller than the minimum size of + * a surface is illegal and will result in a protocol error. + * + * The width and height must be greater than or equal to zero. Using + * strictly negative values for width and height will result in a + * protocol error. + */ +static inline void +xdg_toplevel_set_max_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MAX_SIZE, width, height); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set a minimum size for the window. + * + * The client can specify a minimum size so that the compositor does + * not try to configure the window below this size. + * + * The width and height arguments are in window geometry coordinates. + * See xdg_surface.set_window_geometry. + * + * Values set in this way are double-buffered. They will get applied + * on the next commit. + * + * The compositor can use this information to allow or disallow + * different states like maximize or fullscreen and draw accurate + * animations. + * + * Similarly, a tiling window manager may use this information to + * place and resize client windows in a more effective way. + * + * The client should not rely on the compositor to obey the minimum + * size. The compositor may decide to ignore the values set by the + * client and request a smaller size. + * + * If never set, or a value of zero in the request, means that the + * client has no expected minimum size in the given dimension. + * As a result, a client wishing to reset the minimum size + * to an unspecified state can use zero for width and height in the + * request. + * + * Requesting a minimum size to be larger than the maximum size of + * a surface is illegal and will result in a protocol error. + * + * The width and height must be greater than or equal to zero. Using + * strictly negative values for width and height will result in a + * protocol error. + */ +static inline void +xdg_toplevel_set_min_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MIN_SIZE, width, height); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Maximize the surface. + * + * After requesting that the surface should be maximized, the compositor + * will respond by emitting a configure event. Whether this configure + * actually sets the window maximized is subject to compositor policies. + * The client must then update its content, drawing in the configured + * state. The client must also acknowledge the configure when committing + * the new content (see ack_configure). + * + * It is up to the compositor to decide how and where to maximize the + * surface, for example which output and what region of the screen should + * be used. + * + * If the surface was already maximized, the compositor will still emit + * a configure event with the "maximized" state. + * + * If the surface is in a fullscreen state, this request has no direct + * effect. It may alter the state the surface is returned to when + * unmaximized unless overridden by the compositor. + */ +static inline void +xdg_toplevel_set_maximized(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MAXIMIZED); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Unmaximize the surface. + * + * After requesting that the surface should be unmaximized, the compositor + * will respond by emitting a configure event. Whether this actually + * un-maximizes the window is subject to compositor policies. + * If available and applicable, the compositor will include the window + * geometry dimensions the window had prior to being maximized in the + * configure event. The client must then update its content, drawing it in + * the configured state. The client must also acknowledge the configure + * when committing the new content (see ack_configure). + * + * It is up to the compositor to position the surface after it was + * unmaximized; usually the position the surface had before maximizing, if + * applicable. + * + * If the surface was already not maximized, the compositor will still + * emit a configure event without the "maximized" state. + * + * If the surface is in a fullscreen state, this request has no direct + * effect. It may alter the state the surface is returned to when + * unmaximized unless overridden by the compositor. + */ +static inline void +xdg_toplevel_unset_maximized(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_UNSET_MAXIMIZED); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Make the surface fullscreen. + * + * After requesting that the surface should be fullscreened, the + * compositor will respond by emitting a configure event. Whether the + * client is actually put into a fullscreen state is subject to compositor + * policies. The client must also acknowledge the configure when + * committing the new content (see ack_configure). + * + * The output passed by the request indicates the client's preference as + * to which display it should be set fullscreen on. If this value is NULL, + * it's up to the compositor to choose which display will be used to map + * this surface. + * + * If the surface doesn't cover the whole output, the compositor will + * position the surface in the center of the output and compensate with + * with border fill covering the rest of the output. The content of the + * border fill is undefined, but should be assumed to be in some way that + * attempts to blend into the surrounding area (e.g. solid black). + * + * If the fullscreened surface is not opaque, the compositor must make + * sure that other screen content not part of the same surface tree (made + * up of subsurfaces, popups or similarly coupled surfaces) are not + * visible below the fullscreened surface. + */ +static inline void +xdg_toplevel_set_fullscreen(struct xdg_toplevel *xdg_toplevel, struct wl_output *output) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_FULLSCREEN, output); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Make the surface no longer fullscreen. + * + * After requesting that the surface should be unfullscreened, the + * compositor will respond by emitting a configure event. + * Whether this actually removes the fullscreen state of the client is + * subject to compositor policies. + * + * Making a surface unfullscreen sets states for the surface based on the following: + * * the state(s) it may have had before becoming fullscreen + * * any state(s) decided by the compositor + * * any state(s) requested by the client while the surface was fullscreen + * + * The compositor may include the previous window geometry dimensions in + * the configure event, if applicable. + * + * The client must also acknowledge the configure when committing the new + * content (see ack_configure). + */ +static inline void +xdg_toplevel_unset_fullscreen(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_UNSET_FULLSCREEN); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Request that the compositor minimize your surface. There is no + * way to know if the surface is currently minimized, nor is there + * any way to unset minimization on this surface. + * + * If you are looking to throttle redrawing when minimized, please + * instead use the wl_surface.frame event for this, as this will + * also work with live previews on windows in Alt-Tab, Expose or + * similar compositor features. + */ +static inline void +xdg_toplevel_set_minimized(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MINIMIZED); +} + +#ifndef XDG_POPUP_ERROR_ENUM +#define XDG_POPUP_ERROR_ENUM +enum xdg_popup_error { + /** + * tried to grab after being mapped + */ + XDG_POPUP_ERROR_INVALID_GRAB = 0, +}; +#endif /* XDG_POPUP_ERROR_ENUM */ + +/** + * @ingroup iface_xdg_popup + * @struct xdg_popup_listener + */ +struct xdg_popup_listener { + /** + * configure the popup surface + * + * This event asks the popup surface to configure itself given + * the configuration. The configured state should not be applied + * immediately. See xdg_surface.configure for details. + * + * The x and y arguments represent the position the popup was + * placed at given the xdg_positioner rule, relative to the upper + * left corner of the window geometry of the parent surface. + * + * For version 2 or older, the configure event for an xdg_popup is + * only ever sent once for the initial configuration. Starting with + * version 3, it may be sent again if the popup is setup with an + * xdg_positioner with set_reactive requested, or in response to + * xdg_popup.reposition requests. + * @param x x position relative to parent surface window geometry + * @param y y position relative to parent surface window geometry + * @param width window geometry width + * @param height window geometry height + */ + void (*configure)(void *data, + struct xdg_popup *xdg_popup, + int32_t x, + int32_t y, + int32_t width, + int32_t height); + /** + * popup interaction is done + * + * The popup_done event is sent out when a popup is dismissed by + * the compositor. The client should destroy the xdg_popup object + * at this point. + */ + void (*popup_done)(void *data, + struct xdg_popup *xdg_popup); + /** + * signal the completion of a repositioned request + * + * The repositioned event is sent as part of a popup + * configuration sequence, together with xdg_popup.configure and + * lastly xdg_surface.configure to notify the completion of a + * reposition request. + * + * The repositioned event is to notify about the completion of a + * xdg_popup.reposition request. The token argument is the token + * passed in the xdg_popup.reposition request. + * + * Immediately after this event is emitted, xdg_popup.configure and + * xdg_surface.configure will be sent with the updated size and + * position, as well as a new configure serial. + * + * The client should optionally update the content of the popup, + * but must acknowledge the new popup configuration for the new + * position to take effect. See xdg_surface.ack_configure for + * details. + * @param token reposition request token + * @since 3 + */ + void (*repositioned)(void *data, + struct xdg_popup *xdg_popup, + uint32_t token); +}; + +/** + * @ingroup iface_xdg_popup + */ +static inline int +xdg_popup_add_listener(struct xdg_popup *xdg_popup, + const struct xdg_popup_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_popup, + (void (**)(void)) listener, data); +} + +#define XDG_POPUP_DESTROY 0 +#define XDG_POPUP_GRAB 1 +#define XDG_POPUP_REPOSITION 2 + +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_CONFIGURE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3 + +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_GRAB_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_REPOSITION_SINCE_VERSION 3 + +/** @ingroup iface_xdg_popup */ +static inline void +xdg_popup_set_user_data(struct xdg_popup *xdg_popup, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_popup, user_data); +} + +/** @ingroup iface_xdg_popup */ +static inline void * +xdg_popup_get_user_data(struct xdg_popup *xdg_popup) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_popup); +} + +static inline uint32_t +xdg_popup_get_version(struct xdg_popup *xdg_popup) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_popup); +} + +/** + * @ingroup iface_xdg_popup + * + * This destroys the popup. Explicitly destroying the xdg_popup + * object will also dismiss the popup, and unmap the surface. + * + * If this xdg_popup is not the "topmost" popup, a protocol error + * will be sent. + */ +static inline void +xdg_popup_destroy(struct xdg_popup *xdg_popup) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_popup, + XDG_POPUP_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) xdg_popup); +} + +/** + * @ingroup iface_xdg_popup + * + * This request makes the created popup take an explicit grab. An explicit + * grab will be dismissed when the user dismisses the popup, or when the + * client destroys the xdg_popup. This can be done by the user clicking + * outside the surface, using the keyboard, or even locking the screen + * through closing the lid or a timeout. + * + * If the compositor denies the grab, the popup will be immediately + * dismissed. + * + * This request must be used in response to some sort of user action like a + * button press, key press, or touch down event. The serial number of the + * event should be passed as 'serial'. + * + * The parent of a grabbing popup must either be an xdg_toplevel surface or + * another xdg_popup with an explicit grab. If the parent is another + * xdg_popup it means that the popups are nested, with this popup now being + * the topmost popup. + * + * Nested popups must be destroyed in the reverse order they were created + * in, e.g. the only popup you are allowed to destroy at all times is the + * topmost one. + * + * When compositors choose to dismiss a popup, they may dismiss every + * nested grabbing popup as well. When a compositor dismisses popups, it + * will follow the same dismissing order as required from the client. + * + * The parent of a grabbing popup must either be another xdg_popup with an + * active explicit grab, or an xdg_popup or xdg_toplevel, if there are no + * explicit grabs already taken. + * + * If the topmost grabbing popup is destroyed, the grab will be returned to + * the parent of the popup, if that parent previously had an explicit grab. + * + * If the parent is a grabbing popup which has already been dismissed, this + * popup will be immediately dismissed. If the parent is a popup that did + * not take an explicit grab, an error will be raised. + * + * During a popup grab, the client owning the grab will receive pointer + * and touch events for all their surfaces as normal (similar to an + * "owner-events" grab in X11 parlance), while the top most grabbing popup + * will always have keyboard focus. + */ +static inline void +xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_popup, + XDG_POPUP_GRAB, seat, serial); +} + +/** + * @ingroup iface_xdg_popup + * + * Reposition an already-mapped popup. The popup will be placed given the + * details in the passed xdg_positioner object, and a + * xdg_popup.repositioned followed by xdg_popup.configure and + * xdg_surface.configure will be emitted in response. Any parameters set + * by the previous positioner will be discarded. + * + * The passed token will be sent in the corresponding + * xdg_popup.repositioned event. The new popup position will not take + * effect until the corresponding configure event is acknowledged by the + * client. See xdg_popup.repositioned for details. The token itself is + * opaque, and has no other special meaning. + * + * If multiple reposition requests are sent, the compositor may skip all + * but the last one. + * + * If the popup is repositioned in response to a configure event for its + * parent, the client should send an xdg_positioner.set_parent_configure + * and possibly an xdg_positioner.set_parent_size request to allow the + * compositor to properly constrain the popup. + * + * If the popup is repositioned together with a parent that is being + * resized, but not in response to a configure event, the client should + * send an xdg_positioner.set_parent_size request. + */ +static inline void +xdg_popup_reposition(struct xdg_popup *xdg_popup, struct xdg_positioner *positioner, uint32_t token) +{ + wl_proxy_marshal((struct wl_proxy *) xdg_popup, + XDG_POPUP_REPOSITION, positioner, token); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wl_platform.h b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wl_platform.h index 41a7fdfa7a..0324e67ac9 100644 --- a/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wl_platform.h +++ b/vendor/github.com/go-gl/glfw/v3.3/glfw/glfw/src/wl_platform.h @@ -57,7 +57,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #include "osmesa_context.h" #include "wayland-xdg-shell-client-protocol.h" -#include "wayland-xdg-decoration-client-protocol.h" +#include "wayland-xdg-decoration-unstable-v1-client-protocol.h" #include "wayland-viewporter-client-protocol.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" diff --git a/vendor/modules.txt b/vendor/modules.txt index c31b4a2a42..18f4ba17be 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -23,7 +23,7 @@ github.com/fyne-io/mobile/internal/mobileinit # github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 github.com/go-gl/gl/v3.1/gles2 github.com/go-gl/gl/v3.2-core/gl -# github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 => github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201114140358-a39598fbf952 +# github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 => github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d github.com/go-gl/glfw/v3.3/glfw github.com/go-gl/glfw/v3.3/glfw/glfw/deps github.com/go-gl/glfw/v3.3/glfw/glfw/deps/glad From b66d5507df93856c7194a132b9681a739f3149f2 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 23 Nov 2020 14:41:59 +0000 Subject: [PATCH 10/33] Start work towards 1.4.2 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 684ffbafd1..24c8bb81c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). +## 1.4.2 - Ongoing + +### Fixed + +* [fyne-cli] Android: allow to specify an inline password for the keystore +* Fixed Card widget MinSize (#1581) +* Fix missing release tag to enable BuildRelease in Settings.BuildType() + + ## 1.4.1 - 20 November 2020 ### Changed From c9aa6fde67fa56f16c55a759976bffd4c6270ed6 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 23 Nov 2020 20:21:09 +0000 Subject: [PATCH 11/33] Quietly begin wayland testing --- internal/driver/glfw/driver.go | 7 +++++-- internal/driver/glfw/driver_wayland.go | 7 +++++++ internal/driver/glfw/window.go | 10 ++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 internal/driver/glfw/driver_wayland.go diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index 5f9d7680f6..547bba4afb 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -15,8 +15,11 @@ import ( const mainGoroutineID = 1 -var canvasMutex sync.RWMutex -var canvases = make(map[fyne.CanvasObject]fyne.Canvas) +var ( + canvasMutex sync.RWMutex + canvases = make(map[fyne.CanvasObject]fyne.Canvas) + isWayland = false +) // Declare conformity with Driver var _ fyne.Driver = (*gLDriver)(nil) diff --git a/internal/driver/glfw/driver_wayland.go b/internal/driver/glfw/driver_wayland.go new file mode 100644 index 0000000000..ec76f3eb36 --- /dev/null +++ b/internal/driver/glfw/driver_wayland.go @@ -0,0 +1,7 @@ +// +build wayland + +package glfw + +func init() { + isWayland = true +} diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 39c64418c2..39c4a9a0b5 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -160,6 +160,10 @@ func (w *window) screenSize(canvasSize fyne.Size) (int, int) { } func (w *window) RequestFocus() { + if isWayland { + return + } + w.runOnMainWhenCreated(w.viewport.Focus) } @@ -1185,8 +1189,10 @@ func (d *gLDriver) createWindow(title string, decorate bool) fyne.Window { func (w *window) create() { runOnMain(func() { - // make the window hidden, we will set it up and then show it later - glfw.WindowHint(glfw.Visible, 0) + if !isWayland { + // make the window hidden, we will set it up and then show it later + glfw.WindowHint(glfw.Visible, 0) + } if w.decorate { glfw.WindowHint(glfw.Decorated, 1) } else { From 19ce989a02fa7ed75ea95d149eaff398860de56d Mon Sep 17 00:00:00 2001 From: lucor Date: Tue, 24 Nov 2020 20:08:44 +0100 Subject: [PATCH 12/33] [fyne-cli] Add support for passing custom build tags Fixes #1538 --- CHANGELOG.md | 4 ++++ cmd/fyne/commands/build.go | 11 ++++++++++- cmd/fyne/commands/package.go | 4 ++++ cmd/fyne/commands/release.go | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24c8bb81c8..a0ad3fd1f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ More detailed release notes can be found on the [releases page](https://github.c ## 1.4.2 - Ongoing +### Added + +* [fyne-cli] Add support for passing custom build tags (#1538) + ### Fixed * [fyne-cli] Android: allow to specify an inline password for the keystore diff --git a/cmd/fyne/commands/build.go b/cmd/fyne/commands/build.go index 1c63559b6f..001f681ed7 100644 --- a/cmd/fyne/commands/build.go +++ b/cmd/fyne/commands/build.go @@ -5,11 +5,13 @@ import ( "os" "os/exec" "runtime" + "strings" ) type builder struct { os, srcdir string release bool + tags []string } func (b *builder) build() error { @@ -32,9 +34,16 @@ func (b *builder) build() error { args = append(args, "build") } } + + // handle build tags + tags := b.tags if b.release { - args = append(args, "-tags", "release") + args = append(tags, "release") + } + if len(tags) > 0 { + args = append(args, "-tags", strings.Join(tags, ",")) } + cmd := exec.Command("go", args...) cmd.Dir = b.srcdir env := os.Environ() diff --git a/cmd/fyne/commands/package.go b/cmd/fyne/commands/package.go index c72a10973b..5fac8b24f6 100644 --- a/cmd/fyne/commands/package.go +++ b/cmd/fyne/commands/package.go @@ -31,6 +31,7 @@ type packager struct { appBuild int install, release bool certificate, profile string // optional flags for releasing + tags string } // NewPackager returns a packager command that can wrap executables into full GUI app packages. @@ -48,6 +49,7 @@ func (p *packager) AddFlags() { flag.StringVar(&p.appVersion, "appVersion", "", "Version number in the form x, x.y or x.y.z semantic version") flag.IntVar(&p.appBuild, "appBuild", 0, "Build number, should be greater than 0 and incremented for each build") flag.BoolVar(&p.release, "release", false, "Should this package be prepared for release? (disable debug etc)") + flag.StringVar(&p.tags, "tags", "", "A comma-separated list of build tags") } func (*packager) PrintHelp(indent string) { @@ -71,10 +73,12 @@ func (p *packager) Run(_ []string) { } func (p *packager) buildPackage() error { + tags := strings.Split(p.tags, ",") b := &builder{ os: p.os, srcdir: p.srcDir, release: p.release, + tags: tags, } return b.build() diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index 5115ae086e..6bfd7faf28 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -47,6 +47,7 @@ func (r *releaser) AddFlags() { flag.StringVar(&r.profile, "profile", "", "iOS/macOS: name of the provisioning profile for this release build") flag.StringVar(&r.developer, "developer", "", "Windows: the developer identity for your Microsoft store account") flag.StringVar(&r.password, "password", "", "Windows: password for the certificate used to sign the build") + flag.StringVar(&r.tags, "tags", "", "A comma-separated list of build tags") } func (r *releaser) PrintHelp(indent string) { From cb339726f13f804b591b344b84554b493965d25c Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Thu, 26 Nov 2020 19:33:22 +0000 Subject: [PATCH 13/33] Start work for macOS packager, this gets the format right Transporter now recognises the package and can match it to pending releases --- cmd/fyne/commands/release.go | 9 +++++ cmd/fyne/internal/templates/bundled.go | 2 +- cmd/fyne/internal/templates/data/Info.plist | 40 +++++++++++---------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index 6bfd7faf28..1473c3f617 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -80,6 +80,9 @@ func (r *releaser) afterPackage() error { } return r.signAndroid(apk) } + if r.os == "darwin" { + return r.packageMacOSRelease() + } if r.os == "ios" { return r.packageIOSRelease() } @@ -156,6 +159,12 @@ func (r *releaser) packageIOSRelease() error { return exec.Command("zip", "-r", appName[:len(appName)-4]+".ipa", "Payload/").Run() } +func (r *releaser) packageMacOSRelease() error { + cmd := exec.Command("productbuild", "--component", r.name+".app", "/Applications/", + "--product", r.name+".app/Contents/Info.plist", r.name+".pkg") + return cmd.Run() +} + func (r *releaser) packageWindowsRelease(outFile string) error { payload := filepath.Join(r.dir, "Payload") os.Mkdir(payload, 0750) diff --git a/cmd/fyne/internal/templates/bundled.go b/cmd/fyne/internal/templates/bundled.go index 1c3d382f3d..f3cf32a6e2 100644 --- a/cmd/fyne/internal/templates/bundled.go +++ b/cmd/fyne/internal/templates/bundled.go @@ -7,7 +7,7 @@ import "fyne.io/fyne" var resourceInfoPlist = &fyne.StaticResource{ StaticName: "Info.plist", StaticContent: []byte{ - 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, 56, 34, 63, 62, 10, 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 112, 108, 105, 115, 116, 32, 80, 85, 66, 76, 73, 67, 32, 34, 45, 47, 47, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 47, 47, 68, 84, 68, 32, 80, 76, 73, 83, 84, 32, 49, 46, 48, 47, 47, 69, 78, 34, 32, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 68, 84, 68, 115, 47, 80, 114, 111, 112, 101, 114, 116, 121, 76, 105, 115, 116, 45, 49, 46, 48, 46, 100, 116, 100, 34, 62, 10, 60, 112, 108, 105, 115, 116, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 62, 10, 60, 100, 105, 99, 116, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 78, 97, 109, 101, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 69, 120, 101, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 65, 112, 112, 73, 68, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 99, 111, 110, 70, 105, 108, 101, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 105, 99, 111, 110, 46, 105, 99, 110, 115, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 104, 111, 114, 116, 86, 101, 114, 115, 105, 111, 110, 83, 116, 114, 105, 110, 103, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 86, 101, 114, 115, 105, 111, 110, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 66, 117, 105, 108, 100, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 78, 83, 72, 105, 103, 104, 82, 101, 115, 111, 108, 117, 116, 105, 111, 110, 67, 97, 112, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 60, 116, 114, 117, 101, 47, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 110, 102, 111, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 54, 46, 48, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 80, 97, 99, 107, 97, 103, 101, 84, 121, 112, 101, 60, 47, 107, 101, 121, 62, 10, 60, 115, 116, 114, 105, 110, 103, 62, 65, 80, 80, 76, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 47, 100, 105, 99, 116, 62, 10, 60, 47, 112, 108, 105, 115, 116, 62}} + 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, 56, 34, 63, 62, 10, 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 112, 108, 105, 115, 116, 32, 80, 85, 66, 76, 73, 67, 32, 34, 45, 47, 47, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 47, 47, 68, 84, 68, 32, 80, 76, 73, 83, 84, 32, 49, 46, 48, 47, 47, 69, 78, 34, 32, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 68, 84, 68, 115, 47, 80, 114, 111, 112, 101, 114, 116, 121, 76, 105, 115, 116, 45, 49, 46, 48, 46, 100, 116, 100, 34, 62, 10, 60, 112, 108, 105, 115, 116, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 62, 10, 60, 100, 105, 99, 116, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 78, 97, 109, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 69, 120, 101, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 65, 112, 112, 73, 68, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 99, 111, 110, 70, 105, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 105, 99, 111, 110, 46, 105, 99, 110, 115, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 104, 111, 114, 116, 86, 101, 114, 115, 105, 111, 110, 83, 116, 114, 105, 110, 103, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 86, 101, 114, 115, 105, 111, 110, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 117, 112, 112, 111, 114, 116, 101, 100, 80, 108, 97, 116, 102, 111, 114, 109, 115, 60, 47, 107, 101, 121, 62, 10, 9, 60, 97, 114, 114, 97, 121, 62, 10, 9, 9, 60, 115, 116, 114, 105, 110, 103, 62, 77, 97, 99, 79, 83, 88, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 47, 97, 114, 114, 97, 121, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 66, 117, 105, 108, 100, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 78, 83, 72, 105, 103, 104, 82, 101, 115, 111, 108, 117, 116, 105, 111, 110, 67, 97, 112, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 116, 114, 117, 101, 47, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 110, 102, 111, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 54, 46, 48, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 80, 97, 99, 107, 97, 103, 101, 84, 121, 112, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 65, 80, 80, 76, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 47, 100, 105, 99, 116, 62, 10, 60, 47, 112, 108, 105, 115, 116, 62}} var resourceMakefile = &fyne.StaticResource{ StaticName: "Makefile", diff --git a/cmd/fyne/internal/templates/data/Info.plist b/cmd/fyne/internal/templates/data/Info.plist index 4903536b73..18ad740985 100644 --- a/cmd/fyne/internal/templates/data/Info.plist +++ b/cmd/fyne/internal/templates/data/Info.plist @@ -2,23 +2,27 @@ -CFBundleName -{{.Name}} -CFBundleExecutable -{{.ExeName}} -CFBundleIdentifier -{{.AppID}} -CFBundleIconFile -icon.icns -CFBundleShortVersionString -{{.Version}} -CFBundleVersion -{{.Build}} -NSHighResolutionCapable - -CFBundleInfoDictionaryVersion -6.0 -CFBundlePackageType -APPL + CFBundleName + {{.Name}} + CFBundleExecutable + {{.ExeName}} + CFBundleIdentifier + {{.AppID}} + CFBundleIconFile + icon.icns + CFBundleShortVersionString + {{.Version}} + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + {{.Build}} + NSHighResolutionCapable + + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL \ No newline at end of file From 9796835616be7ae1db254f82d0ed0dc70dea3dfc Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 10:00:52 +0000 Subject: [PATCH 14/33] Complete the package and sign of a macOS app Fixes #1443 --- cmd/fyne/commands/package-darwin.go | 5 +- cmd/fyne/commands/package.go | 2 +- cmd/fyne/commands/release.go | 71 ++++++++++++++++++- cmd/fyne/commands/release_test.go | 10 +++ cmd/fyne/internal/templates/bundled.go | 11 ++- cmd/fyne/internal/templates/data/Info.plist | 4 ++ .../templates/data/entitlements-darwin.plist | 8 +++ ...itlements.plist => entitlements-ios.plist} | 0 cmd/fyne/internal/templates/templates.go | 7 +- 9 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 cmd/fyne/internal/templates/data/entitlements-darwin.plist rename cmd/fyne/internal/templates/data/{entitlements.plist => entitlements-ios.plist} (100%) diff --git a/cmd/fyne/commands/package-darwin.go b/cmd/fyne/commands/package-darwin.go index e96cf63382..abc92a320e 100644 --- a/cmd/fyne/commands/package-darwin.go +++ b/cmd/fyne/commands/package-darwin.go @@ -4,6 +4,7 @@ import ( "image" "os" "path/filepath" + "strings" "fyne.io/fyne/cmd/fyne/internal/templates" "fyne.io/fyne/cmd/fyne/internal/util" @@ -17,6 +18,7 @@ type darwinData struct { AppID string Version string Build int + Category string } func (p *packager) packageDarwin() error { @@ -27,7 +29,8 @@ func (p *packager) packageDarwin() error { info := filepath.Join(contentsDir, "Info.plist") infoFile, _ := os.Create(info) - tplData := darwinData{Name: p.name, ExeName: exeName, AppID: p.appID, Version: p.appVersion, Build: p.appBuild} + tplData := darwinData{Name: p.name, ExeName: exeName, AppID: p.appID, Version: p.appVersion, Build: p.appBuild, + Category: strings.ToLower(p.category)} err := templates.InfoPlistDarwin.Execute(infoFile, tplData) if err != nil { return errors.Wrap(err, "Failed to write plist template") diff --git a/cmd/fyne/commands/package.go b/cmd/fyne/commands/package.go index 5fac8b24f6..28ffb194ae 100644 --- a/cmd/fyne/commands/package.go +++ b/cmd/fyne/commands/package.go @@ -31,7 +31,7 @@ type packager struct { appBuild int install, release bool certificate, profile string // optional flags for releasing - tags string + tags, category string } // NewPackager returns a packager command that can wrap executables into full GUI app packages. diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index 1473c3f617..8c6ec18667 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -15,6 +15,17 @@ import ( "fyne.io/fyne/cmd/fyne/internal/util" ) +var ( + macAppStoreCategories = []string{ + "business", "developer-tools", "education", "entertainment", "finance", "games", "action-games", + "adventure-games", "arcade-games", "board-games", "card-games", "casino-games", "dice-games", + "educational-games", "family-games", "kids-games", "music-games", "puzzle-games", "racing-games", + "role-playing-games", "simulation-games", "sports-games", "strategy-games", "trivia-games", "word-games", + "graphics-design", "healthcare-fitness", "lifestyle", "medical", "music", "news", "photography", + "productivity", "reference", "social-networking", "sports", "travel", "utilities", "video", "weather", + } +) + // Declare conformity to Command interface var _ Command = (*releaser)(nil) @@ -48,6 +59,7 @@ func (r *releaser) AddFlags() { flag.StringVar(&r.developer, "developer", "", "Windows: the developer identity for your Microsoft store account") flag.StringVar(&r.password, "password", "", "Windows: password for the certificate used to sign the build") flag.StringVar(&r.tags, "tags", "", "A comma-separated list of build tags") + flag.StringVar(&r.category, "category", "", "iOS: category of the app for store listing") } func (r *releaser) PrintHelp(indent string) { @@ -143,7 +155,7 @@ func (r *releaser) packageIOSRelease() error { TeamID: team, AppID: r.appID, } - err = templates.EntitlementsDarwin.Execute(entitlements, entitlementData) + err = templates.EntitlementsDarwinMobile.Execute(entitlements, entitlementData) entitlements.Close() if err != nil { return errors.New("failed to write entitlements plist template") @@ -160,8 +172,40 @@ func (r *releaser) packageIOSRelease() error { } func (r *releaser) packageMacOSRelease() error { - cmd := exec.Command("productbuild", "--component", r.name+".app", "/Applications/", - "--product", r.name+".app/Contents/Info.plist", r.name+".pkg") + appCert := r.certificate // try to derive two certificates from one name (they will be consistent) + if strings.Index(appCert, "Installer") != -1 { + appCert = strings.Replace(appCert, "Installer", "Application", 1) + } + installCert := strings.Replace(appCert, "Application", "Installer", 1) + unsignedPath := r.name + "-unsigned.pkg" + + defer os.RemoveAll(r.name + ".app") // this was the output of package and it can get in the way of future builds + entitlementPath := filepath.Join(r.dir, "entitlements.plist") + entitlements, _ := os.Create(entitlementPath) + err := templates.EntitlementsDarwin.Execute(entitlements, nil) + entitlements.Close() + if err != nil { + return errors.New("failed to write entitlements plist template") + } + defer os.Remove(entitlementPath) + + cmd := exec.Command("codesign", "-vfs", appCert, "--entitlement", "entitlements.plist", r.name+".app") + err = cmd.Run() + if err != nil { + fyne.LogError("Codesign failed", err) + return errors.New("unable to codesign application bundle") + } + + cmd = exec.Command("productbuild", "--component", r.name+".app", "/Applications/", + "--product", r.name+".app/Contents/Info.plist", unsignedPath) + err = cmd.Run() + if err != nil { + fyne.LogError("Product build failed", err) + return errors.New("unable to build macOS app package") + } + defer os.Remove(unsignedPath) + + cmd = exec.Command("productsign", "--sign", installCert, unsignedPath, r.name+".pkg") return cmd.Run() } @@ -265,6 +309,16 @@ func (r *releaser) validate() error { if r.keyStore == "" { return errors.New("missing required -keyStore parameter for android release") } + } else if r.os == "darwin" { + if r.certificate == "" { + r.certificate = "3rd Party Mac Developer Application" + } + if r.category == "" { + return errors.New("missing required -category parameter for macOS release") + } else if !isValidMacOSCategory(r.category) { + return errors.New("category does not match one of the supported list: " + + strings.Join(macAppStoreCategories, ", ")) + } } else if r.os == "ios" { if r.certificate == "" { r.certificate = "Apple Distribution" @@ -305,3 +359,14 @@ func findWindowsSDKBin() (string, error) { return filepath.Dir(matches[0]), nil } + +func isValidMacOSCategory(in string) bool { + found := false + for _, cat := range macAppStoreCategories { + if cat == strings.ToLower(in) { + found = true + break + } + } + return found +} diff --git a/cmd/fyne/commands/release_test.go b/cmd/fyne/commands/release_test.go index e9cb752fd8..92612f9e05 100644 --- a/cmd/fyne/commands/release_test.go +++ b/cmd/fyne/commands/release_test.go @@ -16,3 +16,13 @@ func TestReleaser_nameFromCertInfo(t *testing.T) { badCase := "Cn=Company, O=Company, L=City, S=State, C=Country" assert.Equal(t, "Company", rel.nameFromCertInfo(badCase)) } + +func TestIsValidMacOSCategory(t *testing.T) { + assert.True(t, isValidMacOSCategory("games")) + assert.True(t, isValidMacOSCategory("utilities")) + assert.True(t, isValidMacOSCategory("Games")) + + assert.False(t, isValidMacOSCategory("sporps")) + assert.False(t, isValidMacOSCategory("android-games")) + assert.False(t, isValidMacOSCategory("")) +} diff --git a/cmd/fyne/internal/templates/bundled.go b/cmd/fyne/internal/templates/bundled.go index f3cf32a6e2..4980eb5343 100644 --- a/cmd/fyne/internal/templates/bundled.go +++ b/cmd/fyne/internal/templates/bundled.go @@ -7,7 +7,7 @@ import "fyne.io/fyne" var resourceInfoPlist = &fyne.StaticResource{ StaticName: "Info.plist", StaticContent: []byte{ - 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, 56, 34, 63, 62, 10, 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 112, 108, 105, 115, 116, 32, 80, 85, 66, 76, 73, 67, 32, 34, 45, 47, 47, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 47, 47, 68, 84, 68, 32, 80, 76, 73, 83, 84, 32, 49, 46, 48, 47, 47, 69, 78, 34, 32, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 68, 84, 68, 115, 47, 80, 114, 111, 112, 101, 114, 116, 121, 76, 105, 115, 116, 45, 49, 46, 48, 46, 100, 116, 100, 34, 62, 10, 60, 112, 108, 105, 115, 116, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 62, 10, 60, 100, 105, 99, 116, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 78, 97, 109, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 69, 120, 101, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 65, 112, 112, 73, 68, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 99, 111, 110, 70, 105, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 105, 99, 111, 110, 46, 105, 99, 110, 115, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 104, 111, 114, 116, 86, 101, 114, 115, 105, 111, 110, 83, 116, 114, 105, 110, 103, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 86, 101, 114, 115, 105, 111, 110, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 117, 112, 112, 111, 114, 116, 101, 100, 80, 108, 97, 116, 102, 111, 114, 109, 115, 60, 47, 107, 101, 121, 62, 10, 9, 60, 97, 114, 114, 97, 121, 62, 10, 9, 9, 60, 115, 116, 114, 105, 110, 103, 62, 77, 97, 99, 79, 83, 88, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 47, 97, 114, 114, 97, 121, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 66, 117, 105, 108, 100, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 78, 83, 72, 105, 103, 104, 82, 101, 115, 111, 108, 117, 116, 105, 111, 110, 67, 97, 112, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 116, 114, 117, 101, 47, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 110, 102, 111, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 54, 46, 48, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 80, 97, 99, 107, 97, 103, 101, 84, 121, 112, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 65, 80, 80, 76, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 47, 100, 105, 99, 116, 62, 10, 60, 47, 112, 108, 105, 115, 116, 62}} + 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, 56, 34, 63, 62, 10, 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 112, 108, 105, 115, 116, 32, 80, 85, 66, 76, 73, 67, 32, 34, 45, 47, 47, 65, 112, 112, 108, 101, 32, 67, 111, 109, 112, 117, 116, 101, 114, 47, 47, 68, 84, 68, 32, 80, 76, 73, 83, 84, 32, 49, 46, 48, 47, 47, 69, 78, 34, 32, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 68, 84, 68, 115, 47, 80, 114, 111, 112, 101, 114, 116, 121, 76, 105, 115, 116, 45, 49, 46, 48, 46, 100, 116, 100, 34, 62, 10, 60, 112, 108, 105, 115, 116, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 62, 10, 60, 100, 105, 99, 116, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 78, 97, 109, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 69, 120, 101, 78, 97, 109, 101, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 65, 112, 112, 73, 68, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 99, 111, 110, 70, 105, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 105, 99, 111, 110, 46, 105, 99, 110, 115, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 104, 111, 114, 116, 86, 101, 114, 115, 105, 111, 110, 83, 116, 114, 105, 110, 103, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 86, 101, 114, 115, 105, 111, 110, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 83, 117, 112, 112, 111, 114, 116, 101, 100, 80, 108, 97, 116, 102, 111, 114, 109, 115, 60, 47, 107, 101, 121, 62, 10, 9, 60, 97, 114, 114, 97, 121, 62, 10, 9, 9, 60, 115, 116, 114, 105, 110, 103, 62, 77, 97, 99, 79, 83, 88, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 47, 97, 114, 114, 97, 121, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 66, 117, 105, 108, 100, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 78, 83, 72, 105, 103, 104, 82, 101, 115, 111, 108, 117, 116, 105, 111, 110, 67, 97, 112, 97, 98, 108, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 116, 114, 117, 101, 47, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 73, 110, 102, 111, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 54, 46, 48, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 67, 70, 66, 117, 110, 100, 108, 101, 80, 97, 99, 107, 97, 103, 101, 84, 121, 112, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 65, 80, 80, 76, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 76, 83, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 67, 97, 116, 101, 103, 111, 114, 121, 84, 121, 112, 101, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 112, 117, 98, 108, 105, 99, 46, 97, 112, 112, 45, 99, 97, 116, 101, 103, 111, 114, 121, 46, 123, 123, 46, 67, 97, 116, 101, 103, 111, 114, 121, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 9, 60, 107, 101, 121, 62, 76, 83, 77, 105, 110, 105, 109, 117, 109, 83, 121, 115, 116, 101, 109, 86, 101, 114, 115, 105, 111, 110, 60, 47, 107, 101, 121, 62, 10, 9, 60, 115, 116, 114, 105, 110, 103, 62, 49, 48, 46, 49, 49, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 47, 100, 105, 99, 116, 62, 10, 60, 47, 112, 108, 105, 115, 116, 62}} var resourceMakefile = &fyne.StaticResource{ StaticName: "Makefile", @@ -29,8 +29,13 @@ var resourceAppxmanifestXML = &fyne.StaticResource{ StaticContent: []byte{ 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 117, 116, 102, 45, 56, 34, 63, 62, 10, 60, 80, 97, 99, 107, 97, 103, 101, 32, 120, 109, 108, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 115, 99, 104, 101, 109, 97, 115, 46, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 99, 111, 109, 47, 97, 112, 112, 120, 47, 50, 48, 49, 48, 47, 109, 97, 110, 105, 102, 101, 115, 116, 34, 62, 10, 32, 32, 60, 73, 100, 101, 110, 116, 105, 116, 121, 32, 78, 97, 109, 101, 61, 34, 123, 123, 46, 65, 112, 112, 73, 68, 125, 125, 34, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 86, 101, 114, 115, 105, 111, 110, 61, 34, 123, 123, 46, 86, 101, 114, 115, 105, 111, 110, 125, 125, 34, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 80, 117, 98, 108, 105, 115, 104, 101, 114, 61, 34, 123, 123, 46, 68, 101, 118, 101, 108, 111, 112, 101, 114, 125, 125, 34, 32, 47, 62, 10, 32, 32, 60, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 62, 10, 32, 32, 32, 32, 60, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 62, 123, 123, 46, 78, 97, 109, 101, 125, 125, 60, 47, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 62, 10, 32, 32, 32, 32, 60, 80, 117, 98, 108, 105, 115, 104, 101, 114, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 62, 123, 123, 46, 68, 101, 118, 101, 108, 111, 112, 101, 114, 78, 97, 109, 101, 125, 125, 60, 47, 80, 117, 98, 108, 105, 115, 104, 101, 114, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 62, 10, 32, 32, 32, 32, 60, 76, 111, 103, 111, 62, 73, 99, 111, 110, 46, 112, 110, 103, 60, 47, 76, 111, 103, 111, 62, 10, 32, 32, 60, 47, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 62, 10, 32, 32, 60, 80, 114, 101, 114, 101, 113, 117, 105, 115, 105, 116, 101, 115, 62, 10, 32, 32, 32, 32, 60, 79, 83, 77, 105, 110, 86, 101, 114, 115, 105, 111, 110, 62, 54, 46, 50, 60, 47, 79, 83, 77, 105, 110, 86, 101, 114, 115, 105, 111, 110, 62, 10, 32, 32, 32, 32, 60, 79, 83, 77, 97, 120, 86, 101, 114, 115, 105, 111, 110, 84, 101, 115, 116, 101, 100, 62, 49, 48, 46, 48, 60, 47, 79, 83, 77, 97, 120, 86, 101, 114, 115, 105, 111, 110, 84, 101, 115, 116, 101, 100, 62, 10, 32, 32, 60, 47, 80, 114, 101, 114, 101, 113, 117, 105, 115, 105, 116, 101, 115, 62, 10, 32, 32, 60, 82, 101, 115, 111, 117, 114, 99, 101, 115, 62, 10, 32, 32, 32, 32, 60, 82, 101, 115, 111, 117, 114, 99, 101, 32, 76, 97, 110, 103, 117, 97, 103, 101, 61, 34, 101, 110, 45, 117, 115, 34, 32, 47, 62, 10, 32, 32, 60, 47, 82, 101, 115, 111, 117, 114, 99, 101, 115, 62, 10, 10, 32, 32, 60, 33, 45, 45, 32, 84, 79, 68, 79, 32, 60, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 115, 62, 32, 45, 45, 62, 10, 60, 47, 80, 97, 99, 107, 97, 103, 101, 62}} -var resourceEntitlementsPlist = &fyne.StaticResource{ - StaticName: "entitlements.plist", +var resourceEntitlementsDarwinPlist = &fyne.StaticResource{ + StaticName: "entitlements-darwin.plist", + StaticContent: []byte{ + 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, 56, 34, 63, 62, 10, 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 112, 108, 105, 115, 116, 32, 80, 85, 66, 76, 73, 67, 32, 34, 45, 47, 47, 65, 112, 112, 108, 101, 47, 47, 68, 84, 68, 32, 80, 76, 73, 83, 84, 32, 49, 46, 48, 47, 47, 69, 78, 34, 32, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 68, 84, 68, 115, 47, 80, 114, 111, 112, 101, 114, 116, 121, 76, 105, 115, 116, 45, 49, 46, 48, 46, 100, 116, 100, 34, 62, 10, 60, 112, 108, 105, 115, 116, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 62, 10, 60, 100, 105, 99, 116, 62, 10, 32, 32, 32, 32, 60, 107, 101, 121, 62, 99, 111, 109, 46, 97, 112, 112, 108, 101, 46, 115, 101, 99, 117, 114, 105, 116, 121, 46, 97, 112, 112, 45, 115, 97, 110, 100, 98, 111, 120, 60, 47, 107, 101, 121, 62, 10, 32, 32, 32, 32, 60, 116, 114, 117, 101, 47, 62, 10, 60, 47, 100, 105, 99, 116, 62, 10, 60, 47, 112, 108, 105, 115, 116, 62}} + +var resourceEntitlementsIosPlist = &fyne.StaticResource{ + StaticName: "entitlements-ios.plist", StaticContent: []byte{ 60, 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, 56, 34, 63, 62, 10, 60, 33, 68, 79, 67, 84, 89, 80, 69, 32, 112, 108, 105, 115, 116, 32, 80, 85, 66, 76, 73, 67, 32, 34, 45, 47, 47, 65, 112, 112, 108, 101, 47, 47, 68, 84, 68, 32, 80, 76, 73, 83, 84, 32, 49, 46, 48, 47, 47, 69, 78, 34, 32, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 112, 112, 108, 101, 46, 99, 111, 109, 47, 68, 84, 68, 115, 47, 80, 114, 111, 112, 101, 114, 116, 121, 76, 105, 115, 116, 45, 49, 46, 48, 46, 100, 116, 100, 34, 62, 10, 60, 112, 108, 105, 115, 116, 32, 118, 101, 114, 115, 105, 111, 110, 61, 34, 49, 46, 48, 34, 62, 10, 60, 100, 105, 99, 116, 62, 10, 32, 32, 32, 32, 60, 107, 101, 121, 62, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 45, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 60, 47, 107, 101, 121, 62, 10, 32, 32, 32, 32, 60, 115, 116, 114, 105, 110, 103, 62, 123, 123, 46, 84, 101, 97, 109, 73, 68, 125, 125, 46, 123, 123, 46, 65, 112, 112, 73, 68, 125, 125, 60, 47, 115, 116, 114, 105, 110, 103, 62, 10, 60, 47, 100, 105, 99, 116, 62, 10, 60, 47, 112, 108, 105, 115, 116, 62}} diff --git a/cmd/fyne/internal/templates/data/Info.plist b/cmd/fyne/internal/templates/data/Info.plist index 18ad740985..9109e67737 100644 --- a/cmd/fyne/internal/templates/data/Info.plist +++ b/cmd/fyne/internal/templates/data/Info.plist @@ -24,5 +24,9 @@ 6.0 CFBundlePackageType APPL + LSApplicationCategoryType + public.app-category.{{.Category}} + LSMinimumSystemVersion + 10.11 \ No newline at end of file diff --git a/cmd/fyne/internal/templates/data/entitlements-darwin.plist b/cmd/fyne/internal/templates/data/entitlements-darwin.plist new file mode 100644 index 0000000000..ebc85653fb --- /dev/null +++ b/cmd/fyne/internal/templates/data/entitlements-darwin.plist @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + \ No newline at end of file diff --git a/cmd/fyne/internal/templates/data/entitlements.plist b/cmd/fyne/internal/templates/data/entitlements-ios.plist similarity index 100% rename from cmd/fyne/internal/templates/data/entitlements.plist rename to cmd/fyne/internal/templates/data/entitlements-ios.plist diff --git a/cmd/fyne/internal/templates/templates.go b/cmd/fyne/internal/templates/templates.go index 2ad3d84e98..3bf5756ea7 100644 --- a/cmd/fyne/internal/templates/templates.go +++ b/cmd/fyne/internal/templates/templates.go @@ -12,7 +12,10 @@ var ( DesktopFileUNIX = template.Must(template.New("DesktopFile").Parse(string(resourceAppDesktop.StaticContent))) // EntitlementsDarwin is a plist file that lists build entitlements for darwin releases - EntitlementsDarwin = template.Must(template.New("Entitlements").Parse(string(resourceEntitlementsPlist.StaticContent))) + EntitlementsDarwin = template.Must(template.New("Entitlements").Parse(string(resourceEntitlementsDarwinPlist.StaticContent))) + + // EntitlementsDarwinMobile is a plist file that lists build entitlements for iOS releases + EntitlementsDarwinMobile = template.Must(template.New("EntitlementsMobile").Parse(string(resourceEntitlementsIosPlist.StaticContent))) // ManifestWindows is the manifest file for windows packaging ManifestWindows = template.Must(template.New("Manifest").Parse(string(resourceAppManifest.StaticContent))) @@ -21,7 +24,7 @@ var ( AppxManifestWindows = template.Must(template.New("ReleaseManifest").Parse(string(resourceAppxmanifestXML.StaticContent))) // InfoPlistDarwin is the manifest file for darwin packaging - InfoPlistDarwin = template.Must(template.New("Manifest").Parse(string(resourceInfoPlist.StaticContent))) + InfoPlistDarwin = template.Must(template.New("InfoPlist").Parse(string(resourceInfoPlist.StaticContent))) // XCAssetsDarwin is the Contents.json file for darwin xcassets bundle XCAssetsDarwin = template.Must(template.New("XCAssets").Parse(string(resourceXcassetsJSON.StaticContent))) From ad5bdb51167721489e76a905d9a80c84b7c4d33b Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 10:09:07 +0000 Subject: [PATCH 15/33] Fix static check error --- cmd/fyne/commands/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index 8c6ec18667..660a2c5a7a 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -173,7 +173,7 @@ func (r *releaser) packageIOSRelease() error { func (r *releaser) packageMacOSRelease() error { appCert := r.certificate // try to derive two certificates from one name (they will be consistent) - if strings.Index(appCert, "Installer") != -1 { + if strings.Contains(appCert, "Installer") { appCert = strings.Replace(appCert, "Installer", "Application", 1) } installCert := strings.Replace(appCert, "Application", "Installer", 1) From 8a84b1e288f6b2da773842cd50c65f4492ea2bc9 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 10:44:17 +0000 Subject: [PATCH 16/33] Fix typo --- cmd/fyne/commands/build.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fyne/commands/build.go b/cmd/fyne/commands/build.go index 001f681ed7..500ad4041c 100644 --- a/cmd/fyne/commands/build.go +++ b/cmd/fyne/commands/build.go @@ -38,7 +38,7 @@ func (b *builder) build() error { // handle build tags tags := b.tags if b.release { - args = append(tags, "release") + tags = append(tags, "release") } if len(tags) > 0 { args = append(args, "-tags", strings.Join(tags, ",")) From 99cb61e213a314dbf712c923a636a9db176c6545 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 10:54:19 +0000 Subject: [PATCH 17/33] Apply min macOS version as 10.11 like the app store packaging This suppports most computers sold in the last 12 years and goes beyond Apple support plans. Fixes #886 --- cmd/fyne/commands/build.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/cmd/fyne/commands/build.go b/cmd/fyne/commands/build.go index 500ad4041c..255cb4323d 100644 --- a/cmd/fyne/commands/build.go +++ b/cmd/fyne/commands/build.go @@ -20,18 +20,23 @@ func (b *builder) build() error { goos = targetOS() } - args := []string{} + args := []string{"build"} + env := os.Environ() + env = append(env, "CGO_ENABLED=1") // in case someone is trying to cross-compile... + if goos == "windows" { if b.release { - args = append(args, "build", "-ldflags", "-s -w -H=windowsgui") + args = append(args, "-ldflags", "-s -w -H=windowsgui") } else { - args = append(args, "build", "-ldflags", "-H=windowsgui") + args = append(args, "-ldflags", "-H=windowsgui") } } else { + if goos == "darwin" { + env = append(env, "CGO_CFLAGS=-mmacosx-version-min=10.11") + env = append(env, "CGO_LDFLAGS=-mmacosx-version-min=10.11") + } if b.release { - args = append(args, "build", "-ldflags", "-s -w") - } else { - args = append(args, "build") + args = append(args, "-ldflags", "-s -w") } } @@ -46,9 +51,6 @@ func (b *builder) build() error { cmd := exec.Command("go", args...) cmd.Dir = b.srcdir - env := os.Environ() - env = append(env, "CGO_ENABLED=1") // in case someone is trying to cross-compile... - if goos != "ios" && goos != "android" { env = append(env, "GOOS="+goos) } From 786799f41fe99108b93cb47bae2c42501bffdd2b Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 14:48:26 +0000 Subject: [PATCH 18/33] Fix deprecations --- dialog/color.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dialog/color.go b/dialog/color.go index 667353e4ad..d61c74d423 100644 --- a/dialog/color.go +++ b/dialog/color.go @@ -21,7 +21,7 @@ type ColorPickerDialog struct { Advanced bool color color.Color callback func(c color.Color) - advanced *widget.AccordionContainer + advanced *widget.Accordion picker *colorAdvancedPicker } @@ -94,7 +94,7 @@ func (p *ColorPickerDialog) updateUI() { p.picker = newColorAdvancedPicker(p.color, func(c color.Color) { p.color = c }) - p.advanced = widget.NewAccordionContainer(widget.NewAccordionItem("Advanced", p.picker)) + p.advanced = widget.NewAccordion(widget.NewAccordionItem("Advanced", p.picker)) p.dialog.content = fyne.NewContainerWithLayout(layout.NewVBoxLayout(), fyne.NewContainerWithLayout(layout.NewCenterLayout(), From 4acd7036ad9d5b82ed45c891c548667f601478b4 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 14:51:05 +0000 Subject: [PATCH 19/33] Fix issue where dialog shadows may not resize The inner size was not updated when our content forced it to. We cannot override it or it won't shrink again, so this fixes the calculation for shadow size. Fixes #1370 --- CHANGELOG.md | 1 + .../color/dialog_expanded_theme_dark.png | Bin 37891 -> 37960 bytes .../color/dialog_expanded_theme_light.png | Bin 38289 -> 38396 bytes widget/popup.go | 6 ++++-- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0ad3fd1f5..20a4f21789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ More detailed release notes can be found on the [releases page](https://github.c * [fyne-cli] Android: allow to specify an inline password for the keystore * Fixed Card widget MinSize (#1581) * Fix missing release tag to enable BuildRelease in Settings.BuildType() +* Dialog shadow does not resize after Refresh (#1370) ## 1.4.1 - 20 November 2020 diff --git a/dialog/testdata/color/dialog_expanded_theme_dark.png b/dialog/testdata/color/dialog_expanded_theme_dark.png index f4c13bc88a19c4e6d6df9aa4e1a6d6ea17fc9424..30ba402f4ccc110cc7af63c9fb940e020fa4d3d7 100644 GIT binary patch literal 37960 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 literal 37891 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 diff --git a/dialog/testdata/color/dialog_expanded_theme_light.png b/dialog/testdata/color/dialog_expanded_theme_light.png index 332c3e761b73f34a34e8396a88748c91b88e3bce..710f97fc6d36b082824c24ee27df7245135a4d36 100644 GIT binary patch literal 38396 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 AJpcdz literal 38289 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 diff --git a/widget/popup.go b/widget/popup.go index cbdeffe67a..ac6b58d26d 100644 --- a/widget/popup.go +++ b/widget/popup.go @@ -232,7 +232,9 @@ type modalPopUpRenderer struct { func (r *modalPopUpRenderer) Layout(canvasSize fyne.Size) { padding := r.padding() - requestedSize := r.popUp.innerSize.Subtract(padding) + innerSize := r.popUp.innerSize.Max(r.popUp.Content.MinSize().Add(padding)) + + requestedSize := innerSize.Subtract(padding) size := r.popUp.Content.MinSize().Max(requestedSize) size = size.Min(canvasSize.Subtract(padding)) pos := fyne.NewPos((canvasSize.Width-size.Width)/2, (canvasSize.Height-size.Height)/2) @@ -242,7 +244,7 @@ func (r *modalPopUpRenderer) Layout(canvasSize fyne.Size) { innerPos := pos.Subtract(r.offset()) r.bg.Move(innerPos) r.bg.Resize(size.Add(padding)) - r.LayoutShadow(r.popUp.innerSize, innerPos) + r.LayoutShadow(innerSize, innerPos) } func (r *modalPopUpRenderer) MinSize() fyne.Size { From 5cf917f7d663febee6051c098412698223d76b87 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 15:58:08 +0000 Subject: [PATCH 20/33] Pull GBoard android fix from mobile driver Fixes #1256 --- CHANGELOG.md | 1 + go.mod | 2 +- go.sum | 4 ++-- vendor/github.com/fyne-io/mobile/app/android.go | 3 +++ vendor/modules.txt | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20a4f21789..7e568e94e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Fixed Card widget MinSize (#1581) * Fix missing release tag to enable BuildRelease in Settings.BuildType() * Dialog shadow does not resize after Refresh (#1370) +* Android Duplicate Number Entry (#1256) ## 1.4.1 - 20 November 2020 diff --git a/go.mod b/go.mod index de56ba37b2..ce997d0010 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/akavel/rsrc v0.8.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.4.9 - github.com/fyne-io/mobile v0.1.1 + github.com/fyne-io/mobile v0.1.2-0.20201127155338-06aeb98410cc github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 github.com/godbus/dbus/v5 v5.0.3 diff --git a/go.sum b/go.sum index 67a15c4d9b..9271298b02 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d h1:WfVxpuVm+5Gr3ipAoWrxV8lJFYkaBWoEwFRrWThWRSU= github.com/fyne-io/glfw/v3.3/glfw v0.0.0-20201123143003-f2279069162d/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/fyne-io/mobile v0.1.1 h1:Snu9tKaVgu81314egPeqMC09z/k4D/bts0n1O2MfPbk= -github.com/fyne-io/mobile v0.1.1/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY= +github.com/fyne-io/mobile v0.1.2-0.20201127155338-06aeb98410cc h1:oNo/EXJa9DurC8zmzWDzBCUV3R/b03SWCW/Qftmgpb0= +github.com/fyne-io/mobile v0.1.2-0.20201127155338-06aeb98410cc/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= diff --git a/vendor/github.com/fyne-io/mobile/app/android.go b/vendor/github.com/fyne-io/mobile/app/android.go index 4592a140a1..742dfff54b 100644 --- a/vendor/github.com/fyne-io/mobile/app/android.go +++ b/vendor/github.com/fyne-io/mobile/app/android.go @@ -545,6 +545,9 @@ func processKey(env *C.JNIEnv, e *C.AInputEvent) { Rune: rune(C.getKeyRune(env, e)), Code: convAndroidKeyCode(int32(C.AKeyEvent_getKeyCode(e))), } + if k.Rune >= '0' && k.Rune <= '9' { // GBoard generates key events for numbers, but we see them in textChanged + return + } switch C.AKeyEvent_getAction(e) { case C.AKEY_STATE_DOWN: k.Direction = key.DirPress diff --git a/vendor/modules.txt b/vendor/modules.txt index 18f4ba17be..7ae636741b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -8,7 +8,7 @@ github.com/akavel/rsrc/ico github.com/davecgh/go-spew/spew # github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify -# github.com/fyne-io/mobile v0.1.1 +# github.com/fyne-io/mobile v0.1.2-0.20201127155338-06aeb98410cc github.com/fyne-io/mobile/app github.com/fyne-io/mobile/app/internal/callfn github.com/fyne-io/mobile/event/key From 392a0647d45670382f82b954ef49be065eec927b Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 17:56:14 +0000 Subject: [PATCH 21/33] Updaet changelog for recent merges --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e568e94e7..848b81f109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ More detailed release notes can be found on the [releases page](https://github.c * Fix missing release tag to enable BuildRelease in Settings.BuildType() * Dialog shadow does not resize after Refresh (#1370) * Android Duplicate Number Entry (#1256) +* Support older macOS by default - back to 10.11 (#886) +* Complete certification of macOS App Store releases (#1443) +* Fix compilation errors for early stage Wayland testing ## 1.4.1 - 20 November 2020 From f9f91c1947370189c73384fb12ee799b1cf68638 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 27 Nov 2020 18:07:16 +0000 Subject: [PATCH 22/33] Fix typo on category help text --- cmd/fyne/commands/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fyne/commands/release.go b/cmd/fyne/commands/release.go index 660a2c5a7a..c8f1501367 100644 --- a/cmd/fyne/commands/release.go +++ b/cmd/fyne/commands/release.go @@ -59,7 +59,7 @@ func (r *releaser) AddFlags() { flag.StringVar(&r.developer, "developer", "", "Windows: the developer identity for your Microsoft store account") flag.StringVar(&r.password, "password", "", "Windows: password for the certificate used to sign the build") flag.StringVar(&r.tags, "tags", "", "A comma-separated list of build tags") - flag.StringVar(&r.category, "category", "", "iOS: category of the app for store listing") + flag.StringVar(&r.category, "category", "", "macOS: category of the app for store listing") } func (r *releaser) PrintHelp(indent string) { From 15bff22dd8095896f567a9785d6aaba237758f90 Mon Sep 17 00:00:00 2001 From: Stuart Scott Date: Tue, 1 Dec 2020 11:08:56 -0800 Subject: [PATCH 23/33] Ensure Collections calculate MinSize consistently (#1620) * Ensure Collections calculate MinSize consistently * Fix list test * More MinSize tests * Add selection indicator to table minsize * Add column selection indicator to table minsize --- widget/list.go | 2 +- widget/list_test.go | 32 +++++++++++++++++++++- widget/table.go | 2 +- widget/table_test.go | 28 ++++++++++++++++++++ widget/tree_internal_test.go | 51 +++++++++++++++++++++++++++--------- 5 files changed, 100 insertions(+), 15 deletions(-) diff --git a/widget/list.go b/widget/list.go index 129ab8a4a2..6485a6a531 100644 --- a/widget/list.go +++ b/widget/list.go @@ -215,7 +215,7 @@ func (l *listRenderer) Layout(size fyne.Size) { } func (l *listRenderer) MinSize() fyne.Size { - return l.scroller.MinSize() + return l.scroller.MinSize().Max(l.list.itemMin) } func (l *listRenderer) Refresh() { diff --git a/widget/list_test.go b/widget/list_test.go index 65b0bea70b..5cdd8f0538 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -2,11 +2,13 @@ package widget import ( "fmt" + "image/color" "math" "testing" "time" "fyne.io/fyne" + "fyne.io/fyne/canvas" "fyne.io/fyne/driver/desktop" "fyne.io/fyne/layout" "fyne.io/fyne/test" @@ -24,11 +26,39 @@ func TestNewList(t *testing.T) { assert.Equal(t, 1000, list.Length()) assert.GreaterOrEqual(t, list.MinSize().Width, template.MinSize().Width) - assert.Equal(t, list.MinSize(), test.WidgetRenderer(list).(*listRenderer).scroller.MinSize()) + assert.Equal(t, list.MinSize(), template.MinSize().Max(test.WidgetRenderer(list).(*listRenderer).scroller.MinSize())) assert.Equal(t, 0, firstItemIndex) assert.Equal(t, visibleCount, lastItemIndex-firstItemIndex+1) } +func TestList_MinSize(t *testing.T) { + for name, tt := range map[string]struct { + cellSize fyne.Size + expectedMinSize fyne.Size + }{ + "small": { + fyne.NewSize(1, 1), + fyne.NewSize(scrollContainerMinSize, scrollContainerMinSize), + }, + "large": { + fyne.NewSize(100, 100), + fyne.NewSize(100+3*theme.Padding(), 100+2*theme.Padding()), + }, + } { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tt.expectedMinSize, NewList( + func() int { return 5 }, + func() fyne.CanvasObject { + r := canvas.NewRectangle(color.Black) + r.SetMinSize(tt.cellSize) + r.Resize(tt.cellSize) + return r + }, + func(ListItemID, fyne.CanvasObject) {}).MinSize()) + }) + } +} + func TestList_Resize(t *testing.T) { list := createList(1000) w := test.NewWindow(list) diff --git a/widget/table.go b/widget/table.go index d7f83b0d0d..05d3269f81 100644 --- a/widget/table.go +++ b/widget/table.go @@ -246,7 +246,7 @@ func (t *tableRenderer) Layout(s fyne.Size) { } func (t *tableRenderer) MinSize() fyne.Size { - return t.cellSize + return t.t.scroll.MinSize().Max(t.cellSize.Add(fyne.NewSize(theme.Padding(), theme.Padding()))) } func (t *tableRenderer) Refresh() { diff --git a/widget/table_test.go b/widget/table_test.go index a5e869f4b7..bc3df9c3dc 100644 --- a/widget/table_test.go +++ b/widget/table_test.go @@ -102,6 +102,34 @@ func TestTable_Filled(t *testing.T) { test.AssertImageMatches(t, "table/filled.png", w.Canvas().Capture()) } +func TestTable_MinSize(t *testing.T) { + for name, tt := range map[string]struct { + cellSize fyne.Size + expectedMinSize fyne.Size + }{ + "small": { + fyne.NewSize(1, 1), + fyne.NewSize(scrollContainerMinSize, scrollContainerMinSize), + }, + "large": { + fyne.NewSize(100, 100), + fyne.NewSize(100+3*theme.Padding(), 100+3*theme.Padding()), + }, + } { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tt.expectedMinSize, NewTable( + func() (int, int) { return 5, 5 }, + func() fyne.CanvasObject { + r := canvas.NewRectangle(color.Black) + r.SetMinSize(tt.cellSize) + r.Resize(tt.cellSize) + return r + }, + func(TableCellID, fyne.CanvasObject) {}).MinSize()) + }) + } +} + func TestTable_Unselect(t *testing.T) { app := test.NewApp() defer test.NewApp() diff --git a/widget/tree_internal_test.go b/widget/tree_internal_test.go index 63a040672f..1b7e93b9e3 100644 --- a/widget/tree_internal_test.go +++ b/widget/tree_internal_test.go @@ -1,10 +1,12 @@ package widget import ( + "image/color" "testing" "time" "fyne.io/fyne" + "fyne.io/fyne/canvas" "fyne.io/fyne/driver/desktop" "fyne.io/fyne/internal/widget" "fyne.io/fyne/test" @@ -221,22 +223,47 @@ func TestTree_MinSize(t *testing.T) { t.Run("Default", func(t *testing.T) { tree := &Tree{} min := tree.MinSize() - assert.Equal(t, 32, min.Width) - assert.Equal(t, 32, min.Height) + assert.Equal(t, scrollContainerMinSize, min.Width) + assert.Equal(t, scrollContainerMinSize, min.Height) }) t.Run("Callback", func(t *testing.T) { - tree := &Tree{ - CreateNode: func(isBranch bool) fyne.CanvasObject { - if isBranch { - return NewLabel("Branch") - } - return NewLabel("Leaf") + for name, tt := range map[string]struct { + leafSize fyne.Size + branchSize fyne.Size + expectedMinSize fyne.Size + }{ + "small": { + fyne.NewSize(1, 1), + fyne.NewSize(1, 1), + fyne.NewSize(fyne.Max(1+3*theme.Padding()+theme.IconInlineSize(), scrollContainerMinSize), scrollContainerMinSize), + }, + "large-leaf": { + fyne.NewSize(100, 100), + fyne.NewSize(1, 1), + fyne.NewSize(100+3*theme.Padding()+theme.IconInlineSize(), 100+2*theme.Padding()), + }, + "large-branch": { + fyne.NewSize(1, 1), + fyne.NewSize(100, 100), + fyne.NewSize(100+3*theme.Padding()+theme.IconInlineSize(), 100+2*theme.Padding()), }, + } { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tt.expectedMinSize, (&Tree{ + CreateNode: func(isBranch bool) fyne.CanvasObject { + r := canvas.NewRectangle(color.Black) + if isBranch { + r.SetMinSize(tt.branchSize) + r.Resize(tt.branchSize) + } else { + r.SetMinSize(tt.leafSize) + r.Resize(tt.leafSize) + } + return r + }, + }).MinSize()) + }) } - tMin := tree.MinSize() - bMin := newBranch(tree, NewLabel("Branch")).MinSize() - assert.Equal(t, fyne.Max(32, bMin.Width), tMin.Width) - assert.Equal(t, fyne.Max(32, bMin.Height), tMin.Height) }) for name, tt := range map[string]struct { From 71569e6c5320805b882689da48d2ec92f9763027 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 4 Dec 2020 15:53:30 +0000 Subject: [PATCH 24/33] Attempt github actions fix --- .github/workflows/static_analysis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index bdda915d11..036ee12ab3 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -13,6 +13,7 @@ jobs: - name: Get dependencies run: | + sudo apt-get update sudo apt-get install golang gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev GO111MODULE=off go get golang.org/x/tools/cmd/goimports GO111MODULE=off go get github.com/fzipp/gocyclo/cmd/gocyclo From 3d2b577bf86f1a3ba3bb96dfa743fea33bcf4f9a Mon Sep 17 00:00:00 2001 From: Jacalz Date: Fri, 27 Nov 2020 21:50:00 +0100 Subject: [PATCH 25/33] Fix entry.SetOnValidationChanged() --- CHANGELOG.md | 6 ++++++ widget/entry.go | 23 ++++++++++++----------- widget/entry_validation.go | 10 +++++++--- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 848b81f109..e63d47ad89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ More detailed release notes can be found on the [releases page](https://github.c * [fyne-cli] Add support for passing custom build tags (#1538) +### Changed + +* Run validation on content change instead of on each Refresh in widget.Entry +* Run onValidationChanged() when calling entry.SetValidationError() + ### Fixed * [fyne-cli] Android: allow to specify an inline password for the keystore @@ -19,6 +24,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Support older macOS by default - back to 10.11 (#886) * Complete certification of macOS App Store releases (#1443) * Fix compilation errors for early stage Wayland testing +* Fix entry.SetValidationError() not working correctly ## 1.4.1 - 20 November 2020 diff --git a/widget/entry.go b/widget/entry.go index 4ba9b31c32..e50e8d81da 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -999,6 +999,18 @@ func (e *Entry) updateText(text string) { } }) + if validate := e.Validator; validate != nil { + if err := validate(text); err != e.validationError { + e.validationError = err + + if f := e.onValidationChanged; f != nil { + f(err) + } + } + + e.validationStatus.Refresh() + } + if callback != nil { callback(text) } @@ -1135,21 +1147,10 @@ func (r *entryRenderer) Refresh() { } if r.entry.Validator != nil { - err := r.entry.Validator(content) - if err != r.entry.validationError { - r.entry.validationError = err - - if f := r.entry.onValidationChanged; f != nil { - f(err) - } - } - if !r.entry.focused && r.entry.Text != "" && r.entry.validationError != nil { r.line.FillColor = &color.NRGBA{0xf4, 0x43, 0x36, 0xff} // TODO: Should be current().ErrorColor() in the future } - r.ensureValidationSetup() - r.entry.validationStatus.Refresh() } else if r.entry.validationStatus != nil { r.entry.validationStatus.Hide() diff --git a/widget/entry_validation.go b/widget/entry_validation.go index 99b07454ec..b44f6eadc7 100644 --- a/widget/entry_validation.go +++ b/widget/entry_validation.go @@ -29,10 +29,15 @@ func (e *Entry) SetOnValidationChanged(callback func(error)) { // SetValidationError manually updates the validation status until the next input change func (e *Entry) SetValidationError(err error) { e.validationError = err + if e.Validator == nil { + return + } - if e.Validator != nil { - e.validationStatus.Refresh() + if err != e.validationError && e.onValidationChanged != nil { + e.onValidationChanged(err) } + + e.validationStatus.Refresh() } var _ fyne.Widget = (*validationStatus)(nil) @@ -83,7 +88,6 @@ func (r *validationStatusRenderer) Refresh() { defer r.entry.propertyLock.RUnlock() if r.entry.Text == "" { r.icon.Hide() - canvas.Refresh(r.icon) return } From 77a88af241b77b0efd6efd8b6591c197047c27d5 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Fri, 4 Dec 2020 15:55:10 +0100 Subject: [PATCH 26/33] Fixes to make sure that state is updated correctly --- widget/entry.go | 10 +--------- widget/entry_validation.go | 6 ++++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/widget/entry.go b/widget/entry.go index e50e8d81da..1a8d7512e6 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -1000,15 +1000,7 @@ func (e *Entry) updateText(text string) { }) if validate := e.Validator; validate != nil { - if err := validate(text); err != e.validationError { - e.validationError = err - - if f := e.onValidationChanged; f != nil { - f(err) - } - } - - e.validationStatus.Refresh() + e.SetValidationError(validate(text)) } if callback != nil { diff --git a/widget/entry_validation.go b/widget/entry_validation.go index b44f6eadc7..5bab0fb637 100644 --- a/widget/entry_validation.go +++ b/widget/entry_validation.go @@ -15,7 +15,9 @@ func (e *Entry) Validate() error { return nil } - return e.Validator(e.Text) + err := e.Validator(e.Text) + e.SetValidationError(err) + return err } // SetOnValidationChanged is intended for parent widgets or containers to hook into the validation. @@ -28,7 +30,6 @@ func (e *Entry) SetOnValidationChanged(callback func(error)) { // SetValidationError manually updates the validation status until the next input change func (e *Entry) SetValidationError(err error) { - e.validationError = err if e.Validator == nil { return } @@ -37,6 +38,7 @@ func (e *Entry) SetValidationError(err error) { e.onValidationChanged(err) } + e.validationError = err e.validationStatus.Refresh() } From faa5d9c6a52d68caec402e7e66c4c7c72bc7cc06 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Fri, 4 Dec 2020 17:04:32 +0100 Subject: [PATCH 27/33] Remove unnecessary line in changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e63d47ad89..94e3301ac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,6 @@ More detailed release notes can be found on the [releases page](https://github.c ### Changed * Run validation on content change instead of on each Refresh in widget.Entry -* Run onValidationChanged() when calling entry.SetValidationError() ### Fixed From 8f33697cf6117da329412c6614e188fa55423b85 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 4 Dec 2020 17:14:45 +0000 Subject: [PATCH 28/33] Release prep for 1.4.2 --- CHANGELOG.md | 2 +- README.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94e3301ac3..5c7d167a37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 1.4.2 - Ongoing +## 1.4.2 - 8 December 2020 ### Added diff --git a/README.md b/README.md index 7a05e685e8..7baed0170b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@

Go API Reference - 1.4.1 release + 1.4.2 release Join us on Slack
Code Status Build Status + Build Status Coverage Status

From 2ff4cc2fc878641958a6c23ad57bce1a5c30ae64 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 5 Dec 2020 19:46:41 +0100 Subject: [PATCH 29/33] Refresh entry on SetValidationError() --- widget/entry_test.go | 20 ---- widget/entry_validation.go | 2 +- widget/entry_validation_test.go | 91 ++++++++++++++++++ .../testdata/entry/validation_set_invalid.png | Bin 0 -> 2849 bytes .../testdata/entry/validation_set_valid.png | Bin 0 -> 2565 bytes 5 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 widget/entry_validation_test.go create mode 100644 widget/testdata/entry/validation_set_invalid.png create mode 100644 widget/testdata/entry/validation_set_valid.png diff --git a/widget/entry_test.go b/widget/entry_test.go index 56ba07d2ab..798fd34995 100644 --- a/widget/entry_test.go +++ b/widget/entry_test.go @@ -6,7 +6,6 @@ import ( "fyne.io/fyne" "fyne.io/fyne/canvas" - "fyne.io/fyne/data/validation" "fyne.io/fyne/driver/desktop" "fyne.io/fyne/test" "fyne.io/fyne/theme" @@ -1383,25 +1382,6 @@ func TestEntry_TextWrap(t *testing.T) { } } -func TestEntry_ValidatedEntry(t *testing.T) { - entry, window := setupImageTest(false) - defer teardownImageTest(window) - c := window.Canvas() - - r := validation.NewRegexp(`^\d{4}-\d{2}-\d{2}`, "Input is not a valid date") - entry.Validator = r - test.AssertImageMatches(t, "entry/validate_initial.png", c.Capture()) - - test.Type(entry, "2020-02") - assert.Error(t, r(entry.Text)) - entry.FocusLost() - test.AssertImageMatches(t, "entry/validate_invalid.png", c.Capture()) - - test.Type(entry, "-12") - assert.NoError(t, r(entry.Text)) - test.AssertImageMatches(t, "entry/validate_valid.png", c.Capture()) -} - func TestMultiLineEntry_MinSize(t *testing.T) { entry := widget.NewEntry() singleMin := entry.MinSize() diff --git a/widget/entry_validation.go b/widget/entry_validation.go index 5bab0fb637..e06762decd 100644 --- a/widget/entry_validation.go +++ b/widget/entry_validation.go @@ -39,7 +39,7 @@ func (e *Entry) SetValidationError(err error) { } e.validationError = err - e.validationStatus.Refresh() + e.Refresh() } var _ fyne.Widget = (*validationStatus)(nil) diff --git a/widget/entry_validation_test.go b/widget/entry_validation_test.go new file mode 100644 index 0000000000..8582ce272c --- /dev/null +++ b/widget/entry_validation_test.go @@ -0,0 +1,91 @@ +package widget_test + +import ( + "errors" + "testing" + + "fyne.io/fyne/data/validation" + "fyne.io/fyne/test" + "fyne.io/fyne/widget" + + "github.com/stretchr/testify/assert" +) + +var validator = validation.NewRegexp(`^\d{4}-\d{2}-\d{2}$`, "Input is not a valid date") + +func TestEntry_Validated(t *testing.T) { + entry, window := setupImageTest(false) + defer teardownImageTest(window) + c := window.Canvas() + + entry.Validator = validator + test.AssertImageMatches(t, "entry/validate_initial.png", c.Capture()) + + test.Type(entry, "2020-02") + assert.Error(t, entry.Validator(entry.Text)) + entry.FocusLost() + test.AssertImageMatches(t, "entry/validate_invalid.png", c.Capture()) + + test.Type(entry, "-12") + assert.NoError(t, entry.Validator(entry.Text)) + test.AssertImageMatches(t, "entry/validate_valid.png", c.Capture()) +} + +func TestEntry_Validate(t *testing.T) { + entry := widget.NewEntry() + entry.Validator = validator + + test.Type(entry, "2020-02") + assert.Error(t, entry.Validate()) + assert.Equal(t, entry.Validate(), entry.Validator(entry.Text)) + + test.Type(entry, "-12") + assert.NoError(t, entry.Validate()) + assert.Equal(t, entry.Validate(), entry.Validator(entry.Text)) + + entry.SetText("incorrect") + assert.Error(t, entry.Validate()) + assert.Equal(t, entry.Validate(), entry.Validator(entry.Text)) +} + +func TestEntry_SetValidationError(t *testing.T) { + entry, window := setupImageTest(false) + defer teardownImageTest(window) + c := window.Canvas() + + entry.Validator = validator + + entry.SetText("2020-30-30") + entry.SetValidationError(errors.New("Forced to be incorrect")) + test.AssertImageMatches(t, "entry/validation_set_invalid.png", c.Capture()) + + entry.SetText("forced to be valid") + entry.SetValidationError(nil) + test.AssertImageMatches(t, "entry/validation_set_valid.png", c.Capture()) +} + +func TestEntry_SetOnValidationChanged(t *testing.T) { + entry := widget.NewEntry() + entry.Validator = validator + + modified := false + entry.SetOnValidationChanged(func(err error) { + if entry.Text != "18:00" { + assert.Equal(t, err, entry.Validator(entry.Text)) + } + + modified = true + }) + + entry.SetText("2020") + assert.True(t, modified) + + modified = false + test.Type(entry, "-01-01") + assert.True(t, modified) + + modified = false + entry.SetText("18:00") + entry.SetValidationError(nil) + assert.True(t, modified) +} diff --git a/widget/testdata/entry/validation_set_invalid.png b/widget/testdata/entry/validation_set_invalid.png new file mode 100644 index 0000000000000000000000000000000000000000..b0ba095e7cd1ab339e76382a7eb413ff4515aebc GIT binary patch literal 2849 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 C4g-S# literal 0 HcmV?d00001 From 18271e5704b27c5880d25dd9f7efb7f3572e046d Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 5 Dec 2020 19:59:27 +0100 Subject: [PATCH 30/33] Simplify one of the tests --- widget/entry_validation_test.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/widget/entry_validation_test.go b/widget/entry_validation_test.go index 8582ce272c..28bd674440 100644 --- a/widget/entry_validation_test.go +++ b/widget/entry_validation_test.go @@ -70,10 +70,7 @@ func TestEntry_SetOnValidationChanged(t *testing.T) { modified := false entry.SetOnValidationChanged(func(err error) { - if entry.Text != "18:00" { - assert.Equal(t, err, entry.Validator(entry.Text)) - } - + assert.Equal(t, err, entry.Validator(entry.Text)) modified = true }) @@ -83,9 +80,4 @@ func TestEntry_SetOnValidationChanged(t *testing.T) { modified = false test.Type(entry, "-01-01") assert.True(t, modified) - - modified = false - entry.SetText("18:00") - entry.SetValidationError(nil) - assert.True(t, modified) } From e61cf15a4816d2e845937b0bb4fc132dc15ade58 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 5 Dec 2020 22:04:57 +0100 Subject: [PATCH 31/33] Change image text to not overflow --- widget/entry_validation_test.go | 4 ++-- .../testdata/entry/validation_set_valid.png | Bin 2565 -> 1985 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widget/entry_validation_test.go b/widget/entry_validation_test.go index 28bd674440..b4b0638082 100644 --- a/widget/entry_validation_test.go +++ b/widget/entry_validation_test.go @@ -56,10 +56,10 @@ func TestEntry_SetValidationError(t *testing.T) { entry.Validator = validator entry.SetText("2020-30-30") - entry.SetValidationError(errors.New("Forced to be incorrect")) + entry.SetValidationError(errors.New("set invalid")) test.AssertImageMatches(t, "entry/validation_set_invalid.png", c.Capture()) - entry.SetText("forced to be valid") + entry.SetText("set valid") entry.SetValidationError(nil) test.AssertImageMatches(t, "entry/validation_set_valid.png", c.Capture()) } diff --git a/widget/testdata/entry/validation_set_valid.png b/widget/testdata/entry/validation_set_valid.png index 7de76204239fce528260c0ecbc8d962bbcb4b9ed..5eb678d1b9a942802ab5fc471646c92252cc3f49 100644 GIT binary patch literal 1985 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 C4g-S# From a2af54f4e645dda3cbe07cc1ba11b3674860bb10 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 5 Dec 2020 21:53:54 +0000 Subject: [PATCH 32/33] Let's get rid of Travis mentions --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 7baed0170b..073e07510c 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,8 @@ Join us on Slack
Code Status - Build Status - Build Status + Build Status Coverage Status -

# About From 7489e4a63f01e9cbc1edf103b61e1543c10f389f Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 5 Dec 2020 22:12:04 +0000 Subject: [PATCH 33/33] Let's try again for release vote --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c7d167a37..49f33f75ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 1.4.2 - 8 December 2020 +## 1.4.2 - 9 December 2020 ### Added