mirror of
https://github.com/taigrr/wails.git
synced 2026-04-04 06:02:43 -07:00
Compare commits
2 Commits
master
...
linux-dial
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b296fbbb99 | ||
|
|
26c4f112e3 |
@@ -74,8 +74,6 @@ const (
|
|||||||
NixOS
|
NixOS
|
||||||
// Artix linux distribution
|
// Artix linux distribution
|
||||||
ArtixLinux
|
ArtixLinux
|
||||||
//Uos distribution
|
|
||||||
Uos
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DistroInfo contains all the information relating to a linux distribution
|
// DistroInfo contains all the information relating to a linux distribution
|
||||||
@@ -192,8 +190,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
|||||||
result.Distribution = NixOS
|
result.Distribution = NixOS
|
||||||
case "artix":
|
case "artix":
|
||||||
result.Distribution = ArtixLinux
|
result.Distribution = ArtixLinux
|
||||||
case "uos":
|
|
||||||
result.Distribution = Uos
|
|
||||||
default:
|
default:
|
||||||
result.Distribution = Unknown
|
result.Distribution = Unknown
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,15 +100,6 @@ distributions:
|
|||||||
gccversioncommand: *gccdumpfullversion
|
gccversioncommand: *gccdumpfullversion
|
||||||
programs: *debiandefaultprograms
|
programs: *debiandefaultprograms
|
||||||
libraries: *debiandefaultlibraries
|
libraries: *debiandefaultlibraries
|
||||||
uos:
|
|
||||||
id: uos
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: Uos
|
|
||||||
gccversioncommand: *gccdumpfullversion
|
|
||||||
programs: *debiandefaultprograms
|
|
||||||
libraries: *debiandefaultlibraries
|
|
||||||
void:
|
void:
|
||||||
id: void
|
id: void
|
||||||
releases:
|
releases:
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
|||||||
distroInfo := GetLinuxDistroInfo()
|
distroInfo := GetLinuxDistroInfo()
|
||||||
|
|
||||||
switch distroInfo.Distribution {
|
switch distroInfo.Distribution {
|
||||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS, Uos:
|
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
|
||||||
libraryChecker = DpkgInstalled
|
libraryChecker = DpkgInstalled
|
||||||
case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS, ArtixLinux:
|
case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS, ArtixLinux:
|
||||||
libraryChecker = PacmanInstalled
|
libraryChecker = PacmanInstalled
|
||||||
|
|||||||
32
v2/internal/frontend/desktop/linux/calloc.go
Normal file
32
v2/internal/frontend/desktop/linux/calloc.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// Calloc handles alloc/dealloc of C data
|
||||||
|
type Calloc struct {
|
||||||
|
pool []unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCalloc creates a new allocator
|
||||||
|
func NewCalloc() Calloc {
|
||||||
|
return Calloc{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String creates a new C string and retains a reference to it
|
||||||
|
func (c Calloc) String(in string) *C.char {
|
||||||
|
result := C.CString(in)
|
||||||
|
c.pool = append(c.pool, unsafe.Pointer(result))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free frees all allocated C memory
|
||||||
|
func (c Calloc) Free() {
|
||||||
|
for _, str := range c.pool {
|
||||||
|
C.free(str)
|
||||||
|
}
|
||||||
|
c.pool = []unsafe.Pointer{}
|
||||||
|
}
|
||||||
@@ -3,10 +3,24 @@
|
|||||||
|
|
||||||
package linux
|
package linux
|
||||||
|
|
||||||
import "github.com/wailsapp/wails/v2/internal/frontend"
|
import (
|
||||||
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
|
)
|
||||||
|
import "C"
|
||||||
|
|
||||||
func (f *Frontend) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (string, error) {
|
var openFileResults = make(chan string)
|
||||||
panic("implement me")
|
|
||||||
|
func (f *Frontend) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (result string, err error) {
|
||||||
|
|
||||||
|
f.dispatch(func() {
|
||||||
|
println("Before OpenFileDialog")
|
||||||
|
f.mainWindow.OpenFileDialog(dialogOptions)
|
||||||
|
println("After OpenFileDialog")
|
||||||
|
})
|
||||||
|
println("Waiting for result")
|
||||||
|
result = <-openFileResults
|
||||||
|
println("Got result")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
|
func (f *Frontend) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
|
||||||
@@ -24,3 +38,8 @@ func (f *Frontend) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (str
|
|||||||
func (f *Frontend) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) {
|
func (f *Frontend) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export processOpenFileResult
|
||||||
|
func processOpenFileResult(result *C.char) {
|
||||||
|
openFileResults <- C.GoString(result)
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -62,6 +63,7 @@ type Frontend struct {
|
|||||||
|
|
||||||
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
|
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
|
||||||
|
|
||||||
|
println("[NewFrontend] PID:", os.Getpid())
|
||||||
// Set GDK_BACKEND=x11 to prevent warnings
|
// Set GDK_BACKEND=x11 to prevent warnings
|
||||||
os.Setenv("GDK_BACKEND", "x11")
|
os.Setenv("GDK_BACKEND", "x11")
|
||||||
|
|
||||||
@@ -301,10 +303,11 @@ var dispatchCallbackLock sync.Mutex
|
|||||||
|
|
||||||
//export callDispatchedMethod
|
//export callDispatchedMethod
|
||||||
func callDispatchedMethod(cid C.int) {
|
func callDispatchedMethod(cid C.int) {
|
||||||
|
println("[callDispatchedMethod] PID:", os.Getpid())
|
||||||
id := int(cid)
|
id := int(cid)
|
||||||
fn := dispatchCallbacks[id]
|
fn := dispatchCallbacks[id]
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
go fn()
|
fn()
|
||||||
dispatchCallbackLock.Lock()
|
dispatchCallbackLock.Lock()
|
||||||
delete(dispatchCallbacks, id)
|
delete(dispatchCallbacks, id)
|
||||||
dispatchCallbackLock.Unlock()
|
dispatchCallbackLock.Unlock()
|
||||||
@@ -342,11 +345,24 @@ func (f *Frontend) processRequest(request unsafe.Pointer) {
|
|||||||
|
|
||||||
// Load file from asset store
|
// Load file from asset store
|
||||||
content, mimeType, err := f.assets.Load(file)
|
content, mimeType, err := f.assets.Load(file)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO How to return 404/500 errors to webkit?
|
// TODO How to return 404/500 errors to webkit?
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
f.dispatch(func() {
|
||||||
|
message := C.CString("not found")
|
||||||
|
defer C.free(unsafe.Pointer(message))
|
||||||
|
C.webkit_uri_scheme_request_finish_error(req, C.g_error_new_literal(C.G_FILE_ERROR_NOENT, C.int(404), message))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("Error processing request %s: %w", uri, err)
|
||||||
|
f.logger.Error(err.Error())
|
||||||
|
message := C.CString("internal server error")
|
||||||
|
defer C.free(unsafe.Pointer(message))
|
||||||
|
C.webkit_uri_scheme_request_finish_error(req, C.g_error_new_literal(C.G_FILE_ERROR_NOENT, C.int(500), message))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
cContent := C.CString(string(content))
|
cContent := C.CString(string(content))
|
||||||
defer C.free(unsafe.Pointer(cContent))
|
defer C.free(unsafe.Pointer(cContent))
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
package linux
|
package linux
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
|
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 x11
|
||||||
|
|
||||||
#include "gtk/gtk.h"
|
#include "gtk/gtk.h"
|
||||||
#include "webkit2/webkit2.h"
|
#include "webkit2/webkit2.h"
|
||||||
|
#include <X11/Xlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
@@ -105,6 +106,11 @@ ulong setupInvokeSignal(void* contentManager) {
|
|||||||
return g_signal_connect((WebKitUserContentManager*)contentManager, "script-message-received::external", G_CALLBACK(sendMessageToBackend), NULL);
|
return g_signal_connect((WebKitUserContentManager*)contentManager, "script-message-received::external", G_CALLBACK(sendMessageToBackend), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initThreads() {
|
||||||
|
printf("init threads\n");
|
||||||
|
XInitThreads();
|
||||||
|
}
|
||||||
|
|
||||||
// These are the x,y & time of the last mouse down event
|
// These are the x,y & time of the last mouse down event
|
||||||
// It's used for window dragging
|
// It's used for window dragging
|
||||||
float xroot = 0.0f;
|
float xroot = 0.0f;
|
||||||
@@ -184,10 +190,36 @@ static void startDrag(void *webview, GtkWindow* mainwindow)
|
|||||||
gtk_window_begin_move_drag(mainwindow, 1, xroot, yroot, dragTime);
|
gtk_window_begin_move_drag(mainwindow, 1, xroot, yroot, dragTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void extern processOpenFileResult(char*);
|
||||||
|
|
||||||
|
static void OpenDialog(GtkWindow* window, char *title) {
|
||||||
|
printf("Here\n");
|
||||||
|
GtkWidget *dlg = gtk_file_chooser_dialog_new(title, window, GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
|
"_Open", GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
printf("Here3\n");
|
||||||
|
|
||||||
|
gint response = gtk_dialog_run(GTK_DIALOG(dlg));
|
||||||
|
printf("Here 4\n");
|
||||||
|
|
||||||
|
if (response == GTK_RESPONSE_ACCEPT)
|
||||||
|
{
|
||||||
|
printf("Here 5\n");
|
||||||
|
|
||||||
|
gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
|
||||||
|
processOpenFileResult(filename);
|
||||||
|
g_free(filename);
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(dlg);
|
||||||
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
|
"os"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -369,6 +401,8 @@ func (w *Window) Run() {
|
|||||||
case options.Maximised:
|
case options.Maximised:
|
||||||
w.Maximise()
|
w.Maximise()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C.initThreads()
|
||||||
C.gtk_main()
|
C.gtk_main()
|
||||||
w.Destroy()
|
w.Destroy()
|
||||||
}
|
}
|
||||||
@@ -408,3 +442,11 @@ func (w *Window) StartDrag() {
|
|||||||
func (w *Window) Quit() {
|
func (w *Window) Quit() {
|
||||||
C.gtk_main_quit()
|
C.gtk_main_quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Window) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) {
|
||||||
|
println("OpenFileDialog PID:", os.Getpid())
|
||||||
|
mem := NewCalloc()
|
||||||
|
title := mem.String(dialogOptions.Title)
|
||||||
|
C.OpenDialog(w.asGTKWindow(), title)
|
||||||
|
mem.Free()
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,10 +57,10 @@ func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
|||||||
result.SetText(appoptions.Title)
|
result.SetText(appoptions.Title)
|
||||||
if appoptions.Frameless == false && !appoptions.Fullscreen {
|
if appoptions.Frameless == false && !appoptions.Fullscreen {
|
||||||
result.EnableMaxButton(!appoptions.DisableResize)
|
result.EnableMaxButton(!appoptions.DisableResize)
|
||||||
|
result.EnableSizable(!appoptions.DisableResize)
|
||||||
result.SetMinSize(appoptions.MinWidth, appoptions.MinHeight)
|
result.SetMinSize(appoptions.MinWidth, appoptions.MinHeight)
|
||||||
result.SetMaxSize(appoptions.MaxWidth, appoptions.MaxHeight)
|
result.SetMaxSize(appoptions.MaxWidth, appoptions.MaxHeight)
|
||||||
}
|
}
|
||||||
result.EnableSizable(!appoptions.DisableResize)
|
|
||||||
|
|
||||||
if appoptions.Windows != nil {
|
if appoptions.Windows != nil {
|
||||||
if appoptions.Windows.WindowIsTranslucent {
|
if appoptions.Windows.WindowIsTranslucent {
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ package runtime
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
"github.com/wailsapp/wails/v2/internal/fs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileFilter defines a filter for dialog boxes
|
// FileFilter defines a filter for dialog boxes
|
||||||
@@ -31,44 +29,24 @@ type MessageDialogOptions = frontend.MessageDialogOptions
|
|||||||
// OpenDirectoryDialog prompts the user to select a directory
|
// OpenDirectoryDialog prompts the user to select a directory
|
||||||
func OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
|
func OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
|
||||||
appFrontend := getFrontend(ctx)
|
appFrontend := getFrontend(ctx)
|
||||||
if dialogOptions.DefaultDirectory != "" {
|
|
||||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
|
||||||
return "", fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return appFrontend.OpenDirectoryDialog(dialogOptions)
|
return appFrontend.OpenDirectoryDialog(dialogOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFileDialog prompts the user to select a file
|
// OpenFileDialog prompts the user to select a file
|
||||||
func OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
|
func OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
|
||||||
appFrontend := getFrontend(ctx)
|
appFrontend := getFrontend(ctx)
|
||||||
if dialogOptions.DefaultDirectory != "" {
|
|
||||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
|
||||||
return "", fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return appFrontend.OpenFileDialog(dialogOptions)
|
return appFrontend.OpenFileDialog(dialogOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenMultipleFilesDialog prompts the user to select a file
|
// OpenMultipleFilesDialog prompts the user to select a file
|
||||||
func OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error) {
|
func OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error) {
|
||||||
appFrontend := getFrontend(ctx)
|
appFrontend := getFrontend(ctx)
|
||||||
if dialogOptions.DefaultDirectory != "" {
|
|
||||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
|
||||||
return nil, fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return appFrontend.OpenMultipleFilesDialog(dialogOptions)
|
return appFrontend.OpenMultipleFilesDialog(dialogOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveFileDialog prompts the user to select a file
|
// SaveFileDialog prompts the user to select a file
|
||||||
func SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error) {
|
func SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error) {
|
||||||
appFrontend := getFrontend(ctx)
|
appFrontend := getFrontend(ctx)
|
||||||
if dialogOptions.DefaultDirectory != "" {
|
|
||||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
|
||||||
return "", fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return appFrontend.SaveFileDialog(dialogOptions)
|
return appFrontend.SaveFileDialog(dialogOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,3 @@ sidebar_position: 1
|
|||||||
## Angular
|
## Angular
|
||||||
|
|
||||||
- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - 带有 TypeScript, Sass, 热重载, 代码拆分和 i18n 的 Angular
|
- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - 带有 TypeScript, Sass, 热重载, 代码拆分和 i18n 的 Angular
|
||||||
|
|
||||||
## React
|
|
||||||
|
|
||||||
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - 基于 reactjs 的模板
|
|
||||||
- [wails-react-template](https://github.com/flin7/wails-react-template) - 基于 React 并支持实时开发模式的轻量级模板
|
|
||||||
|
|
||||||
## Svelte
|
|
||||||
|
|
||||||
- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - 基于 Svelte 的模板
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user