mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
Support linux systrays, of sorts...
This commit is contained in:
committed by
Travis McLane
parent
12e2e2101a
commit
161444107a
@@ -60,6 +60,7 @@ typedef struct WindowEvent {
|
||||
void activateLinux(gpointer data);
|
||||
extern void emit(WindowEvent* data);
|
||||
extern gboolean handleDeleteEvent(GtkWidget*, GdkEvent*, uintptr_t);
|
||||
extern gboolean handleFocusEvent(GtkWidget*, GdkEvent*, uintptr_t);
|
||||
extern void handleLoadChanged(WebKitWebView*, WebKitLoadEvent, uintptr_t);
|
||||
void handleClick(void*);
|
||||
extern gboolean onButtonEvent(GtkWidget *widget, GdkEventButton *event, uintptr_t user_data);
|
||||
@@ -701,6 +702,31 @@ func (w *linuxWebviewWindow) execJS(js string) {
|
||||
C.free(unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
func getMousePosition() (int, int, *Screen) {
|
||||
var x, y C.gint
|
||||
var screen *C.GdkScreen
|
||||
defaultDisplay := C.gdk_display_get_default()
|
||||
device := C.gdk_seat_get_pointer(C.gdk_display_get_default_seat(defaultDisplay))
|
||||
C.gdk_device_get_position(device, &screen, &x, &y)
|
||||
// Get Monitor for screen
|
||||
monitor := C.gdk_display_get_monitor_at_point(defaultDisplay, x, y)
|
||||
geometry := C.GdkRectangle{}
|
||||
C.gdk_monitor_get_geometry(monitor, &geometry)
|
||||
scale := int(C.gdk_monitor_get_scale_factor(monitor))
|
||||
return int(x), int(y), &Screen{
|
||||
ID: fmt.Sprintf("%d", 0), // A unique identifier for the display
|
||||
Name: C.GoString(C.gdk_monitor_get_model(monitor)), // The name of the display
|
||||
Scale: float32(scale), // The scale factor of the display
|
||||
X: int(geometry.x), // The x-coordinate of the top-left corner of the rectangle
|
||||
Y: int(geometry.y), // The y-coordinate of the top-left corner of the rectangle
|
||||
Size: Size{Width: int(geometry.width), Height: int(geometry.height)}, // The size of the display
|
||||
Bounds: Rect{}, // The bounds of the display
|
||||
WorkArea: Rect{}, // The work area of the display
|
||||
IsPrimary: false, // Whether this is the primary display
|
||||
Rotation: 0.0, // The rotation of the display
|
||||
}
|
||||
}
|
||||
|
||||
func (w *linuxWebviewWindow) destroy() {
|
||||
w.parent.markAsDestroyed()
|
||||
// Free menu
|
||||
@@ -708,7 +734,8 @@ func (w *linuxWebviewWindow) destroy() {
|
||||
C.gtk_widget_destroy((*C.GtkWidget)(w.gtkmenu))
|
||||
w.gtkmenu = nil
|
||||
}
|
||||
w.destroy()
|
||||
// Free window
|
||||
C.gtk_widget_destroy(w.gtkWidget())
|
||||
}
|
||||
|
||||
func (w *linuxWebviewWindow) fullscreen() {
|
||||
@@ -908,7 +935,7 @@ func (w *linuxWebviewWindow) show() {
|
||||
return
|
||||
}
|
||||
C.gtk_widget_show_all(w.gtkWidget())
|
||||
w.setAbsolutePosition(w.lastX, w.lastY)
|
||||
//w.setAbsolutePosition(w.lastX, w.lastY)
|
||||
}
|
||||
|
||||
func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) {
|
||||
@@ -1057,6 +1084,19 @@ func handleDeleteEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t)
|
||||
return C.gboolean(1)
|
||||
}
|
||||
|
||||
//export handleFocusEvent
|
||||
func handleFocusEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t) C.gboolean {
|
||||
focusEvent := (*C.GdkEventFocus)(unsafe.Pointer(event))
|
||||
if focusEvent._type == C.GDK_FOCUS_CHANGE {
|
||||
if focusEvent.in == C.TRUE {
|
||||
processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusIn))
|
||||
} else {
|
||||
processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusOut))
|
||||
}
|
||||
}
|
||||
return C.gboolean(0)
|
||||
}
|
||||
|
||||
//export handleLoadChanged
|
||||
func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C.uintptr_t) {
|
||||
switch event {
|
||||
@@ -1075,6 +1115,7 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT
|
||||
// Set up the window close event
|
||||
wv := unsafe.Pointer(w.webview)
|
||||
C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID)
|
||||
C.signal_connect(unsafe.Pointer(w.window), c.String("focus-out-event"), C.handleFocusEvent, winID)
|
||||
C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID)
|
||||
|
||||
contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView())
|
||||
@@ -1111,6 +1152,14 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT
|
||||
C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID)
|
||||
}
|
||||
|
||||
func getMouseButtons() (bool, bool, bool) {
|
||||
var pointer *C.GdkDevice
|
||||
var state C.GdkModifierType
|
||||
pointer = C.gdk_seat_get_pointer(C.gdk_display_get_default_seat(C.gdk_display_get_default()))
|
||||
C.gdk_device_get_state(pointer, nil, nil, &state)
|
||||
return state&C.GDK_BUTTON1_MASK > 0, state&C.GDK_BUTTON2_MASK > 0, state&C.GDK_BUTTON3_MASK > 0
|
||||
}
|
||||
|
||||
func openDevTools(webview pointer) {
|
||||
inspector := C.webkit_web_view_get_inspector((*C.WebKitWebView)(webview))
|
||||
C.webkit_web_inspector_show(inspector)
|
||||
@@ -1180,7 +1229,8 @@ func (w *linuxWebviewWindow) setZoom(zoom float64) {
|
||||
}
|
||||
|
||||
func (w *linuxWebviewWindow) move(x, y int) {
|
||||
C.gtk_window_move((*C.GtkWindow)(w.window), C.int(x), C.int(y))
|
||||
// Move the window to these coordinates
|
||||
C.gtk_window_move(w.gtkWindow(), C.int(x), C.int(y))
|
||||
}
|
||||
|
||||
func (w *linuxWebviewWindow) absolutePosition() (int, int) {
|
||||
@@ -1380,7 +1430,7 @@ func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden b
|
||||
|
||||
gtkFilters := []*C.GtkFileFilter{}
|
||||
for _, filter := range filters {
|
||||
f := (C.gtk_file_filter_new())
|
||||
f := C.gtk_file_filter_new()
|
||||
displayStr := C.CString(filter.DisplayName)
|
||||
C.gtk_file_filter_set_name(f, displayStr)
|
||||
C.free(unsafe.Pointer(displayStr))
|
||||
|
||||
@@ -106,6 +106,10 @@ func (m *Menu) clone() *Menu {
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *Menu) Append(in *Menu) {
|
||||
m.items = append(m.items, in.items...)
|
||||
}
|
||||
|
||||
func (a *App) NewMenu() *Menu {
|
||||
return &Menu{}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ const (
|
||||
)
|
||||
|
||||
type linuxSystemTray struct {
|
||||
parent *SystemTray
|
||||
|
||||
id uint
|
||||
label string
|
||||
icon []byte
|
||||
@@ -41,6 +43,11 @@ type linuxSystemTray struct {
|
||||
itemMap map[int32]*systrayMenuItem
|
||||
}
|
||||
|
||||
func (s *linuxSystemTray) getScreen() (*Screen, error) {
|
||||
_, _, result := getMousePosition()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// dbusMenu is a named struct to map into generated bindings.
|
||||
// It represents the layout of a menu item
|
||||
type dbusMenu = struct {
|
||||
@@ -182,6 +189,22 @@ func (s *linuxSystemTray) refresh() {
|
||||
}
|
||||
|
||||
func (s *linuxSystemTray) setMenu(menu *Menu) {
|
||||
if s.parent.attachedWindow.Window != nil {
|
||||
temp := menu
|
||||
menu = NewMenu()
|
||||
title := "Open"
|
||||
if s.parent.attachedWindow.Window.Name() != "" {
|
||||
title += " " + s.parent.attachedWindow.Window.Name()
|
||||
} else {
|
||||
title += " window"
|
||||
}
|
||||
openMenuItem := menu.Add(title)
|
||||
openMenuItem.OnClick(func(*Context) {
|
||||
s.parent.clickHandler()
|
||||
})
|
||||
menu.AddSeparator()
|
||||
menu.Append(temp)
|
||||
}
|
||||
s.itemMap = map[int32]*systrayMenuItem{}
|
||||
// our root menu element
|
||||
s.itemMap[0] = &systrayMenuItem{
|
||||
@@ -198,16 +221,47 @@ func (s *linuxSystemTray) setMenu(menu *Menu) {
|
||||
}
|
||||
|
||||
func (s *linuxSystemTray) positionWindow(window *WebviewWindow, offset int) error {
|
||||
// Get the mouse location on the screen
|
||||
mouseX, mouseY, currentScreen := getMousePosition()
|
||||
screenBounds := currentScreen.Size
|
||||
|
||||
// Calculate new X position
|
||||
newX := mouseX - (window.Width() / 2)
|
||||
|
||||
// Check if the window goes out of the screen bounds on the left side
|
||||
if newX < 0 {
|
||||
newX = 0
|
||||
}
|
||||
|
||||
// Check if the window goes out of the screen bounds on the right side
|
||||
if newX+window.Width() > screenBounds.Width {
|
||||
newX = screenBounds.Width - window.Width()
|
||||
}
|
||||
|
||||
// Calculate new Y position
|
||||
newY := mouseY - (window.Height() / 2)
|
||||
|
||||
// Check if the window goes out of the screen bounds on the top
|
||||
if newY < 0 {
|
||||
newY = 0
|
||||
}
|
||||
|
||||
// Check if the window goes out of the screen bounds on the bottom
|
||||
if newY+window.Height() > screenBounds.Height {
|
||||
newY = screenBounds.Height - window.Height() - offset
|
||||
}
|
||||
|
||||
// Set the new position of the window
|
||||
window.SetAbsolutePosition(newX, newY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *linuxSystemTray) getScreen() (*Screen, error) {
|
||||
// FIXME: How do we get the screen we are on?
|
||||
return &Screen{}, nil
|
||||
}
|
||||
|
||||
func (s *linuxSystemTray) bounds() (*Rect, error) {
|
||||
|
||||
// Best effort guess at the screen bounds
|
||||
|
||||
return &Rect{}, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *linuxSystemTray) run() {
|
||||
@@ -354,6 +408,7 @@ func newSystemTrayImpl(s *SystemTray) systemTrayImpl {
|
||||
}
|
||||
|
||||
return &linuxSystemTray{
|
||||
parent: s,
|
||||
id: s.id,
|
||||
label: label,
|
||||
icon: s.icon,
|
||||
@@ -572,6 +627,16 @@ func (s *linuxSystemTray) Event(id int32, eventID string, data dbus.Variant, tim
|
||||
InvokeAsync(item.menuItem.handleClick)
|
||||
}
|
||||
}
|
||||
if eventID == "opened" {
|
||||
if s.parent.onMenuOpen != nil {
|
||||
s.parent.onMenuOpen()
|
||||
}
|
||||
}
|
||||
if eventID == "closed" {
|
||||
if s.parent.onMenuClose != nil {
|
||||
s.parent.onMenuClose()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -583,6 +648,7 @@ func (s *linuxSystemTray) EventGroup(events []struct {
|
||||
V3 uint32
|
||||
}) (idErrors []int32, err *dbus.Error) {
|
||||
for _, event := range events {
|
||||
fmt.Printf("EventGroup: %v, %v, %v, %v\n", event.V0, event.V1, event.V2, event.V3)
|
||||
if event.V1 == "clicked" {
|
||||
item, ok := s.itemMap[event.V0]
|
||||
if ok {
|
||||
|
||||
@@ -264,6 +264,12 @@ func (w *linuxWebviewWindow) run() {
|
||||
w.execJS(js)
|
||||
}
|
||||
})
|
||||
w.parent.On(events.Linux.WindowFocusIn, func(e *WindowEvent) {
|
||||
w.parent.emit(events.Common.WindowFocus)
|
||||
})
|
||||
w.parent.On(events.Linux.WindowFocusOut, func(e *WindowEvent) {
|
||||
w.parent.emit(events.Common.WindowLostFocus)
|
||||
})
|
||||
w.parent.On(events.Linux.WindowDeleteEvent, func(e *WindowEvent) {
|
||||
w.parent.emit(events.Common.WindowClosing)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user