5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 10:21:20 +08:00

[linux] Dialogs WIP

This commit is contained in:
Lea Anthony 2021-12-29 09:47:31 +11:00 committed by Travis McLane
parent 5c24f8bf83
commit 1920a545f4
4 changed files with 118 additions and 8 deletions

View 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{}
}

View File

@ -3,10 +3,24 @@
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) {
panic("implement me")
var openFileResults = make(chan string)
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) {
@ -24,3 +38,8 @@ func (f *Frontend) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (str
func (f *Frontend) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) {
panic("implement me")
}
//export processOpenFileResult
func processOpenFileResult(result *C.char) {
openFileResults <- C.GoString(result)
}

View File

@ -24,6 +24,7 @@ import "C"
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"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 {
println("[NewFrontend] PID:", os.Getpid())
// Set GDK_BACKEND=x11 to prevent warnings
os.Setenv("GDK_BACKEND", "x11")
@ -301,10 +303,11 @@ var dispatchCallbackLock sync.Mutex
//export callDispatchedMethod
func callDispatchedMethod(cid C.int) {
println("[callDispatchedMethod] PID:", os.Getpid())
id := int(cid)
fn := dispatchCallbacks[id]
if fn != nil {
go fn()
fn()
dispatchCallbackLock.Lock()
delete(dispatchCallbacks, id)
dispatchCallbackLock.Unlock()
@ -342,11 +345,24 @@ func (f *Frontend) processRequest(request unsafe.Pointer) {
// Load file from asset store
content, mimeType, err := f.assets.Load(file)
if err != nil {
return
}
// 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))
defer C.free(unsafe.Pointer(cContent))

View File

@ -4,10 +4,11 @@
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 "webkit2/webkit2.h"
#include <X11/Xlib.h>
#include <stdio.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);
}
void initThreads() {
printf("init threads\n");
XInitThreads();
}
// These are the x,y & time of the last mouse down event
// It's used for window dragging
float xroot = 0.0f;
@ -199,10 +205,37 @@ int executeJS(gpointer data) {
void ExecuteOnMainThread(JSCallback* jscallback) {
g_idle_add((GSourceFunc)executeJS, (gpointer)jscallback);
}
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 (
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/pkg/options"
"os"
"unsafe"
)
@ -384,6 +417,8 @@ func (w *Window) Run() {
case options.Maximised:
w.Maximise()
}
C.initThreads()
C.gtk_main()
w.Destroy()
}
@ -425,3 +460,11 @@ func (w *Window) StartDrag() {
func (w *Window) 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()
}