5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 03:40:12 +08:00

Make draggable CSS property customisable (#1828)

Co-authored-by: stffabi <stffabi@users.noreply.github.com>
This commit is contained in:
Lea Anthony 2022-09-10 14:33:35 +10:00 committed by GitHub
parent ec0e1cca58
commit d23108a49e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1424 additions and 196 deletions

View File

@ -291,11 +291,8 @@ func (f *Frontend) processMessage(message string) {
} }
if message == "runtime:ready" { if message == "runtime:ready" {
if f.frontendOptions.Experimental != nil { cmd := fmt.Sprintf("window.wails.setCSSDragProperties('%s', '%s');", f.frontendOptions.CSSDragProperty, f.frontendOptions.CSSDragValue)
if f.frontendOptions.Experimental.UseCSSDrag { f.ExecJS(cmd)
f.ExecJS(`window.wails.useCSSDrag();`)
}
}
return return
} }

View File

@ -292,11 +292,8 @@ func (f *Frontend) processMessage(message string) {
} }
if message == "runtime:ready" { if message == "runtime:ready" {
if f.frontendOptions.Experimental != nil { cmd := fmt.Sprintf("window.wails.setCSSDragProperties('%s', '%s');", f.frontendOptions.CSSDragProperty, f.frontendOptions.CSSDragValue)
if f.frontendOptions.Experimental.UseCSSDrag { f.ExecJS(cmd)
f.ExecJS(`window.wails.useCSSDrag();`)
}
}
return return
} }

View File

@ -547,11 +547,8 @@ func (f *Frontend) processMessage(message string) {
} }
if message == "runtime:ready" { if message == "runtime:ready" {
if f.frontendOptions.Experimental != nil { cmd := fmt.Sprintf("window.wails.setCSSDragProperties('%s', '%s');", f.frontendOptions.CSSDragProperty, f.frontendOptions.CSSDragValue)
if f.frontendOptions.Experimental.UseCSSDrag { f.ExecJS(cmd)
f.ExecJS(`window.wails.useCSSDrag();`)
}
}
return return
} }

View File

