context menu fixes

This commit is contained in:
2026-01-17 15:19:03 +00:00
parent 10a66cd399
commit 88679dfae8
5 changed files with 119 additions and 47 deletions

View File

@@ -900,7 +900,7 @@ public class LinuxApplication : IDisposable
private void OnPointerPressed(object? sender, PointerEventArgs e) private void OnPointerPressed(object? sender, PointerEventArgs e)
{ {
Console.WriteLine($"[LinuxApplication] OnPointerPressed at ({e.X}, {e.Y})"); Console.WriteLine($"[LinuxApplication] OnPointerPressed at ({e.X}, {e.Y}), Button={e.Button}");
// Route to context menu if one is active // Route to context menu if one is active
if (LinuxDialogService.HasContextMenu) if (LinuxDialogService.HasContextMenu)

View File

@@ -253,8 +253,8 @@ public class GpuRenderingEngine : IDisposable
// Draw popup overlays // Draw popup overlays
SkiaView.DrawPopupOverlays(_canvas); SkiaView.DrawPopupOverlays(_canvas);
// Draw modal dialogs // Draw modal dialogs and context menus
if (LinuxDialogService.HasActiveDialog) if (LinuxDialogService.HasActiveDialog || LinuxDialogService.HasContextMenu)
{ {
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0, 0, Width, Height)); LinuxDialogService.DrawDialogs(_canvas, new SKRect(0, 0, Width, Height));
} }

View File

@@ -205,8 +205,8 @@ public class SkiaRenderingEngine : IDisposable
// Draw popup overlays (always on top, full redraw) // Draw popup overlays (always on top, full redraw)
SkiaView.DrawPopupOverlays(_canvas); SkiaView.DrawPopupOverlays(_canvas);
// Draw modal dialogs on top of everything // Draw modal dialogs and context menus on top of everything
if (LinuxDialogService.HasActiveDialog) if (LinuxDialogService.HasActiveDialog || LinuxDialogService.HasContextMenu)
{ {
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0, 0, Width, Height)); LinuxDialogService.DrawDialogs(_canvas, new SKRect(0, 0, Width, Height));
} }

View File

@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Maui.Controls; using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics; using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform.Linux;
using Microsoft.Maui.Platform.Linux.Rendering; using Microsoft.Maui.Platform.Linux.Rendering;
using Microsoft.Maui.Platform.Linux.Services; using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp; using SkiaSharp;
@@ -1086,11 +1087,13 @@ public class SkiaEditor : SkiaView, IInputContext
public override void OnPointerPressed(PointerEventArgs e) public override void OnPointerPressed(PointerEventArgs e)
{ {
Console.WriteLine($"[SkiaEditor] OnPointerPressed: Button={e.Button}, IsEnabled={IsEnabled}");
if (!IsEnabled) return; if (!IsEnabled) return;
// Handle right-click context menu // Handle right-click context menu
if (e.Button == PointerButton.Right) if (e.Button == PointerButton.Right)
{ {
Console.WriteLine("[SkiaEditor] Right-click detected, showing context menu");
ShowContextMenu(e.X, e.Y); ShowContextMenu(e.X, e.Y);
return; return;
} }
@@ -1503,12 +1506,15 @@ public class SkiaEditor : SkiaView, IInputContext
private void ShowContextMenu(float x, float y) private void ShowContextMenu(float x, float y)
{ {
Console.WriteLine($"[SkiaEditor] ShowContextMenu at ({x}, {y})"); Console.WriteLine($"[SkiaEditor] ShowContextMenu at ({x}, {y}), IsGtkMode={LinuxApplication.IsGtkMode}");
bool hasSelection = _selectionLength != 0; bool hasSelection = _selectionLength != 0;
bool hasText = !string.IsNullOrEmpty(Text); bool hasText = !string.IsNullOrEmpty(Text);
bool hasClipboard = !string.IsNullOrEmpty(SystemClipboard.GetText()); bool hasClipboard = !string.IsNullOrEmpty(SystemClipboard.GetText());
bool isEditable = !IsReadOnly; bool isEditable = !IsReadOnly;
if (LinuxApplication.IsGtkMode)
{
// Use GTK context menu when running in GTK mode (e.g., with WebView)
GtkContextMenuService.ShowContextMenu(new List<GtkMenuItem> GtkContextMenuService.ShowContextMenu(new List<GtkMenuItem>
{ {
new GtkMenuItem("Cut", () => new GtkMenuItem("Cut", () =>
@@ -1533,6 +1539,37 @@ public class SkiaEditor : SkiaView, IInputContext
}, hasText) }, hasText)
}); });
} }
else
{
// Use Skia-rendered context menu for pure Skia mode (Wayland/X11)
bool isDarkTheme = Application.Current?.RequestedTheme == AppTheme.Dark;
var items = new List<ContextMenuItem>
{
new ContextMenuItem("Cut", () =>
{
CutToClipboard();
Invalidate();
}, hasSelection && isEditable),
new ContextMenuItem("Copy", () =>
{
CopyToClipboard();
}, hasSelection),
new ContextMenuItem("Paste", () =>
{
PasteFromClipboard();
Invalidate();
}, hasClipboard && isEditable),
ContextMenuItem.Separator,
new ContextMenuItem("Select All", () =>
{
SelectAll();
Invalidate();
}, hasText)
};
var menu = new SkiaContextMenu(x, y, items, isDarkTheme);
LinuxDialogService.ShowContextMenu(menu);
}
}
#endregion #endregion

