Skip to content

Commit

Permalink
feat: Cursors loaded from Gtk display theme. Support for more cursors…
Browse files Browse the repository at this point in the history
… on Gtk
  • Loading branch information
trungnt2910 committed Jun 6, 2021
1 parent 19140cd commit 6ce492a
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 33 deletions.
12 changes: 10 additions & 2 deletions src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Uno.UI.Runtime.Skia.GTK.Extensions.Helpers;
using Uno.Extensions.System;
using Uno.UI.Runtime.Skia.GTK.Extensions.System;
using Uno.UI.Runtime.Skia.GTK.UI.Core;

namespace Uno.UI.Runtime.Skia
{
Expand Down Expand Up @@ -60,6 +61,13 @@ public void Run()
_window.SetDefaultSize(1024, 800);
_window.SetPosition(Gtk.WindowPosition.Center);

_window.Realized += (s, e) =>
{
// Load the correct cursors before the window is shown
// but after the window has been initialized.
Cursors.Reload();
};

_window.DeleteEvent += delegate
{
Gtk.Application.Quit();
Expand Down Expand Up @@ -116,9 +124,9 @@ void Dispatch(System.Action d)

_window.WindowStateEvent += OnWindowStateChanged;

var overlay = new Overlay();
var overlay = new Overlay();

_eventBox = new EventBox();
_eventBox = new EventBox();
_area = new UnoDrawingArea();
_fix = new Fixed();
overlay.Add(_area);
Expand Down
118 changes: 87 additions & 31 deletions src/Uno.UI.Runtime.Skia.Gtk/UI/Core/CursorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,101 @@
using System.Threading.Tasks;
using Gdk;
using Windows.UI.Core;
using Uno.UI.Runtime.Skia.GTK.UI.Core;

namespace Uno.UI.Runtime.Skia.GTK.Extensions
{
internal static class CursorExtensions
{
public static CoreCursor ToCoreCursor(this Cursor cursor)
{
CoreCursorType GetCoreCursorType(CursorType? type) =>
type switch
{
CursorType.Arrow => CoreCursorType.Arrow,
CursorType.Cross => CoreCursorType.Cross,
CursorType.Hand1 => CoreCursorType.Hand,
CursorType.Hand2 => CoreCursorType.Hand,
CursorType.QuestionArrow => CoreCursorType.Help,
CursorType.Sizing => CoreCursorType.SizeAll,
CursorType.Watch => CoreCursorType.Wait,
_ => CoreCursorType.Arrow,
};

return new CoreCursor(GetCoreCursorType(cursor?.CursorType), 0);
}

public static Cursor ToCursor(this CoreCursor coreCursor)
{
CursorType GetCursorType(CoreCursorType? coreCursorType) =>
coreCursorType switch
{
CoreCursorType.Arrow => CursorType.Arrow,
CoreCursorType.Cross => CursorType.Cross,
CoreCursorType.Hand => CursorType.Hand1,
CoreCursorType.Help => CursorType.QuestionArrow,
CoreCursorType.SizeAll => CursorType.Sizing,
CoreCursorType.Wait => CursorType.Watch,
_ => CursorType.Arrow,
};
CoreCursorType cursorType;
if (cursor == Cursors.Wait)
{
cursorType = CoreCursorType.Wait;
}
else if (cursor == Cursors.Pointer)
{
cursorType = CoreCursorType.Hand;
}
else if (cursor == Cursors.Crosshair)
{
cursorType = CoreCursorType.Cross;
}
else if (cursor == Cursors.Help)
{
cursorType = CoreCursorType.Help;
}
else if (cursor == Cursors.Text)
{
cursorType = CoreCursorType.IBeam;
}
else if (cursor == Cursors.NotAllowed)
{
cursorType = CoreCursorType.UniversalNo;
}
else if (cursor == Cursors.UpArrow)
{
cursorType = CoreCursorType.UpArrow;
}
else if (cursor == Cursors.NeswResize)
{
cursorType = CoreCursorType.SizeNortheastSouthwest;
}
else if (cursor == Cursors.NsResize)
{
cursorType = CoreCursorType.SizeNorthSouth;
}
else if (cursor == Cursors.NwseResize)
{
cursorType = CoreCursorType.SizeNorthwestSoutheast;
}
else if (cursor == Cursors.EwResize)
{
cursorType = CoreCursorType.SizeWestEast;
}
else
{
CoreCursorType GetCoreCursorType(CursorType? type) =>
type switch
{
CursorType.Arrow => CoreCursorType.Arrow,
CursorType.Cross => CoreCursorType.Cross,
CursorType.Fleur => CoreCursorType.SizeAll,
CursorType.Hand1 => CoreCursorType.Hand,
CursorType.Hand2 => CoreCursorType.Hand,
CursorType.QuestionArrow => CoreCursorType.Help,
CursorType.SbUpArrow => CoreCursorType.UpArrow,
CursorType.SbHDoubleArrow => CoreCursorType.SizeWestEast,
CursorType.SbVDoubleArrow => CoreCursorType.SizeNorthSouth,
CursorType.Sizing => CoreCursorType.SizeAll,
CursorType.Watch => CoreCursorType.Wait,
CursorType.Xterm => CoreCursorType.IBeam,
_ => CoreCursorType.Arrow,
};
cursorType = GetCoreCursorType(cursor?.CursorType);

return new Cursor(GetCursorType(coreCursor?.Type));
}
return new CoreCursor(cursorType, 0);
}


public static Cursor ToCursor(this CoreCursor coreCursor) =>
coreCursor?.Type switch
{
CoreCursorType.Arrow => Cursors.Default,
CoreCursorType.Cross => Cursors.Crosshair,
CoreCursorType.Hand => Cursors.Pointer,
CoreCursorType.Help => Cursors.Help,
CoreCursorType.IBeam => Cursors.Text,
CoreCursorType.SizeAll => Cursors.AllScroll,
CoreCursorType.SizeNortheastSouthwest => Cursors.NeswResize,
CoreCursorType.SizeNorthSouth => Cursors.NsResize,
CoreCursorType.SizeNorthwestSoutheast => Cursors.NwseResize,
CoreCursorType.SizeWestEast => Cursors.EwResize,
CoreCursorType.UniversalNo => Cursors.NotAllowed,
CoreCursorType.UpArrow => Cursors.UpArrow,
CoreCursorType.Wait => Cursors.Wait,
_ => Cursors.Default
};
}
}
82 changes: 82 additions & 0 deletions src/Uno.UI.Runtime.Skia.Gtk/UI/Core/Cursors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Gdk;
using System;
using Uno.UI.Runtime.Skia;

namespace Uno.UI.Runtime.Skia.GTK.UI.Core
{
internal static class Cursors
{
private static Cursor _default;
public static Cursor Default => _default;
private static Cursor _crosshair;
public static Cursor Crosshair => _crosshair;
private static Cursor _pointer;
public static Cursor Pointer => _pointer;
private static Cursor _help;
public static Cursor Help => _help;
private static Cursor _text;
public static Cursor Text => _text;
private static Cursor _allScroll;
public static Cursor AllScroll => _allScroll;
private static Cursor _neswResize;
public static Cursor NeswResize => _neswResize;
private static Cursor _nsResize;
public static Cursor NsResize => _nsResize;
private static Cursor _nwseResize;
public static Cursor NwseResize => _nwseResize;
private static Cursor _ewResize;
public static Cursor EwResize => _ewResize;
private static Cursor _notAllowed;
public static Cursor NotAllowed => _notAllowed;
private static Cursor _upArrow;
public static Cursor UpArrow => _upArrow;
private static Cursor _wait;
public static Cursor Wait => _wait;

public static void Reload()
{
// Name based on this: https://developer.gnome.org/gdk3/stable/gdk3-Cursors.html#gdk-cursor-new-from-name
// Fallback based on this list: https://developer.gnome.org/gdk3/stable/gdk3-Cursors.html#GdkCursorType
Set(ref _default, "default", CursorType.Arrow);
Set(ref _crosshair, "crosshair", CursorType.Cross);
Set(ref _pointer, "pointer", CursorType.Hand1);
Set(ref _help, "help", CursorType.QuestionArrow);
Set(ref _text, "text", CursorType.Xterm);
Set(ref _allScroll, "all-scroll", CursorType.Fleur);
Set(ref _neswResize, "nesw-resize");
Set(ref _nsResize, "ns-resize", CursorType.SbVDoubleArrow);
Set(ref _nwseResize, "nwse-resize");
Set(ref _ewResize, "ew-resize", CursorType.SbHDoubleArrow);
Set(ref _notAllowed, "not-allowed");
Set(ref _upArrow, CursorType.SbUpArrow);
Set(ref _wait, "wait", CursorType.Watch);
}

private static void Set(ref Cursor cursor, string name, CursorType fallback = CursorType.Arrow)
{
try
{
var display = GtkHost.Window.Window.Display;
if (display != null)
{
cursor = new Cursor(display, name);
// Library funtion returns null if theme does not contain cursor with name.
if (cursor.Handle != IntPtr.Zero)
{
return;
}
}
}
catch
{
// Fallback cursor should always work, ignore exception.
}
cursor = new Cursor(fallback);
}

private static void Set(ref Cursor cursor, CursorType type)
{
cursor = new Cursor(type);
}
}
}

0 comments on commit 6ce492a

Please sign in to comment.