Browse Source

[X11] Implemented icons

pull/2011/head
Nikita Tsukanov 8 years ago
parent
commit
ec682e2e1d
  1. 49
      src/Avalonia.X11/Stubs.cs
  2. 6
      src/Avalonia.X11/X11Framebuffer.cs
  3. 2
      src/Avalonia.X11/X11FramebufferSurface.cs
  4. 85
      src/Avalonia.X11/X11IconLoader.cs
  5. 3
      src/Avalonia.X11/X11Platform.cs
  6. 6
      src/Avalonia.X11/X11Window.cs

49
src/Avalonia.X11/Stubs.cs

@ -14,53 +14,4 @@ namespace Avalonia.X11
public Size DoubleClickSize { get; } = new Size(2, 2);
public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
}
class SystemDialogsStub : ISystemDialogImpl
{
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
{
return Task.FromResult((string[])null);
}
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
{
return Task.FromResult((string)null);
}
}
class IconLoaderStub : IPlatformIconLoader
{
class FakeIcon : IWindowIconImpl
{
private readonly byte[] _data;
public FakeIcon(byte[] data)
{
_data = data;
}
public void Save(Stream outputStream)
{
outputStream.Write(_data, 0, _data.Length);
}
}
public IWindowIconImpl LoadIcon(string fileName)
{
return new FakeIcon(File.ReadAllBytes(fileName));
}
public IWindowIconImpl LoadIcon(Stream stream)
{
var ms = new MemoryStream();
stream.CopyTo(ms);
return new FakeIcon(ms.ToArray());
}
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
var ms = new MemoryStream();
bitmap.Save(ms);
return new FakeIcon(ms.ToArray());
}
}
}

6
src/Avalonia.X11/X11Framebuffer.cs

@ -9,12 +9,14 @@ namespace Avalonia.X11
{
private readonly IntPtr _display;
private readonly IntPtr _xid;
private readonly int _depth;
private IUnmanagedBlob _blob;
public X11Framebuffer(IntPtr display, IntPtr xid, int width, int height, double factor)
public X11Framebuffer(IntPtr display, IntPtr xid, int depth, int width, int height, double factor)
{
_display = display;
_xid = xid;
_depth = depth;
Size = new PixelSize(width, height);
RowBytes = width * 4;
Dpi = new Vector(96, 96) * factor;
@ -35,7 +37,7 @@ namespace Avalonia.X11
image.bitmap_unit = bitsPerPixel;
image.bitmap_bit_order = 0;// LSBFirst;
image.bitmap_pad = bitsPerPixel;
image.depth = 24;
image.depth = _depth;
image.bytes_per_line = RowBytes;
image.bits_per_pixel = bitsPerPixel;
XLockDisplay(_display);

2
src/Avalonia.X11/X11FramebufferSurface.cs

@ -23,7 +23,7 @@ namespace Avalonia.X11
XGetGeometry(_display, _xid, out var root, out var x, out var y, out var width, out var height,
out var bw, out var d);
XUnlockDisplay(_display);
return new X11Framebuffer(_display, _xid, width, height, _scaling());
return new X11Framebuffer(_display, _xid, 24,width, height, _scaling());
}
}
}

85
src/Avalonia.X11/X11IconLoader.cs

@ -0,0 +1,85 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Utilities;
using Avalonia.Visuals.Media.Imaging;
using static Avalonia.X11.XLib;
namespace Avalonia.X11
{
class X11IconLoader : IPlatformIconLoader
{
private readonly X11Info _x11;
public X11IconLoader(X11Info x11)
{
_x11 = x11;
}
IWindowIconImpl LoadIcon(Bitmap bitmap) => new X11IconData(bitmap);
public IWindowIconImpl LoadIcon(string fileName) => LoadIcon(new Bitmap(fileName));
public IWindowIconImpl LoadIcon(Stream stream) => LoadIcon(new Bitmap(stream));
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
var ms = new MemoryStream();
bitmap.Save(ms);
ms.Position = 0;
return LoadIcon(ms);
}
}
unsafe class X11IconData : IWindowIconImpl, IFramebufferPlatformSurface
{
private readonly Bitmap _bitmap;
private int _width;
private int _height;
private uint[] _bdata;
public IntPtr[] Data { get; }
public X11IconData(Bitmap bitmap)
{
_bitmap = bitmap;
_width = Math.Min(_bitmap.PixelSize.Width, 128);
_height = Math.Min(_bitmap.PixelSize.Height, 128);
_bdata = new uint[_width * _height];
fixed (void* ptr = _bdata)
{
var iptr = (int*)ptr;
iptr[0] = _width;
iptr[1] = _height;
}
using(var rt = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>().CreateRenderTarget(new[]{this}))
using (var ctx = rt.CreateDrawingContext(null))
ctx.DrawImage(bitmap.PlatformImpl, 1, new Rect(bitmap.Size),
new Rect(0, 0, _width, _height));
Data = new IntPtr[_width * _height + 2];
Data[0] = new IntPtr(_width);
Data[1] = new IntPtr(_height);
for (var y = 0; y < _height; y++)
{
var r = y * _width;
for (var x = 0; x < _width; x++)
Data[r + x] = new IntPtr(_bdata[r + x]);
}
}
public void Save(Stream outputStream)
{
_bitmap.Save(outputStream);
}
public ILockedFramebuffer Lock()
{
var h = GCHandle.Alloc(_bdata, GCHandleType.Pinned);
return new LockedFramebuffer(h.AddrOfPinnedObject(), new PixelSize(_width, _height), _width * 4,
new Vector(96, 96), PixelFormat.Bgra8888,
() => h.Free());
}
}
}

3
src/Avalonia.X11/X11Platform.cs

@ -43,8 +43,7 @@ namespace Avalonia.X11
.Bind<IStandardCursorFactory>().ToConstant(new X11CursorFactory(Display))
.Bind<IClipboard>().ToConstant(new X11Clipboard(this))
.Bind<IPlatformSettings>().ToConstant(new PlatformSettingsStub())
.Bind<ISystemDialogImpl>().ToConstant(new SystemDialogsStub())
.Bind<IPlatformIconLoader>().ToConstant(new IconLoaderStub())
.Bind<IPlatformIconLoader>().ToConstant(new X11IconLoader(Info))
.Bind<ISystemDialogImpl>().ToConstant(new Gtk3ForeignX11SystemDialog());
X11Screens = Avalonia.X11.X11Screens.Init(this);

6
src/Avalonia.X11/X11Window.cs

@ -800,7 +800,11 @@ namespace Avalonia.X11
public void SetIcon(IWindowIconImpl icon)
{
//TODO
var data = ((X11IconData)icon).Data;
fixed (void* pdata = data)
XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_ICON,
new IntPtr((int)Atom.XA_CARDINAL), 32, PropertyMode.Replace,
pdata, data.Length);
}
public void ShowTaskbarIcon(bool value)

Loading…
Cancel
Save