View File

@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Maui.Controls; using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics; using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform.Linux;
using Microsoft.Maui.Platform.Linux.Rendering; using Microsoft.Maui.Platform.Linux.Rendering;
using Microsoft.Maui.Platform.Linux.Services; using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp; using SkiaSharp;
@@ -1643,11 +1644,14 @@ public class SkiaEntry : SkiaView, IInputContext
private void ShowContextMenu(float x, float y) private void ShowContextMenu(float x, float y)
{ {
Console.WriteLine($"[SkiaEntry] ShowContextMenu at ({x}, {y})"); Console.WriteLine($"[SkiaEntry] ShowContextMenu at ({x}, {y}), IsGtkMode={LinuxApplication.IsGtkMode}");
bool hasSelection = _selectionLength != 0; bool hasSelection = _selectionLength != 0;
bool hasText = !string.IsNullOrEmpty(Text); bool hasText = !string.IsNullOrEmpty(Text);
bool hasClipboard = !string.IsNullOrEmpty(SystemClipboard.GetText()); bool hasClipboard = !string.IsNullOrEmpty(SystemClipboard.GetText());
if (LinuxApplication.IsGtkMode)
{
// Use GTK context menu when running in GTK mode (e.g., with WebView)
GtkContextMenuService.ShowContextMenu(new List<GtkMenuItem> GtkContextMenuService.ShowContextMenu(new List<GtkMenuItem>
{ {
new GtkMenuItem("Cut", () => new GtkMenuItem("Cut", () =>
@@ -1672,6 +1676,37 @@ public class SkiaEntry : SkiaView, IInputContext
}, hasText) }, hasText)
}); });
} }
else
{
// Use Skia-rendered context menu for pure Skia mode (Wayland/X11)
bool isDarkTheme = Application.Current?.RequestedTheme == AppTheme.Dark;
var items = new List<ContextMenuItem>
{
new ContextMenuItem("Cut", () =>
{
CutToClipboard();
Invalidate();
}, hasSelection),
new ContextMenuItem("Copy", () =>
{
CopyToClipboard();
}, hasSelection),
new ContextMenuItem("Paste", () =>
{
PasteFromClipboard();
Invalidate();
}, hasClipboard),
ContextMenuItem.Separator,
new ContextMenuItem("Select All", () =>
{
SelectAll();
Invalidate();
}, hasText)
};
var menu = new SkiaContextMenu(x, y, items, isDarkTheme);
LinuxDialogService.ShowContextMenu(menu);
}
}
public override void OnFocusGained() public override void OnFocusGained()
{ {