@ -63,7 +63,9 @@ window.wails = {
enableResize: false, enableResize: false,
defaultCursor: null, defaultCursor: null,
borderThickness: 6, borderThickness: 6,
shouldDrag: false shouldDrag: false,
cssDragProperty: "--wails-draggable",
cssDragValue: "drag",
} }
}; };
@ -82,38 +84,14 @@ window.addEventListener('mouseup', () => {
window.wails.flags.shouldDrag = false; window.wails.flags.shouldDrag = false;
}); });
let cssDragTest = function (e) { let dragTest = function (e) {
return window.getComputedStyle(e.target).getPropertyValue('--wails-draggable') === "drag"; return window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty) === window.wails.flags.cssDragValue;
}; };
// Element drag handler window.wails.setCSSDragProperties = function(property, value) {
// Based on code from: https://github.com/patr0nus/DeskGap window.wails.flags.cssDragProperty = property;
let elementDragTest = function (e) { window.wails.flags.cssDragValue = value;
// Check for dragging
let currentElement = e.target;
while (currentElement != null) {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
return true;
} }
currentElement = currentElement.parentElement;
}
return false;
};
let dragTest = elementDragTest;
window.wails.useCSSDrag = function (t) {
if (t === false) {
console.log("Using original drag detection");
dragTest = elementDragTest;
} else {
console.log("Using CSS drag detection");
dragTest = cssDragTest;
}
};
window.addEventListener('mousedown', (e) => { window.addEventListener('mousedown', (e) => {

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
"author": "Lea Anthony <lea.anthony@gmail.com>", "author": "Lea Anthony <lea.anthony@gmail.com>",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"esbuild": "^0.15.3", "esbuild": "^0.15.6",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"svelte": "^3.49.0" "svelte": "^3.49.0"
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,8 @@ var Default = &App{
Logger: logger.NewDefaultLogger(), Logger: logger.NewDefaultLogger(),
LogLevel: logger.INFO, LogLevel: logger.INFO,
LogLevelProduction: logger.ERROR, LogLevelProduction: logger.ERROR,
CSSDragProperty: "--wails-draggable",
CSSDragValue: "drag",
} }
var defaultMacMenu = menu.NewMenuFromItems( var defaultMacMenu = menu.NewMenuFromItems(

View File

@ -2,6 +2,7 @@ package options
import ( import (
"context" "context"
"html"
"io/fs" "io/fs"
"log" "log"
"net/http" "net/http"
@ -27,10 +28,6 @@ const (
) )
type Experimental struct { type Experimental struct {
// UseCSSDrag uses the `--wails-draggable` CSS variable to indicate drag regions
// Add `style="--wails-draggable:drag"` to your draggable elements
// `style="--wails-draggable:no-drag"` will disable dragging for that element + children
UseCSSDrag bool
} }
// App contains options for creating the App // App contains options for creating the App
@ -66,8 +63,12 @@ type App struct {
Bind []interface{} Bind []interface{}
WindowStartState WindowStartState WindowStartState WindowStartState
//ContextMenus []*menu.ContextMenu // CSS property to test for draggable elements. Default "--wails-draggable"
//TrayMenus []*menu.TrayMenu CSSDragProperty string
// The CSS Value that the CSSDragProperty must have to be draggable, EG: "drag"
CSSDragValue string
Windows *windows.Options Windows *windows.Options
Mac *mac.Options Mac *mac.Options
Linux *linux.Options Linux *linux.Options
@ -105,6 +106,8 @@ func NewRGB(r, g, b uint8) *RGBA {
// MergeDefaults will set the minimum default values for an application // MergeDefaults will set the minimum default values for an application
func MergeDefaults(appoptions *App) { func MergeDefaults(appoptions *App) {
// Do default merge
err := mergo.Merge(appoptions, Default) err := mergo.Merge(appoptions, Default)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -121,6 +124,25 @@ func MergeDefaults(appoptions *App) {
} }
// Ensure max and min are valid // Ensure max and min are valid
processMinMaxConstraints(appoptions)
// Default menus
processMenus(appoptions)
// Process Drag Options
processDragOptions(appoptions)
}
func processMenus(appoptions *App) {
switch runtime.GOOS {
case "darwin":
if appoptions.Menu == nil {
appoptions.Menu = defaultMacMenu
}
}
}
func processMinMaxConstraints(appoptions *App) {
if appoptions.MinWidth > 0 && appoptions.MaxWidth > 0 { if appoptions.MinWidth > 0 && appoptions.MaxWidth > 0 {
if appoptions.MinWidth > appoptions.MaxWidth { if appoptions.MinWidth > appoptions.MaxWidth {
appoptions.MinWidth = appoptions.MaxWidth appoptions.MinWidth = appoptions.MaxWidth
@ -144,12 +166,9 @@ func MergeDefaults(appoptions *App) {
if appoptions.MaxHeight > 0 && appoptions.Height > appoptions.MaxHeight { if appoptions.MaxHeight > 0 && appoptions.Height > appoptions.MaxHeight {
appoptions.Height = appoptions.MaxHeight appoptions.Height = appoptions.MaxHeight
} }
switch runtime.GOOS {
case "darwin":
if appoptions.Menu == nil {
appoptions.Menu = defaultMacMenu
}
} }
func processDragOptions(appoptions *App) {
appoptions.CSSDragProperty = html.EscapeString(appoptions.CSSDragProperty)
appoptions.CSSDragValue = html.EscapeString(appoptions.CSSDragValue)
} }

View File

@ -1,27 +1,12 @@
# Frameless Applications # Frameless Applications
Wails supports applications with no frame. This can be achieved by using the [frameless](../reference/options.mdx#frameless) Wails supports application that have no frames. This can be achieved by using the [frameless](../reference/options.mdx#frameless)
field in [Application Options](../reference/options.mdx#application-options). field in [Application Options](../reference/options.mdx#application-options).
:::warning Wails offers a simple solution for dragging the window: Any HTML element that has the CSS style `--wails-draggable:drag` will
The `data-wails-drag` attribute is being deprecated in favour of the following CSS style: act as a "drag handle". This property applies to all child elements. If you need to indicate that a nested element
`style="--wails-draggable:drag"`. You can use `style="--wails-draggable:no-drag"` to disable the drag behaviour. should not drag, then use the attribute '--wails-draggable:no-drag' on that element.
For this release only, you can test this by setting the following application option:
```go
Experimental: &options.Experimental{
UseCSSDrag: true,
},
```
:::
Wails offers a simple solution for dragging the window: Any HTML element that has the attribute "data-wails-drag" will
act as a "drag handle". This property applies to all nested elements. If you need to indicate that a nested element
should not drag, then use the attribute 'data-wails-no-drag' on that element.
The default vanilla template uses this, even though it is not frameless. The whole `body` element is tagged as draggable.
The `<div id="input" data-wails-no-drag>` is tagged as being not draggable.
```html ```html
<html> <html>
@ -29,9 +14,9 @@ The `<div id="input" data-wails-no-drag>` is tagged as being not draggable.
<link rel="stylesheet" href="/main.css" /> <link rel="stylesheet" href="/main.css" />
</head> </head>
<body data-wails-drag> <body style="--wails-draggable:drag">
<div id="logo"></div> <div id="logo"></div>
<div id="input" data-wails-no-drag> <div id="input" style="--wails-draggable:no-drag">
<input id="name" type="text" /> <input id="name" type="text" />
<button onclick="greet()">Greet</button> <button onclick="greet()">Greet</button>
</div> </div>
@ -42,6 +27,63 @@ The `<div id="input" data-wails-no-drag>` is tagged as being not draggable.
</html> </html>
``` ```
For some projects, using a CSS variable may not be possible due to dynamic styling. In this case, you can use the
`CSSDragProperty` and `CSSDragValue` application options to define a property and value that will be used to indicate
draggable regions:
```go title=main.go
package main
import (
"embed"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
)
//go:embed frontend/dist
var assets embed.FS
func main() {
// Create an instance of the app structure
app := NewApp()
// Create application with options
err := wails.Run(&options.App{
Title: "alwaysontop",
Width: 1024,
Height: 768,
Assets: assets,
Frameless: true,
CSSDragProperty: "widows",
CSSDragValue: "1",
Bind: []interface{}{
app,
},
})
if err != nil {
println("Error:", err)
}
}
```
```html title=index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>alwaysontop</title>
</head>
<body style="widows: 1">
<div id="app"></div>
<script src="./src/main.js" type="module"></script>
</body>
</html>
```
:::info Fullscreen :::info Fullscreen
If you allow your application to go fullscreen, this drag functionality will be disabled. If you allow your application to go fullscreen, this drag functionality will be disabled.
::: :::

View File

@ -40,6 +40,8 @@ func main() {
OnShutdown: app.shutdown, OnShutdown: app.shutdown,
OnBeforeClose: app.beforeClose, OnBeforeClose: app.beforeClose,
WindowStartState: options.Maximised, WindowStartState: options.Maximised,
CSSDragProperty: "--wails-draggable",
CSSDragValue: "drag",
Bind: []interface{}{ Bind: []interface{}{
app, app,
}, },
@ -313,6 +315,18 @@ Defines how the window should present itself at startup.
Type: `options.WindowStartState` Type: `options.WindowStartState`
### CSSDragProperty
Indicates the CSS property to use to identify which elements can be used to drag the window. Default: `--wails-draggable`.
Type: `string`
### CSSDragValue
Indicates what value the `CSSDragProperty` style should have to drag the window. Default: `drag`.
Type: `string`
### Bind ### Bind
A slice of struct instances defining methods that need to be bound to the frontend. A slice of struct instances defining methods that need to be bound to the frontend.