Skip to content

Commit

Permalink
Allow mods to customize the window icon on Linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mailaender committed Sep 26, 2021
1 parent 9eab92e commit ca89056
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 0 deletions.
4 changes: 4 additions & 0 deletions OpenRA.Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static class Game
public static CursorManager Cursor;
public static bool HideCursor;

public static IconManager Icon;
static WorldRenderer worldRenderer;
static string modLaunchWrapper;

Expand Down Expand Up @@ -487,6 +488,9 @@ public static void InitializeMod(string mod, Arguments args)
if (!string.IsNullOrEmpty(metadata.WindowTitle))
Renderer.Window.SetWindowTitle(metadata.WindowTitle);

Icon?.Dispose();
Icon = new IconManager(ModData);

PerfHistory.Items["render"].HasNormalTick = false;
PerfHistory.Items["batches"].HasNormalTick = false;
PerfHistory.Items["render_world"].HasNormalTick = false;
Expand Down
62 changes: 62 additions & 0 deletions OpenRA.Game/Graphics/IconManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#region Copyright & License Information
/*
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion

using System;
using OpenRA.FileFormats;

namespace OpenRA.Graphics
{
public sealed class IconManager
{
readonly Sprite icon;
readonly SheetBuilder sheetBuilder;

public IconManager(ModData modData)
{
if (Platform.CurrentPlatform != PlatformType.Linux)
return;

var metadata = modData.Manifest.Metadata;
if (string.IsNullOrEmpty(metadata.WindowIcon))
return;

sheetBuilder = new SheetBuilder(SheetType.BGRA);
var fileSystem = modData.DefaultFileSystem;
using (var stream = fileSystem.Open(metadata.WindowIcon))
icon = sheetBuilder.Add(new Png(stream));

var size = icon.Bounds.Size;
var srcStride = icon.Sheet.Size.Width;
var srcData = icon.Sheet.GetData();
var rgbaData = new byte[4 * size.Width * size.Height];

for (var j = 0; j < size.Height; j++)
{
for (var i = 0; i < size.Width; i++)
{
var src = 4 * (j * srcStride + i);
var dest = 4 * (j * size.Width + i);
Array.Copy(srcData, src, rgbaData, dest, 4);
}
}

Game.Renderer.Window.SetWindowIcon(size, rgbaData);

foreach (var s in sheetBuilder.AllSheets)
s.ReleaseBuffer();
}

public void Dispose()
{
sheetBuilder.Dispose();
}
}
}
3 changes: 3 additions & 0 deletions OpenRA.Game/Graphics/PlatformInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ public interface IPlatformWindow : IDisposable

IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot, bool pixelDouble);
void SetHardwareCursor(IHardwareCursor cursor);

void SetWindowTitle(string title);
void SetWindowIcon(Size size, byte[] data);

void SetRelativeMouseMode(bool mode);
void SetScaleModifier(float scale);

Expand Down
1 change: 1 addition & 0 deletions OpenRA.Game/Manifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class ModMetadata
public string Website;
public string WebIcon32;
public string WindowTitle;
public string WindowIcon;
public bool Hidden;
}

Expand Down
23 changes: 23 additions & 0 deletions OpenRA.Platforms.Default/Sdl2PlatformWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using OpenRA.Primitives;
Expand Down Expand Up @@ -382,6 +383,28 @@ public void SetWindowTitle(string title)
SDL.SDL_SetWindowTitle(window, title);
}

public void SetWindowIcon(Size size, byte[] data)
{
VerifyThreadAffinity();
var surfacePointer = IntPtr.Zero;
try
{
surfacePointer = SDL.SDL_CreateRGBSurface(0, size.Width, size.Height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
if (surfacePointer == IntPtr.Zero)
throw new InvalidDataException($"Failed to set icon: {SDL.SDL_GetError()}");

var iconSurface = (SDL.SDL_Surface)Marshal.PtrToStructure(surfacePointer, typeof(SDL.SDL_Surface));
Marshal.Copy(data, 0, iconSurface.pixels, data.Length);

SDL.SDL_SetWindowIcon(window, surfacePointer);
}
catch
{
if (surfacePointer != IntPtr.Zero)
SDL.SDL_FreeSurface(surfacePointer);
}
}

public void SetRelativeMouseMode(bool mode)
{
if (mode)
Expand Down
1 change: 1 addition & 0 deletions mods/cnc/mod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Metadata:
Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/cnc_32x32.png
WindowTitle: OpenRA - Tiberian Dawn
WindowIcon: icon.png

PackageFormats: Mix

Expand Down
1 change: 1 addition & 0 deletions mods/d2k/mod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Metadata:
Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/d2k_32x32.png
WindowTitle: OpenRA - Dune 2000
WindowIcon: icon.png

PackageFormats: D2kSoundResources

Expand Down
1 change: 1 addition & 0 deletions mods/ra/mod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Metadata:
Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/ra_32x32.png
WindowTitle: OpenRA - Red Alert
WindowIcon: icon.png

PackageFormats: Mix

Expand Down
1 change: 1 addition & 0 deletions mods/ts/mod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Metadata:
Website: https://www.openra.net
WebIcon32: https://www.openra.net/images/icons/ts_32x32.png
WindowTitle: OpenRA - Tiberian Sun
WindowIcon: icon.png

PackageFormats: Mix

Expand Down

0 comments on commit ca89056

Please sign in to comment.