mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-07-23 13:28:24 +00:00
Branched for 1.0 release.
This commit is contained in:
parent
9eb504eb4e
commit
2870532c78
|
@ -1,4 +1,4 @@
|
||||||
#region --- License ---
|
#region --- License ---
|
||||||
/* Licensed under the MIT/X11 license.
|
/* Licensed under the MIT/X11 license.
|
||||||
* Copyright (c) 2006-2008 the OpenTK Team.
|
* Copyright (c) 2006-2008 the OpenTK Team.
|
||||||
* This notice may not be removed from any source distribution.
|
* This notice may not be removed from any source distribution.
|
||||||
|
@ -65,6 +65,8 @@ namespace Examples.Tutorial
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected override void OnResize(EventArgs e)
|
protected override void OnResize(EventArgs e)
|
||||||
{
|
{
|
||||||
|
base.OnResize(e);
|
||||||
|
|
||||||
GL.Viewport(0, 0, Width, Height);
|
GL.Viewport(0, 0, Width, Height);
|
||||||
|
|
||||||
double aspect_ratio = Width / (double)Height;
|
double aspect_ratio = Width / (double)Height;
|
||||||
|
@ -87,6 +89,8 @@ namespace Examples.Tutorial
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||||
{
|
{
|
||||||
|
base.OnUpdateFrame(e);
|
||||||
|
|
||||||
if (Keyboard[OpenTK.Input.Key.Escape])
|
if (Keyboard[OpenTK.Input.Key.Escape])
|
||||||
{
|
{
|
||||||
this.Exit();
|
this.Exit();
|
||||||
|
@ -103,6 +107,8 @@ namespace Examples.Tutorial
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void OnRenderFrame(FrameEventArgs e)
|
protected override void OnRenderFrame(FrameEventArgs e)
|
||||||
{
|
{
|
||||||
|
base.OnRenderFrame(e);
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
|
||||||
Matrix4 lookat = Matrix4.LookAt(0, 5, 5, 0, 0, 0, 0, 1, 0);
|
Matrix4 lookat = Matrix4.LookAt(0, 5, 5, 0, 0, 0, 0, 1, 0);
|
||||||
|
|
|
@ -37,20 +37,13 @@ namespace Examples.Tests
|
||||||
{
|
{
|
||||||
public static void Main()
|
public static void Main()
|
||||||
{
|
{
|
||||||
const int ThreadCount = 4;
|
const int ThreadCount = 2;
|
||||||
List<Thread> threads = new List<Thread>();
|
List<Thread> threads = new List<Thread>();
|
||||||
|
|
||||||
// launch threads
|
// launch threads
|
||||||
for (int i = 0; i < ThreadCount; i++)
|
for (int i = 0; i < ThreadCount; i++)
|
||||||
{
|
{
|
||||||
Thread t = new Thread(delegate()
|
Thread t = new Thread(RunGame);
|
||||||
{
|
|
||||||
using (Tutorial.T03_Immediate_Mode_Cube game = new Examples.Tutorial.T03_Immediate_Mode_Cube())
|
|
||||||
{
|
|
||||||
Utilities.SetWindowTitle(game);
|
|
||||||
game.Run(30.0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
t.IsBackground = true;
|
t.IsBackground = true;
|
||||||
t.Priority = ThreadPriority.BelowNormal;
|
t.Priority = ThreadPriority.BelowNormal;
|
||||||
t.Start();
|
t.Start();
|
||||||
|
@ -63,5 +56,24 @@ namespace Examples.Tests
|
||||||
t.Join();
|
t.Join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void RunGame()
|
||||||
|
{
|
||||||
|
using (Tutorial.T03_Immediate_Mode_Cube game = new Examples.Tutorial.T03_Immediate_Mode_Cube())
|
||||||
|
{
|
||||||
|
Utilities.SetWindowTitle(game);
|
||||||
|
game.Keyboard.KeyUp += delegate(object sender, OpenTK.Input.KeyboardKeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == OpenTK.Input.Key.Space)
|
||||||
|
{
|
||||||
|
if (game.WindowState == OpenTK.WindowState.Fullscreen)
|
||||||
|
game.WindowState = OpenTK.WindowState.Normal;
|
||||||
|
else
|
||||||
|
game.WindowState = OpenTK.WindowState.Fullscreen;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
game.Run(30.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,935 +0,0 @@
|
||||||
#define NET_2_0
|
|
||||||
|
|
||||||
//
|
|
||||||
// Icon.cs
|
|
||||||
//
|
|
||||||
// Authors:
|
|
||||||
// Dennis Hayes (dennish@Raytek.com)
|
|
||||||
// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
|
|
||||||
// Sanjay Gupta (gsanjay@novell.com)
|
|
||||||
// Peter Dennis Bartok (pbartok@novell.com)
|
|
||||||
// Sebastien Pouliot <sebastien@ximian.com>
|
|
||||||
//
|
|
||||||
// Copyright (C) 2002 Ximian, Inc. http://www.ximian.com
|
|
||||||
// Copyright (C) 2004-2008 Novell, Inc (http://www.novell.com)
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
// a copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
// permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
// the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be
|
|
||||||
// included in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.Permissions;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace OpenTK
|
|
||||||
{
|
|
||||||
#if EXPERIMENTAL
|
|
||||||
#if !NET_2_0
|
|
||||||
[ComVisible(false)]
|
|
||||||
#endif
|
|
||||||
[Serializable]
|
|
||||||
//[Editor("Design.IconEditor, " + Consts.AssemblySystem_Drawing_Design, typeof(Design.UITypeEditor))]
|
|
||||||
[TypeConverter(typeof(IconConverter))]
|
|
||||||
public sealed class Icon : MarshalByRefObject, ISerializable, ICloneable, IDisposable
|
|
||||||
{
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct IconDirEntry
|
|
||||||
{
|
|
||||||
internal byte width;
|
|
||||||
// Width of icon
|
|
||||||
internal byte height;
|
|
||||||
// Height of icon
|
|
||||||
internal byte colorCount;
|
|
||||||
// colors in icon
|
|
||||||
internal byte reserved;
|
|
||||||
// Reserved
|
|
||||||
internal ushort planes;
|
|
||||||
// Color Planes
|
|
||||||
internal ushort bitCount;
|
|
||||||
// Bits per pixel
|
|
||||||
internal uint bytesInRes;
|
|
||||||
// bytes in resource
|
|
||||||
internal uint imageOffset;
|
|
||||||
// position in file
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct IconDir
|
|
||||||
{
|
|
||||||
internal ushort idReserved;
|
|
||||||
// Reserved
|
|
||||||
internal ushort idType;
|
|
||||||
// resource type (1 for icons)
|
|
||||||
internal ushort idCount;
|
|
||||||
// how many images?
|
|
||||||
internal IconDirEntry[] idEntries;
|
|
||||||
// the entries for each image
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct BitmapInfoHeader
|
|
||||||
{
|
|
||||||
internal uint biSize;
|
|
||||||
internal int biWidth;
|
|
||||||
internal int biHeight;
|
|
||||||
internal ushort biPlanes;
|
|
||||||
internal ushort biBitCount;
|
|
||||||
internal uint biCompression;
|
|
||||||
internal uint biSizeImage;
|
|
||||||
internal int biXPelsPerMeter;
|
|
||||||
internal int biYPelsPerMeter;
|
|
||||||
internal uint biClrUsed;
|
|
||||||
internal uint biClrImportant;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct IconImage
|
|
||||||
{
|
|
||||||
internal BitmapInfoHeader iconHeader;
|
|
||||||
//image header
|
|
||||||
internal uint[] iconColors;
|
|
||||||
//colors table
|
|
||||||
internal byte[] iconXOR;
|
|
||||||
// bits for XOR mask
|
|
||||||
internal byte[] iconAND;
|
|
||||||
//bits for AND mask
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct IconInfo
|
|
||||||
{
|
|
||||||
int fIcon;
|
|
||||||
public int xHotspot;
|
|
||||||
public int yHotspot;
|
|
||||||
public IntPtr hbmMask;
|
|
||||||
public IntPtr hbmColor;
|
|
||||||
|
|
||||||
public bool IsIcon
|
|
||||||
{
|
|
||||||
get { return (fIcon == 1); }
|
|
||||||
set { fIcon = (value) ? 1 : 0; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError=true)]
|
|
||||||
static extern bool GetIconInfo(IntPtr hIcon, out IconInfo iconinfo);
|
|
||||||
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError=true)]
|
|
||||||
internal static extern IntPtr CreateIconIndirect([In] ref IconInfo piconinfo);
|
|
||||||
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError=true)]
|
|
||||||
internal static extern bool DestroyIcon(IntPtr hIcon);
|
|
||||||
|
|
||||||
private Size iconSize;
|
|
||||||
private IntPtr handle = IntPtr.Zero;
|
|
||||||
private IconDir iconDir;
|
|
||||||
private ushort id;
|
|
||||||
private IconImage[] imageData;
|
|
||||||
private bool undisposable;
|
|
||||||
private bool disposed;
|
|
||||||
private Bitmap bitmap;
|
|
||||||
|
|
||||||
private Icon()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private Icon(IntPtr handle)
|
|
||||||
{
|
|
||||||
this.handle = handle;
|
|
||||||
if (Configuration.RunningOnUnix)
|
|
||||||
{
|
|
||||||
bitmap = Bitmap.FromHicon(handle);
|
|
||||||
iconSize = new Size(bitmap.Width, bitmap.Height);
|
|
||||||
// FIXME: we need to convert the bitmap into an icon
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IconInfo ii;
|
|
||||||
GetIconInfo(handle, out ii);
|
|
||||||
if (!ii.IsIcon)
|
|
||||||
throw new NotImplementedException("Handle doesn't represent an ICON.");
|
|
||||||
|
|
||||||
// If this structure defines an icon, the hot spot is always in the center of the icon
|
|
||||||
iconSize = new Size(ii.xHotspot * 2, ii.yHotspot * 2);
|
|
||||||
bitmap = (Bitmap)Image.FromHbitmap(ii.hbmColor);
|
|
||||||
}
|
|
||||||
undisposable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(Icon original, int width, int height) : this(original, new Size(width, height))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(Icon original, Size size)
|
|
||||||
{
|
|
||||||
if (original == null)
|
|
||||||
throw new ArgumentException("original");
|
|
||||||
|
|
||||||
iconSize = size;
|
|
||||||
iconDir = original.iconDir;
|
|
||||||
|
|
||||||
int count = iconDir.idCount;
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
imageData = original.imageData;
|
|
||||||
id = UInt16.MaxValue;
|
|
||||||
|
|
||||||
for (ushort i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
IconDirEntry ide = iconDir.idEntries[i];
|
|
||||||
if ((ide.height == size.Height) || (ide.width == size.Width))
|
|
||||||
{
|
|
||||||
id = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a perfect match isn't found we look for the biggest icon *smaller* than specified
|
|
||||||
if (id == UInt16.MaxValue)
|
|
||||||
{
|
|
||||||
int requested = Math.Min(size.Height, size.Width);
|
|
||||||
IconDirEntry best = iconDir.idEntries[0];
|
|
||||||
for (ushort i = 1; i < count; i++)
|
|
||||||
{
|
|
||||||
IconDirEntry ide = iconDir.idEntries[i];
|
|
||||||
if ((ide.height < requested) || (ide.width < requested))
|
|
||||||
{
|
|
||||||
if ((ide.height > best.height) || (ide.width > best.width))
|
|
||||||
id = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// last one, if nothing better can be found
|
|
||||||
if (id == UInt16.MaxValue)
|
|
||||||
id = (ushort)(count - 1);
|
|
||||||
|
|
||||||
iconSize.Height = iconDir.idEntries[id].height;
|
|
||||||
iconSize.Width = iconDir.idEntries[id].width;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
iconSize.Height = size.Height;
|
|
||||||
iconSize.Width = size.Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (original.bitmap != null)
|
|
||||||
bitmap = (Bitmap)original.bitmap.Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(Stream stream) : this(stream, 32, 32)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(Stream stream, int width, int height)
|
|
||||||
{
|
|
||||||
InitFromStreamWithSize(stream, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(string fileName)
|
|
||||||
{
|
|
||||||
using (FileStream fs = File.OpenRead(fileName))
|
|
||||||
{
|
|
||||||
InitFromStreamWithSize(fs, 32, 32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(Type type, string resource)
|
|
||||||
{
|
|
||||||
if (resource == null)
|
|
||||||
throw new ArgumentException("resource");
|
|
||||||
|
|
||||||
using (Stream s = type.Assembly.GetManifestResourceStream(type, resource))
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
{
|
|
||||||
string msg = String.Format("Resource '{0}' was not found.", resource);
|
|
||||||
throw new FileNotFoundException(msg);
|
|
||||||
}
|
|
||||||
InitFromStreamWithSize(s, 32, 32);
|
|
||||||
// 32x32 is default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Icon(SerializationInfo info, StreamingContext context)
|
|
||||||
{
|
|
||||||
MemoryStream dataStream = null;
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
foreach (SerializationEntry serEnum in info)
|
|
||||||
{
|
|
||||||
if (String.Compare(serEnum.Name, "IconData", true) == 0)
|
|
||||||
{
|
|
||||||
dataStream = new MemoryStream((byte[])serEnum.Value);
|
|
||||||
}
|
|
||||||
if (String.Compare(serEnum.Name, "IconSize", true) == 0)
|
|
||||||
{
|
|
||||||
Size iconSize = (Size)serEnum.Value;
|
|
||||||
width = iconSize.Width;
|
|
||||||
height = iconSize.Height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((dataStream != null) && (width == height))
|
|
||||||
{
|
|
||||||
dataStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
InitFromStreamWithSize(dataStream, width, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Icon(string resourceName, bool undisposable)
|
|
||||||
{
|
|
||||||
using (Stream s = typeof(Icon).Assembly.GetManifestResourceStream(resourceName))
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
{
|
|
||||||
string msg = String.Format("Resource '{0}' was not found.", resourceName);
|
|
||||||
throw new FileNotFoundException(msg);
|
|
||||||
}
|
|
||||||
InitFromStreamWithSize(s, 32, 32);
|
|
||||||
// 32x32 is default
|
|
||||||
}
|
|
||||||
this.undisposable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context)
|
|
||||||
{
|
|
||||||
MemoryStream ms = new MemoryStream();
|
|
||||||
Save(ms);
|
|
||||||
si.AddValue("IconSize", this.Size, typeof(Size));
|
|
||||||
si.AddValue("IconData", ms.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NET_2_0
|
|
||||||
public Icon(Stream stream, Size size) : this(stream, size.Width, size.Height)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(string fileName, int width, int height)
|
|
||||||
{
|
|
||||||
using (FileStream fs = File.OpenRead(fileName))
|
|
||||||
{
|
|
||||||
InitFromStreamWithSize(fs, width, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon(string fileName, Size size)
|
|
||||||
{
|
|
||||||
using (FileStream fs = File.OpenRead(fileName))
|
|
||||||
{
|
|
||||||
InitFromStreamWithSize(fs, size.Width, size.Height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
[MonoLimitation("The same icon, SystemIcons.WinLogo, is returned for all file types.")]
|
|
||||||
public static Icon ExtractAssociatedIcon(string filePath)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty(filePath))
|
|
||||||
throw new ArgumentException(Locale.GetText("Null or empty path."), "filePath");
|
|
||||||
if (!File.Exists(filePath))
|
|
||||||
throw new FileNotFoundException(Locale.GetText("Couldn't find specified file."), filePath);
|
|
||||||
|
|
||||||
return SystemIcons.WinLogo;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// SystemIcons requires this
|
|
||||||
if (undisposable)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!disposed)
|
|
||||||
{
|
|
||||||
if (Configuration.RunningOnWindows && (handle != IntPtr.Zero))
|
|
||||||
{
|
|
||||||
DestroyIcon(handle);
|
|
||||||
handle = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
if (bitmap != null)
|
|
||||||
{
|
|
||||||
bitmap.Dispose();
|
|
||||||
bitmap = null;
|
|
||||||
}
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Clone()
|
|
||||||
{
|
|
||||||
return new Icon(this, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
|
|
||||||
public static Icon FromHandle(IntPtr handle)
|
|
||||||
{
|
|
||||||
if (handle == IntPtr.Zero)
|
|
||||||
throw new ArgumentException("handle");
|
|
||||||
|
|
||||||
return new Icon(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveIconImage(BinaryWriter writer, IconImage ii)
|
|
||||||
{
|
|
||||||
BitmapInfoHeader bih = ii.iconHeader;
|
|
||||||
writer.Write(bih.biSize);
|
|
||||||
writer.Write(bih.biWidth);
|
|
||||||
writer.Write(bih.biHeight);
|
|
||||||
writer.Write(bih.biPlanes);
|
|
||||||
writer.Write(bih.biBitCount);
|
|
||||||
writer.Write(bih.biCompression);
|
|
||||||
writer.Write(bih.biSizeImage);
|
|
||||||
writer.Write(bih.biXPelsPerMeter);
|
|
||||||
writer.Write(bih.biYPelsPerMeter);
|
|
||||||
writer.Write(bih.biClrUsed);
|
|
||||||
writer.Write(bih.biClrImportant);
|
|
||||||
|
|
||||||
//now write color table
|
|
||||||
int colCount = ii.iconColors.Length;
|
|
||||||
for (int j = 0; j < colCount; j++)
|
|
||||||
writer.Write(ii.iconColors[j]);
|
|
||||||
|
|
||||||
//now write XOR Mask
|
|
||||||
writer.Write(ii.iconXOR);
|
|
||||||
|
|
||||||
//now write AND Mask
|
|
||||||
writer.Write(ii.iconAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveIconDirEntry(BinaryWriter writer, IconDirEntry ide, uint offset)
|
|
||||||
{
|
|
||||||
writer.Write(ide.width);
|
|
||||||
writer.Write(ide.height);
|
|
||||||
writer.Write(ide.colorCount);
|
|
||||||
writer.Write(ide.reserved);
|
|
||||||
writer.Write(ide.planes);
|
|
||||||
writer.Write(ide.bitCount);
|
|
||||||
writer.Write(ide.bytesInRes);
|
|
||||||
writer.Write((offset == UInt32.MaxValue) ? ide.imageOffset : offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveAll(BinaryWriter writer)
|
|
||||||
{
|
|
||||||
writer.Write(iconDir.idReserved);
|
|
||||||
writer.Write(iconDir.idType);
|
|
||||||
ushort count = iconDir.idCount;
|
|
||||||
writer.Write(count);
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)count; i++)
|
|
||||||
{
|
|
||||||
SaveIconDirEntry(writer, iconDir.idEntries[i], UInt32.MaxValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)count; i++)
|
|
||||||
{
|
|
||||||
SaveIconImage(writer, imageData[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveBestSingleIcon(BinaryWriter writer, int width, int height)
|
|
||||||
{
|
|
||||||
writer.Write(iconDir.idReserved);
|
|
||||||
writer.Write(iconDir.idType);
|
|
||||||
writer.Write((ushort)1);
|
|
||||||
|
|
||||||
// find best entry and save it
|
|
||||||
int best = 0;
|
|
||||||
int bitCount = 0;
|
|
||||||
for (int i = 0; i < iconDir.idCount; i++)
|
|
||||||
{
|
|
||||||
IconDirEntry ide = iconDir.idEntries[i];
|
|
||||||
if ((width == ide.width) && (height == ide.height))
|
|
||||||
{
|
|
||||||
if (ide.bitCount >= bitCount)
|
|
||||||
{
|
|
||||||
bitCount = ide.bitCount;
|
|
||||||
best = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveIconDirEntry(writer, iconDir.idEntries[best], 22);
|
|
||||||
SaveIconImage(writer, imageData[best]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveBitmapAsIcon(BinaryWriter writer)
|
|
||||||
{
|
|
||||||
writer.Write((ushort)0);
|
|
||||||
// idReserved must be 0
|
|
||||||
writer.Write((ushort)1);
|
|
||||||
// idType must be 1
|
|
||||||
writer.Write((ushort)1);
|
|
||||||
// only one icon
|
|
||||||
// when transformed into a bitmap only a single image exists
|
|
||||||
IconDirEntry ide = new IconDirEntry();
|
|
||||||
ide.width = (byte)bitmap.Width;
|
|
||||||
ide.height = (byte)bitmap.Height;
|
|
||||||
ide.colorCount = 0;
|
|
||||||
// 32 bbp == 0, for palette size
|
|
||||||
ide.reserved = 0;
|
|
||||||
// always 0
|
|
||||||
ide.planes = 0;
|
|
||||||
ide.bitCount = 32;
|
|
||||||
ide.imageOffset = 22;
|
|
||||||
// 22 is the first icon position (for single icon files)
|
|
||||||
BitmapInfoHeader bih = new BitmapInfoHeader();
|
|
||||||
bih.biSize = (uint)Marshal.SizeOf(typeof(BitmapInfoHeader));
|
|
||||||
bih.biWidth = bitmap.Width;
|
|
||||||
bih.biHeight = 2 * bitmap.Height;
|
|
||||||
// include both XOR and AND images
|
|
||||||
bih.biPlanes = 1;
|
|
||||||
bih.biBitCount = 32;
|
|
||||||
bih.biCompression = 0;
|
|
||||||
bih.biSizeImage = 0;
|
|
||||||
bih.biXPelsPerMeter = 0;
|
|
||||||
bih.biYPelsPerMeter = 0;
|
|
||||||
bih.biClrUsed = 0;
|
|
||||||
bih.biClrImportant = 0;
|
|
||||||
|
|
||||||
IconImage ii = new IconImage();
|
|
||||||
ii.iconHeader = bih;
|
|
||||||
ii.iconColors = new uint[0];
|
|
||||||
// no palette
|
|
||||||
int xor_size = (((bih.biBitCount * bitmap.Width + 31) & ~31) >> 3) * bitmap.Height;
|
|
||||||
ii.iconXOR = new byte[xor_size];
|
|
||||||
int p = 0;
|
|
||||||
for (int y = bitmap.Height - 1; y >= 0; y--)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < bitmap.Width; x++)
|
|
||||||
{
|
|
||||||
Color c = bitmap.GetPixel(x, y);
|
|
||||||
ii.iconXOR[p++] = c.B;
|
|
||||||
ii.iconXOR[p++] = c.G;
|
|
||||||
ii.iconXOR[p++] = c.R;
|
|
||||||
ii.iconXOR[p++] = c.A;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int and_line_size = (((Width + 31) & ~31) >> 3);
|
|
||||||
// must be a multiple of 4 bytes
|
|
||||||
int and_size = and_line_size * bitmap.Height;
|
|
||||||
ii.iconAND = new byte[and_size];
|
|
||||||
|
|
||||||
ide.bytesInRes = (uint)(bih.biSize + xor_size + and_size);
|
|
||||||
|
|
||||||
SaveIconDirEntry(writer, ide, UInt32.MaxValue);
|
|
||||||
SaveIconImage(writer, ii);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Save(Stream outputStream, int width, int height)
|
|
||||||
{
|
|
||||||
BinaryWriter writer = new BinaryWriter(outputStream);
|
|
||||||
// if we have the icon information then save from this
|
|
||||||
if (iconDir.idEntries != null)
|
|
||||||
{
|
|
||||||
if ((width == -1) && (height == -1))
|
|
||||||
SaveAll(writer);
|
|
||||||
else
|
|
||||||
SaveBestSingleIcon(writer, width, height);
|
|
||||||
} else if (bitmap != null)
|
|
||||||
{
|
|
||||||
// if the icon was created from a bitmap then convert it
|
|
||||||
SaveBitmapAsIcon(writer);
|
|
||||||
}
|
|
||||||
writer.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Save(Stream outputStream)
|
|
||||||
{
|
|
||||||
if (outputStream == null)
|
|
||||||
throw new NullReferenceException("outputStream");
|
|
||||||
|
|
||||||
// save every icons available
|
|
||||||
Save(outputStream, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Bitmap BuildBitmapOnWin32()
|
|
||||||
{
|
|
||||||
Bitmap bmp;
|
|
||||||
|
|
||||||
if (imageData == null)
|
|
||||||
return new Bitmap(32, 32);
|
|
||||||
|
|
||||||
IconImage ii = imageData[id];
|
|
||||||
BitmapInfoHeader bih = ii.iconHeader;
|
|
||||||
int biHeight = bih.biHeight / 2;
|
|
||||||
|
|
||||||
int ncolors = (int)bih.biClrUsed;
|
|
||||||
if ((ncolors == 0) && (bih.biBitCount < 24))
|
|
||||||
ncolors = (int)(1 << bih.biBitCount);
|
|
||||||
|
|
||||||
switch (bih.biBitCount) {
|
|
||||||
case 1:
|
|
||||||
bmp = new Bitmap(bih.biWidth, biHeight, PixelFormat.Format1bppIndexed);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
bmp = new Bitmap(bih.biWidth, biHeight, PixelFormat.Format4bppIndexed);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
bmp = new Bitmap(bih.biWidth, biHeight, PixelFormat.Format8bppIndexed);
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
bmp = new Bitmap(bih.biWidth, biHeight, PixelFormat.Format24bppRgb);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
bmp = new Bitmap(bih.biWidth, biHeight, PixelFormat.Format32bppArgb);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
string msg = String.Format("Unexpected number of bits: {0}", bih.biBitCount);
|
|
||||||
throw new Exception(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bih.biBitCount < 24)
|
|
||||||
{
|
|
||||||
ColorPalette pal = bmp.Palette;
|
|
||||||
// Managed palette
|
|
||||||
for (int i = 0; i < ii.iconColors.Length; i++)
|
|
||||||
{
|
|
||||||
pal.Entries[i] = Color.FromArgb((int)ii.iconColors[i] | unchecked((int)0xff000000u));
|
|
||||||
}
|
|
||||||
bmp.Palette = pal;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bytesPerLine = (int)((((bih.biWidth * bih.biBitCount) + 31) & ~31) >> 3);
|
|
||||||
BitmapData bits = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
|
|
||||||
|
|
||||||
for (int y = 0; y < biHeight; y++)
|
|
||||||
{
|
|
||||||
Marshal.Copy(ii.iconXOR, bytesPerLine * y, (IntPtr)(bits.Scan0.ToInt64() + bits.Stride * (biHeight - 1 - y)), bytesPerLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
bmp.UnlockBits(bits);
|
|
||||||
|
|
||||||
bmp = new Bitmap(bmp);
|
|
||||||
// This makes a 32bpp image out of an indexed one
|
|
||||||
// Apply the mask to make properly transparent
|
|
||||||
bytesPerLine = (int)((((bih.biWidth) + 31) & ~31) >> 3);
|
|
||||||
for (int y = 0; y < biHeight; y++)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < bih.biWidth / 8; x++)
|
|
||||||
{
|
|
||||||
for (int bit = 7; bit >= 0; bit--)
|
|
||||||
{
|
|
||||||
if (((ii.iconAND[y * bytesPerLine + x] >> bit) & 1) != 0)
|
|
||||||
{
|
|
||||||
bmp.SetPixel(x * 8 + 7 - bit, biHeight - y - 1, Color.Transparent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Bitmap GetInternalBitmap()
|
|
||||||
{
|
|
||||||
if (bitmap == null)
|
|
||||||
{
|
|
||||||
if (Configuration.RunningOnUnix)
|
|
||||||
{
|
|
||||||
// Mono's libgdiplus doesn't require to keep the stream alive when loading images
|
|
||||||
using (MemoryStream ms = new MemoryStream())
|
|
||||||
{
|
|
||||||
// save the current icon
|
|
||||||
Save(ms, Width, Height);
|
|
||||||
ms.Position = 0;
|
|
||||||
|
|
||||||
// libgdiplus can now decode icons
|
|
||||||
//bitmap = (Bitmap)Image.LoadFromStream(ms, false);
|
|
||||||
bitmap = (Bitmap)Image.FromStream(ms);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// MS GDI+ ICO codec is more limited than the MS Icon class
|
|
||||||
// so we can't, reliably, get bitmap using it. We need to do this the "slow" way
|
|
||||||
bitmap = BuildBitmapOnWin32();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// note: all bitmaps are 32bits ARGB - no matter what the icon format (bitcount) was
|
|
||||||
public Bitmap ToBitmap()
|
|
||||||
{
|
|
||||||
if (disposed)
|
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
|
||||||
|
|
||||||
// note: we can't return the original image because
|
|
||||||
// (a) we have no control over the bitmap instance we return (i.e. it could be disposed)
|
|
||||||
// (b) the palette, flags won't match MS results. See MonoTests.Imaging.IconCodecTest.
|
|
||||||
// Image16 for the differences
|
|
||||||
return new Bitmap(GetInternalBitmap());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
//is this correct, this is what returned by .Net
|
|
||||||
return "<Icon>";
|
|
||||||
}
|
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public IntPtr Handle
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// note: this handle doesn't survive the lifespan of the icon instance
|
|
||||||
if (!disposed && (handle == IntPtr.Zero))
|
|
||||||
{
|
|
||||||
if (Configuration.RunningOnUnix)
|
|
||||||
{
|
|
||||||
// Hack: access Mono internals to retrieve the NativeObject handle.
|
|
||||||
// handle = GetInternalBitmap().NativeObject;
|
|
||||||
Bitmap bmp = GetInternalBitmap();
|
|
||||||
FieldInfo field = bmp.GetType().GetField("NativeObject",
|
|
||||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
if (field == null)
|
|
||||||
throw new NotSupportedException("Internal OpenTK error. Please report this error at http://www.opentk.com/node/add/project-issue, attaching the stacktrace of the exception.");
|
|
||||||
handle = (IntPtr)field.GetValue(bmp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// remember that this block executes only with MS GDI+
|
|
||||||
IconInfo ii = new IconInfo();
|
|
||||||
ii.IsIcon = true;
|
|
||||||
ii.hbmColor = ToBitmap().GetHbitmap();
|
|
||||||
ii.hbmMask = ii.hbmColor;
|
|
||||||
handle = CreateIconIndirect(ref ii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public int Height
|
|
||||||
{
|
|
||||||
get { return iconSize.Height; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Size Size
|
|
||||||
{
|
|
||||||
get { return iconSize; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public int Width
|
|
||||||
{
|
|
||||||
get { return iconSize.Width; }
|
|
||||||
}
|
|
||||||
|
|
||||||
~Icon()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitFromStreamWithSize(Stream stream, int width, int height)
|
|
||||||
{
|
|
||||||
//read the icon header
|
|
||||||
if (stream == null || stream.Length == 0)
|
|
||||||
throw new System.ArgumentException("The argument 'stream' must be a picture that can be used as a Icon", "stream");
|
|
||||||
|
|
||||||
BinaryReader reader = new BinaryReader(stream);
|
|
||||||
|
|
||||||
//iconDir = new IconDir ();
|
|
||||||
iconDir.idReserved = reader.ReadUInt16();
|
|
||||||
if (iconDir.idReserved != 0)
|
|
||||||
//must be 0
|
|
||||||
throw new System.ArgumentException("Invalid Argument", "stream");
|
|
||||||
|
|
||||||
iconDir.idType = reader.ReadUInt16();
|
|
||||||
if (iconDir.idType != 1)
|
|
||||||
//must be 1
|
|
||||||
throw new System.ArgumentException("Invalid Argument", "stream");
|
|
||||||
|
|
||||||
ushort dirEntryCount = reader.ReadUInt16();
|
|
||||||
ArrayList entries = new ArrayList(dirEntryCount);
|
|
||||||
bool sizeObtained = false;
|
|
||||||
// now read in the IconDirEntry structures
|
|
||||||
for (int i = 0; i < dirEntryCount; i++)
|
|
||||||
{
|
|
||||||
IconDirEntry ide;
|
|
||||||
ide.width = reader.ReadByte();
|
|
||||||
ide.height = reader.ReadByte();
|
|
||||||
ide.colorCount = reader.ReadByte();
|
|
||||||
ide.reserved = reader.ReadByte();
|
|
||||||
ide.planes = reader.ReadUInt16();
|
|
||||||
ide.bitCount = reader.ReadUInt16();
|
|
||||||
ide.bytesInRes = reader.ReadUInt32();
|
|
||||||
ide.imageOffset = reader.ReadUInt32();
|
|
||||||
#if false
|
|
||||||
Console.WriteLine("Entry: {0}", i);
|
|
||||||
Console.WriteLine("\tide.width: {0}", ide.width);
|
|
||||||
Console.WriteLine("\tide.height: {0}", ide.height);
|
|
||||||
Console.WriteLine("\tide.colorCount: {0}", ide.colorCount);
|
|
||||||
Console.WriteLine("\tide.reserved: {0}", ide.reserved);
|
|
||||||
Console.WriteLine("\tide.planes: {0}", ide.planes);
|
|
||||||
Console.WriteLine("\tide.bitCount: {0}", ide.bitCount);
|
|
||||||
Console.WriteLine("\tide.bytesInRes: {0}", ide.bytesInRes);
|
|
||||||
Console.WriteLine("\tide.imageOffset: {0}", ide.imageOffset);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 256x256 icons are decoded as 0x0 (width and height are encoded as BYTE)
|
|
||||||
// and we ignore them just like MS does (at least up to fx 2.0)
|
|
||||||
if ((ide.width == 0) && (ide.height == 0))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int index = entries.Add(ide);
|
|
||||||
|
|
||||||
//is this is the best fit??
|
|
||||||
if (!sizeObtained)
|
|
||||||
{
|
|
||||||
if ((ide.height == height) || (ide.width == width))
|
|
||||||
{
|
|
||||||
this.id = (ushort)index;
|
|
||||||
sizeObtained = true;
|
|
||||||
this.iconSize.Height = ide.height;
|
|
||||||
this.iconSize.Width = ide.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vista 256x256 icons points directly to a PNG bitmap
|
|
||||||
dirEntryCount = (ushort)entries.Count;
|
|
||||||
if (dirEntryCount == 0)
|
|
||||||
throw new Win32Exception(0, "No valid icon entry were found.");
|
|
||||||
|
|
||||||
iconDir.idCount = dirEntryCount;
|
|
||||||
imageData = new IconImage[dirEntryCount];
|
|
||||||
iconDir.idEntries = new IconDirEntry[dirEntryCount];
|
|
||||||
entries.CopyTo(iconDir.idEntries);
|
|
||||||
|
|
||||||
//if we havent found the best match, return the one with the
|
|
||||||
//largest size. Is this approach correct??
|
|
||||||
if (!sizeObtained)
|
|
||||||
{
|
|
||||||
uint largestSize = 0;
|
|
||||||
for (int j = 0; j < dirEntryCount; j++)
|
|
||||||
{
|
|
||||||
if (iconDir.idEntries[j].bytesInRes >= largestSize)
|
|
||||||
{
|
|
||||||
largestSize = iconDir.idEntries[j].bytesInRes;
|
|
||||||
this.id = (ushort)j;
|
|
||||||
this.iconSize.Height = iconDir.idEntries[j].height;
|
|
||||||
this.iconSize.Width = iconDir.idEntries[j].width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//now read in the icon data
|
|
||||||
for (int j = 0; j < dirEntryCount; j++)
|
|
||||||
{
|
|
||||||
IconImage iidata = new IconImage();
|
|
||||||
BitmapInfoHeader bih = new BitmapInfoHeader();
|
|
||||||
stream.Seek(iconDir.idEntries[j].imageOffset, SeekOrigin.Begin);
|
|
||||||
byte[] buffer = new byte[iconDir.idEntries[j].bytesInRes];
|
|
||||||
stream.Read(buffer, 0, buffer.Length);
|
|
||||||
BinaryReader bihReader = new BinaryReader(new MemoryStream(buffer));
|
|
||||||
bih.biSize = bihReader.ReadUInt32();
|
|
||||||
bih.biWidth = bihReader.ReadInt32();
|
|
||||||
bih.biHeight = bihReader.ReadInt32();
|
|
||||||
bih.biPlanes = bihReader.ReadUInt16();
|
|
||||||
bih.biBitCount = bihReader.ReadUInt16();
|
|
||||||
bih.biCompression = bihReader.ReadUInt32();
|
|
||||||
bih.biSizeImage = bihReader.ReadUInt32();
|
|
||||||
bih.biXPelsPerMeter = bihReader.ReadInt32();
|
|
||||||
bih.biYPelsPerMeter = bihReader.ReadInt32();
|
|
||||||
bih.biClrUsed = bihReader.ReadUInt32();
|
|
||||||
bih.biClrImportant = bihReader.ReadUInt32();
|
|
||||||
#if false
|
|
||||||
Console.WriteLine("Entry: {0}", j);
|
|
||||||
Console.WriteLine("\tbih.biSize: {0}", bih.biSize);
|
|
||||||
Console.WriteLine("\tbih.biWidth: {0}", bih.biWidth);
|
|
||||||
Console.WriteLine("\tbih.biHeight: {0}", bih.biHeight);
|
|
||||||
Console.WriteLine("\tbih.biPlanes: {0}", bih.biPlanes);
|
|
||||||
Console.WriteLine("\tbih.biBitCount: {0}", bih.biBitCount);
|
|
||||||
Console.WriteLine("\tbih.biCompression: {0}", bih.biCompression);
|
|
||||||
Console.WriteLine("\tbih.biSizeImage: {0}", bih.biSizeImage);
|
|
||||||
Console.WriteLine("\tbih.biXPelsPerMeter: {0}", bih.biXPelsPerMeter);
|
|
||||||
Console.WriteLine("\tbih.biYPelsPerMeter: {0}", bih.biYPelsPerMeter);
|
|
||||||
Console.WriteLine("\tbih.biClrUsed: {0}", bih.biClrUsed);
|
|
||||||
Console.WriteLine("\tbih.biClrImportant: {0}", bih.biClrImportant);
|
|
||||||
#endif
|
|
||||||
iidata.iconHeader = bih;
|
|
||||||
//Read the number of colors used and corresponding memory occupied by
|
|
||||||
//color table. Fill this memory chunk into rgbquad[]
|
|
||||||
int numColors;
|
|
||||||
switch (bih.biBitCount) {
|
|
||||||
case 1:
|
|
||||||
numColors = 2;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
numColors = 16;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
numColors = 256;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
numColors = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iidata.iconColors = new uint[numColors];
|
|
||||||
for (int i = 0; i < numColors; i++)
|
|
||||||
iidata.iconColors[i] = bihReader.ReadUInt32();
|
|
||||||
|
|
||||||
//XOR mask is immediately after ColorTable and its size is
|
|
||||||
//icon height* no. of bytes per line
|
|
||||||
|
|
||||||
//icon height is half of BITMAPINFOHEADER.biHeight, since it contains
|
|
||||||
//both XOR as well as AND mask bytes
|
|
||||||
int iconHeight = bih.biHeight / 2;
|
|
||||||
|
|
||||||
//bytes per line should should be uint aligned
|
|
||||||
int numBytesPerLine = ((((bih.biWidth * bih.biPlanes * bih.biBitCount) + 31) >> 5) << 2);
|
|
||||||
|
|
||||||
//Determine the XOR array Size
|
|
||||||
int xorSize = numBytesPerLine * iconHeight;
|
|
||||||
iidata.iconXOR = new byte[xorSize];
|
|
||||||
int nread = bihReader.Read(iidata.iconXOR, 0, xorSize);
|
|
||||||
if (nread != xorSize)
|
|
||||||
{
|
|
||||||
string msg = String.Format("{0} data length expected {1}, read {2}", "XOR", xorSize, nread);
|
|
||||||
throw new ArgumentException(msg, "stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Determine the AND array size
|
|
||||||
numBytesPerLine = (int)((((bih.biWidth) + 31) & ~31) >> 3);
|
|
||||||
int andSize = numBytesPerLine * iconHeight;
|
|
||||||
iidata.iconAND = new byte[andSize];
|
|
||||||
nread = bihReader.Read(iidata.iconAND, 0, andSize);
|
|
||||||
if (nread != andSize)
|
|
||||||
{
|
|
||||||
string msg = String.Format("{0} data length expected {1}, read {2}", "AND", andSize, nread);
|
|
||||||
throw new ArgumentException(msg, "stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
imageData[j] = iidata;
|
|
||||||
bihReader.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
//
|
|
||||||
// System.Drawing.IconConverter.cs
|
|
||||||
//
|
|
||||||
// Authors:
|
|
||||||
// Dennis Hayes (dennish@Raytek.com)
|
|
||||||
// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
|
|
||||||
// Sanjay Gupta (gsanjay@novell.com)
|
|
||||||
//
|
|
||||||
// (C) 2002 Ximian, Inc
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
// a copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
// permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
// the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be
|
|
||||||
// included in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace OpenTK
|
|
||||||
{
|
|
||||||
#if EXPERIMENTAL
|
|
||||||
/// <summary>
|
|
||||||
/// Summary description for IconConverter.
|
|
||||||
/// </summary>
|
|
||||||
public class IconConverter : ExpandableObjectConverter
|
|
||||||
{
|
|
||||||
public IconConverter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(System.Byte[]))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if ((destinationType == typeof(System.Byte[])) || (destinationType == typeof(System.String)))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
|
||||||
{
|
|
||||||
byte[] bytes = value as byte[];
|
|
||||||
if (bytes == null)
|
|
||||||
return base.ConvertFrom(context, culture, value);
|
|
||||||
|
|
||||||
MemoryStream ms = new MemoryStream(bytes);
|
|
||||||
|
|
||||||
return new Icon(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
|
||||||
{
|
|
||||||
if ((value is Icon) && (destinationType == typeof(string)))
|
|
||||||
return value.ToString(); else if (value == null && destinationType == typeof(string))
|
|
||||||
return "(none)"; else if (CanConvertTo(null, destinationType))
|
|
||||||
{
|
|
||||||
//came here means destType is byte array ;
|
|
||||||
MemoryStream ms = new MemoryStream();
|
|
||||||
((Icon)value).Save(ms);
|
|
||||||
return ms.GetBuffer();
|
|
||||||
} else
|
|
||||||
return new NotSupportedException("IconConverter can not convert from " + value.GetType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1590,15 +1590,32 @@ XF86VidModeGetGammaRampSize(
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Helper structure for calling XLock/UnlockDisplay
|
||||||
struct XLock : IDisposable
|
struct XLock : IDisposable
|
||||||
{
|
{
|
||||||
readonly IntPtr Display;
|
IntPtr _display;
|
||||||
|
|
||||||
|
public IntPtr Display
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_display == IntPtr.Zero)
|
||||||
|
throw new InvalidOperationException("Internal error (XLockDisplay with IntPtr.Zero). Please report this at http://www.opentk.com/node/add/project-issue/opentk");
|
||||||
|
return _display;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == IntPtr.Zero)
|
||||||
|
throw new ArgumentException();
|
||||||
|
_display = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public XLock(IntPtr display)
|
public XLock(IntPtr display)
|
||||||
: this()
|
: this()
|
||||||
{
|
{
|
||||||
Functions.XLockDisplay(display);
|
|
||||||
Display = display;
|
Display = display;
|
||||||
|
Functions.XLockDisplay(Display);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
|
@ -280,7 +280,10 @@ namespace OpenTK.Platform.X11
|
||||||
IntPtr dummy;
|
IntPtr dummy;
|
||||||
XSizeHints hints = new XSizeHints();
|
XSizeHints hints = new XSizeHints();
|
||||||
|
|
||||||
Functions.XGetWMNormalHints(window.Display, window.WindowHandle, ref hints, out dummy);
|
using (new XLock(window.Display))
|
||||||
|
{
|
||||||
|
Functions.XGetWMNormalHints(window.Display, window.WindowHandle, ref hints, out dummy);
|
||||||
|
}
|
||||||
|
|
||||||
if (min_width > 0 || min_height > 0)
|
if (min_width > 0 || min_height > 0)
|
||||||
{
|
{
|
||||||
|
@ -300,13 +303,15 @@ namespace OpenTK.Platform.X11
|
||||||
else
|
else
|
||||||
hints.flags = (IntPtr)((int)hints.flags & ~(int)XSizeHintsFlags.PMaxSize);
|
hints.flags = (IntPtr)((int)hints.flags & ~(int)XSizeHintsFlags.PMaxSize);
|
||||||
|
|
||||||
|
|
||||||
if (hints.flags != IntPtr.Zero)
|
if (hints.flags != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
// The Metacity team has decided that they won't care about this when clicking the maximize
|
// The Metacity team has decided that they won't care about this when clicking the maximize
|
||||||
// icon, will maximize the window to fill the screen/parent no matter what.
|
// icon, will maximize the window to fill the screen/parent no matter what.
|
||||||
// http://bugzilla.ximian.com/show_bug.cgi?id=80021
|
// http://bugzilla.ximian.com/show_bug.cgi?id=80021
|
||||||
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
|
using (new XLock(window.Display))
|
||||||
|
{
|
||||||
|
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,20 +331,23 @@ namespace OpenTK.Platform.X11
|
||||||
IntPtr atom;
|
IntPtr atom;
|
||||||
//XWindowAttributes attributes;
|
//XWindowAttributes attributes;
|
||||||
|
|
||||||
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
|
using (new XLock(window.Display))
|
||||||
_atom_net_wm_allowed_actions, IntPtr.Zero, new IntPtr(256), false,
|
|
||||||
IntPtr.Zero, out actual_atom, out actual_format, out nitems,
|
|
||||||
out bytes_after, ref prop);
|
|
||||||
if ((long)nitems > 0 && prop != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (long)nitems; i++)
|
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
|
||||||
|
_atom_net_wm_allowed_actions, IntPtr.Zero, new IntPtr(256), false,
|
||||||
|
IntPtr.Zero, out actual_atom, out actual_format, out nitems,
|
||||||
|
out bytes_after, ref prop);
|
||||||
|
if ((long)nitems > 0 && prop != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
atom = (IntPtr)Marshal.ReadIntPtr(prop, i * IntPtr.Size);
|
for (int i = 0; i < (long)nitems; i++)
|
||||||
|
{
|
||||||
|
atom = (IntPtr)Marshal.ReadIntPtr(prop, i * IntPtr.Size);
|
||||||
|
|
||||||
if (atom == _atom_net_wm_action_resize)
|
if (atom == _atom_net_wm_action_resize)
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
Functions.XFree(prop);
|
||||||
}
|
}
|
||||||
Functions.XFree(prop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -362,24 +370,27 @@ namespace OpenTK.Platform.X11
|
||||||
//IntPtr atom;
|
//IntPtr atom;
|
||||||
//XWindowAttributes attributes;
|
//XWindowAttributes attributes;
|
||||||
|
|
||||||
// Test if decorations have been disabled through Motif.
|
using (new XLock(window.Display))
|
||||||
IntPtr motif_hints_atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
|
|
||||||
if (motif_hints_atom != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
// TODO: How to check if MotifWMHints decorations have been really disabled?
|
// Test if decorations have been disabled through Motif.
|
||||||
if (_decorations_hidden)
|
IntPtr motif_hints_atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
|
||||||
|
if (motif_hints_atom != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// TODO: How to check if MotifWMHints decorations have been really disabled?
|
||||||
|
if (_decorations_hidden)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some WMs remove decorations when the transient_for hint is set. Most new ones do not (but those
|
||||||
|
// should obey the Motif hint). Anyway, if this hint is set, we say the decorations have been remove
|
||||||
|
// although there is a slight chance this is not the case.
|
||||||
|
IntPtr transient_for_parent;
|
||||||
|
Functions.XGetTransientForHint(window.Display, window.WindowHandle, out transient_for_parent);
|
||||||
|
if (transient_for_parent != IntPtr.Zero)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some WMs remove decorations when the transient_for hint is set. Most new ones do not (but those
|
|
||||||
// should obey the Motif hint). Anyway, if this hint is set, we say the decorations have been remove
|
|
||||||
// although there is a slight chance this is not the case.
|
|
||||||
IntPtr transient_for_parent;
|
|
||||||
Functions.XGetTransientForHint(window.Display, window.WindowHandle, out transient_for_parent);
|
|
||||||
if (transient_for_parent != IntPtr.Zero)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,15 +406,18 @@ namespace OpenTK.Platform.X11
|
||||||
_decorations_hidden = true;
|
_decorations_hidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
|
using (new XLock(window.Display))
|
||||||
|
|
||||||
// Some WMs remove decorations when this hint is set. Doesn't hurt to try.
|
|
||||||
Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
|
|
||||||
|
|
||||||
if (_decorations_hidden)
|
|
||||||
{
|
{
|
||||||
Functions.XUnmapWindow(this.window.Display, this.Handle);
|
// Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
|
||||||
Functions.XMapWindow(this.window.Display, this.Handle);
|
|
||||||
|
// Some WMs remove decorations when this hint is set. Doesn't hurt to try.
|
||||||
|
Functions.XSetTransientForHint(this.window.Display, this.Handle, this.window.RootWindow);
|
||||||
|
|
||||||
|
if (_decorations_hidden)
|
||||||
|
{
|
||||||
|
Functions.XUnmapWindow(this.window.Display, this.Handle);
|
||||||
|
Functions.XMapWindow(this.window.Display, this.Handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,12 +473,15 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
//if (EnableGnomeDecorations()) { Debug.Print("Activated decorations through gnome."); activated = true; }
|
//if (EnableGnomeDecorations()) { Debug.Print("Activated decorations through gnome."); activated = true; }
|
||||||
|
|
||||||
Functions.XSetTransientForHint(this.window.Display, this.Handle, IntPtr.Zero);
|
using (new XLock(window.Display))
|
||||||
|
|
||||||
if (!_decorations_hidden)
|
|
||||||
{
|
{
|
||||||
Functions.XUnmapWindow(this.window.Display, this.Handle);
|
Functions.XSetTransientForHint(this.window.Display, this.Handle, IntPtr.Zero);
|
||||||
Functions.XMapWindow(this.window.Display, this.Handle);
|
|
||||||
|
if (!_decorations_hidden)
|
||||||
|
{
|
||||||
|
Functions.XUnmapWindow(this.window.Display, this.Handle);
|
||||||
|
Functions.XMapWindow(this.window.Display, this.Handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,19 +489,22 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
bool EnableMotifDecorations()
|
bool EnableMotifDecorations()
|
||||||
{
|
{
|
||||||
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
|
using (new XLock(window.Display))
|
||||||
if (atom != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
//Functions.XDeleteProperty(this.window.Display, this.Handle, atom);
|
IntPtr atom = Functions.XInternAtom(this.window.Display, MOTIF_WM_ATOM, true);
|
||||||
MotifWmHints hints = new MotifWmHints();
|
if (atom != IntPtr.Zero)
|
||||||
hints.flags = (IntPtr)MotifFlags.Decorations;
|
{
|
||||||
hints.decorations = (IntPtr)MotifDecorations.All;
|
//Functions.XDeleteProperty(this.window.Display, this.Handle, atom);
|
||||||
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
|
MotifWmHints hints = new MotifWmHints();
|
||||||
ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
|
hints.flags = (IntPtr)MotifFlags.Decorations;
|
||||||
|
hints.decorations = (IntPtr)MotifDecorations.All;
|
||||||
|
Functions.XChangeProperty(this.window.Display, this.Handle, atom, atom, 32, PropertyMode.Replace,
|
||||||
|
ref hints, Marshal.SizeOf(hints) / IntPtr.Size);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -493,23 +513,26 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
bool EnableGnomeDecorations()
|
bool EnableGnomeDecorations()
|
||||||
{
|
{
|
||||||
// Restore window layer.
|
using (new XLock(window.Display))
|
||||||
//XEvent xev = new XEvent();
|
|
||||||
//xev.ClientMessageEvent.window = this.window.Handle;
|
|
||||||
//xev.ClientMessageEvent.type = XEventName.ClientMessage;
|
|
||||||
//xev.ClientMessageEvent.message_type = Functions.XInternAtom(this.window.Display, Constants.XA_WIN_LAYER, false);
|
|
||||||
//xev.ClientMessageEvent.format = 32;
|
|
||||||
//xev.ClientMessageEvent.ptr1 = (IntPtr)WindowLayer.AboveDock;
|
|
||||||
//Functions.XSendEvent(this.window.Display, this.window.RootWindow, false, (IntPtr)EventMask.SubstructureNotifyMask, ref xev);
|
|
||||||
|
|
||||||
IntPtr atom = Functions.XInternAtom(this.window.Display, Constants.XA_WIN_HINTS, true);
|
|
||||||
if (atom != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
Functions.XDeleteProperty(this.window.Display, this.Handle, atom);
|
// Restore window layer.
|
||||||
return true;
|
//XEvent xev = new XEvent();
|
||||||
}
|
//xev.ClientMessageEvent.window = this.window.Handle;
|
||||||
|
//xev.ClientMessageEvent.type = XEventName.ClientMessage;
|
||||||
|
//xev.ClientMessageEvent.message_type = Functions.XInternAtom(this.window.Display, Constants.XA_WIN_LAYER, false);
|
||||||
|
//xev.ClientMessageEvent.format = 32;
|
||||||
|
//xev.ClientMessageEvent.ptr1 = (IntPtr)WindowLayer.AboveDock;
|
||||||
|
//Functions.XSendEvent(this.window.Display, this.window.RootWindow, false, (IntPtr)EventMask.SubstructureNotifyMask, ref xev);
|
||||||
|
|
||||||
return false;
|
IntPtr atom = Functions.XInternAtom(this.window.Display, Constants.XA_WIN_HINTS, true);
|
||||||
|
if (atom != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Functions.XDeleteProperty(this.window.Display, this.Handle, atom);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -520,27 +543,30 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
static void DeleteIconPixmaps(IntPtr display, IntPtr window)
|
static void DeleteIconPixmaps(IntPtr display, IntPtr window)
|
||||||
{
|
{
|
||||||
IntPtr wmHints_ptr = Functions.XGetWMHints(display, window);
|
using (new XLock(display))
|
||||||
|
|
||||||
if (wmHints_ptr != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
XWMHints wmHints = (XWMHints)Marshal.PtrToStructure(wmHints_ptr, typeof(XWMHints));
|
IntPtr wmHints_ptr = Functions.XGetWMHints(display, window);
|
||||||
XWMHintsFlags flags = (XWMHintsFlags)wmHints.flags.ToInt32();
|
|
||||||
|
|
||||||
if ((flags & XWMHintsFlags.IconPixmapHint) != 0)
|
if (wmHints_ptr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
wmHints.flags = new IntPtr((int)(flags & ~XWMHintsFlags.IconPixmapHint));
|
XWMHints wmHints = (XWMHints)Marshal.PtrToStructure(wmHints_ptr, typeof(XWMHints));
|
||||||
Functions.XFreePixmap(display, wmHints.icon_pixmap);
|
XWMHintsFlags flags = (XWMHintsFlags)wmHints.flags.ToInt32();
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & XWMHintsFlags.IconMaskHint) != 0)
|
if ((flags & XWMHintsFlags.IconPixmapHint) != 0)
|
||||||
{
|
{
|
||||||
wmHints.flags = new IntPtr((int)(flags & ~XWMHintsFlags.IconMaskHint));
|
wmHints.flags = new IntPtr((int)(flags & ~XWMHintsFlags.IconPixmapHint));
|
||||||
Functions.XFreePixmap(display, wmHints.icon_mask);
|
Functions.XFreePixmap(display, wmHints.icon_pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Functions.XSetWMHints(display, window, ref wmHints);
|
if ((flags & XWMHintsFlags.IconMaskHint) != 0)
|
||||||
Functions.XFree(wmHints_ptr);
|
{
|
||||||
|
wmHints.flags = new IntPtr((int)(flags & ~XWMHintsFlags.IconMaskHint));
|
||||||
|
Functions.XFreePixmap(display, wmHints.icon_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
Functions.XSetWMHints(display, window, ref wmHints);
|
||||||
|
Functions.XFree(wmHints_ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,8 +889,11 @@ namespace OpenTK.Platform.X11
|
||||||
// For this reason, we'll also set the icon using XSetWMHints.
|
// For this reason, we'll also set the icon using XSetWMHints.
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
Functions.XDeleteProperty(window.Display, window.WindowHandle, _atom_net_wm_icon);
|
using (new XLock(window.Display))
|
||||||
DeleteIconPixmaps(window.Display, window.WindowHandle);
|
{
|
||||||
|
Functions.XDeleteProperty(window.Display, window.WindowHandle, _atom_net_wm_icon);
|
||||||
|
DeleteIconPixmaps(window.Display, window.WindowHandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -881,27 +910,33 @@ namespace OpenTK.Platform.X11
|
||||||
for (int x = 0; x < bitmap.Width; x++)
|
for (int x = 0; x < bitmap.Width; x++)
|
||||||
data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
|
data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
|
||||||
|
|
||||||
Functions.XChangeProperty(window.Display, window.WindowHandle,
|
using (new XLock(window.Display))
|
||||||
_atom_net_wm_icon, _atom_xa_cardinal, 32,
|
{
|
||||||
PropertyMode.Replace, data, size);
|
Functions.XChangeProperty(window.Display, window.WindowHandle,
|
||||||
|
_atom_net_wm_icon, _atom_xa_cardinal, 32,
|
||||||
|
PropertyMode.Replace, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
// Set XWMHints
|
// Set XWMHints
|
||||||
DeleteIconPixmaps(window.Display, window.WindowHandle);
|
DeleteIconPixmaps(window.Display, window.WindowHandle);
|
||||||
IntPtr wmHints_ptr = Functions.XGetWMHints(window.Display, window.WindowHandle);
|
using (new XLock(window.Display))
|
||||||
|
{
|
||||||
|
IntPtr wmHints_ptr = Functions.XGetWMHints(window.Display, window.WindowHandle);
|
||||||
|
|
||||||
if (wmHints_ptr == IntPtr.Zero)
|
if (wmHints_ptr == IntPtr.Zero)
|
||||||
wmHints_ptr = Functions.XAllocWMHints();
|
wmHints_ptr = Functions.XAllocWMHints();
|
||||||
|
|
||||||
XWMHints wmHints = (XWMHints)Marshal.PtrToStructure(wmHints_ptr, typeof(XWMHints));
|
XWMHints wmHints = (XWMHints)Marshal.PtrToStructure(wmHints_ptr, typeof(XWMHints));
|
||||||
|
|
||||||
wmHints.flags = new IntPtr(wmHints.flags.ToInt32() | (int)(XWMHintsFlags.IconPixmapHint | XWMHintsFlags.IconMaskHint));
|
wmHints.flags = new IntPtr(wmHints.flags.ToInt32() | (int)(XWMHintsFlags.IconPixmapHint | XWMHintsFlags.IconMaskHint));
|
||||||
wmHints.icon_pixmap = Functions.CreatePixmapFromImage(window.Display, bitmap);
|
wmHints.icon_pixmap = Functions.CreatePixmapFromImage(window.Display, bitmap);
|
||||||
wmHints.icon_mask = Functions.CreateMaskFromImage(window.Display, bitmap);
|
wmHints.icon_mask = Functions.CreateMaskFromImage(window.Display, bitmap);
|
||||||
|
|
||||||
Functions.XSetWMHints(window.Display, window.WindowHandle, ref wmHints);
|
Functions.XSetWMHints(window.Display, window.WindowHandle, ref wmHints);
|
||||||
Functions.XFree (wmHints_ptr);
|
Functions.XFree (wmHints_ptr);
|
||||||
|
|
||||||
Functions.XSync(window.Display, false);
|
Functions.XSync(window.Display, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
icon = value;
|
icon = value;
|
||||||
|
@ -941,9 +976,12 @@ namespace OpenTK.Platform.X11
|
||||||
int maximized = 0;
|
int maximized = 0;
|
||||||
bool minimized = false;
|
bool minimized = false;
|
||||||
|
|
||||||
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
|
using (new XLock(window.Display))
|
||||||
_atom_net_wm_state, IntPtr.Zero, new IntPtr(256), false,
|
{
|
||||||
IntPtr.Zero, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
|
Functions.XGetWindowProperty(window.Display, window.WindowHandle,
|
||||||
|
_atom_net_wm_state, IntPtr.Zero, new IntPtr(256), false,
|
||||||
|
IntPtr.Zero, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
|
||||||
|
}
|
||||||
|
|
||||||
if ((long)nitems > 0 && prop != IntPtr.Zero)
|
if ((long)nitems > 0 && prop != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
|
@ -959,7 +997,10 @@ namespace OpenTK.Platform.X11
|
||||||
else if (atom == _atom_net_wm_state_fullscreen)
|
else if (atom == _atom_net_wm_state_fullscreen)
|
||||||
fullscreen = true;
|
fullscreen = true;
|
||||||
}
|
}
|
||||||
Functions.XFree(prop);
|
using (new XLock(window.Display))
|
||||||
|
{
|
||||||
|
Functions.XFree(prop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minimized)
|
if (minimized)
|
||||||
|
@ -986,19 +1027,21 @@ namespace OpenTK.Platform.X11
|
||||||
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
|
Debug.Print("GameWindow {0} changing WindowState from {1} to {2}.", window.WindowHandle.ToString(),
|
||||||
current_state.ToString(), value.ToString());
|
current_state.ToString(), value.ToString());
|
||||||
|
|
||||||
if (current_state == OpenTK.WindowState.Minimized)
|
using (new XLock(window.Display))
|
||||||
Functions.XMapWindow(window.Display, window.WindowHandle);
|
{
|
||||||
else if (current_state == OpenTK.WindowState.Fullscreen)
|
if (current_state == OpenTK.WindowState.Minimized)
|
||||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_remove,
|
Functions.XMapWindow(window.Display, window.WindowHandle);
|
||||||
_atom_net_wm_state_fullscreen,
|
else if (current_state == OpenTK.WindowState.Fullscreen)
|
||||||
IntPtr.Zero);
|
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_remove,
|
||||||
else if (current_state == OpenTK.WindowState.Maximized)
|
_atom_net_wm_state_fullscreen,
|
||||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_toggle,
|
IntPtr.Zero);
|
||||||
_atom_net_wm_state_maximized_horizontal,
|
else if (current_state == OpenTK.WindowState.Maximized)
|
||||||
_atom_net_wm_state_maximized_vertical);
|
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_toggle,
|
||||||
|
_atom_net_wm_state_maximized_horizontal,
|
||||||
Functions.XSync(window.Display, false);
|
_atom_net_wm_state_maximized_vertical);
|
||||||
|
|
||||||
|
Functions.XSync(window.Display, false);
|
||||||
|
}
|
||||||
// We can't resize the window if its border is fixed, so make it resizable first.
|
// We can't resize the window if its border is fixed, so make it resizable first.
|
||||||
bool temporary_resizable = false;
|
bool temporary_resizable = false;
|
||||||
WindowBorder previous_state = WindowBorder;
|
WindowBorder previous_state = WindowBorder;
|
||||||
|
@ -1008,35 +1051,38 @@ namespace OpenTK.Platform.X11
|
||||||
WindowBorder = WindowBorder.Resizable;
|
WindowBorder = WindowBorder.Resizable;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (value)
|
using (new XLock(window.Display))
|
||||||
{
|
{
|
||||||
case OpenTK.WindowState.Normal:
|
switch (value)
|
||||||
Functions.XRaiseWindow(window.Display, window.WindowHandle);
|
{
|
||||||
|
case OpenTK.WindowState.Normal:
|
||||||
|
Functions.XRaiseWindow(window.Display, window.WindowHandle);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OpenTK.WindowState.Maximized:
|
case OpenTK.WindowState.Maximized:
|
||||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||||
_atom_net_wm_state_maximized_horizontal,
|
_atom_net_wm_state_maximized_horizontal,
|
||||||
_atom_net_wm_state_maximized_vertical);
|
_atom_net_wm_state_maximized_vertical);
|
||||||
Functions.XRaiseWindow(window.Display, window.WindowHandle);
|
Functions.XRaiseWindow(window.Display, window.WindowHandle);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OpenTK.WindowState.Minimized:
|
case OpenTK.WindowState.Minimized:
|
||||||
// Todo: multiscreen support
|
// Todo: multiscreen support
|
||||||
Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
|
Functions.XIconifyWindow(window.Display, window.WindowHandle, window.Screen);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OpenTK.WindowState.Fullscreen:
|
case OpenTK.WindowState.Fullscreen:
|
||||||
//_previous_window_border = this.WindowBorder;
|
//_previous_window_border = this.WindowBorder;
|
||||||
//this.WindowBorder = WindowBorder.Hidden;
|
//this.WindowBorder = WindowBorder.Hidden;
|
||||||
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
Functions.SendNetWMMessage(window, _atom_net_wm_state, _atom_add,
|
||||||
_atom_net_wm_state_fullscreen, IntPtr.Zero);
|
_atom_net_wm_state_fullscreen, IntPtr.Zero);
|
||||||
Functions.XRaiseWindow(window.Display, window.WindowHandle);
|
Functions.XRaiseWindow(window.Display, window.WindowHandle);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temporary_resizable)
|
if (temporary_resizable)
|
||||||
|
|
Loading…
Reference in a new issue