GtkHostUiTheme.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using Gtk;
  2. using Ryujinx.HLE.Ui;
  3. using System.Diagnostics;
  4. namespace Ryujinx.Ui.Applet
  5. {
  6. internal class GtkHostUiTheme : IHostUiTheme
  7. {
  8. private const int RenderSurfaceWidth = 32;
  9. private const int RenderSurfaceHeight = 32;
  10. public string FontFamily { get; private set; }
  11. public ThemeColor DefaultBackgroundColor { get; }
  12. public ThemeColor DefaultForegroundColor { get; }
  13. public ThemeColor DefaultBorderColor { get; }
  14. public ThemeColor SelectionBackgroundColor { get; }
  15. public ThemeColor SelectionForegroundColor { get; }
  16. public GtkHostUiTheme(Window parent)
  17. {
  18. Entry entry = new Entry();
  19. entry.SetStateFlags(StateFlags.Selected, true);
  20. // Get the font and some colors directly from GTK.
  21. FontFamily = entry.PangoContext.FontDescription.Family;
  22. // Get foreground colors from the style context.
  23. var defaultForegroundColor = entry.StyleContext.GetColor(StateFlags.Normal);
  24. var selectedForegroundColor = entry.StyleContext.GetColor(StateFlags.Selected);
  25. DefaultForegroundColor = new ThemeColor((float) defaultForegroundColor.Alpha, (float) defaultForegroundColor.Red, (float) defaultForegroundColor.Green, (float) defaultForegroundColor.Blue);
  26. SelectionForegroundColor = new ThemeColor((float)selectedForegroundColor.Alpha, (float)selectedForegroundColor.Red, (float)selectedForegroundColor.Green, (float)selectedForegroundColor.Blue);
  27. ListBoxRow row = new ListBoxRow();
  28. row.SetStateFlags(StateFlags.Selected, true);
  29. // Request the main thread to render some UI elements to an image to get an approximation for the color.
  30. // NOTE (caian): This will only take the color of the top-left corner of the background, which may be incorrect
  31. // if someone provides a custom style with a gradient or image.
  32. using (var surface = new Cairo.ImageSurface(Cairo.Format.Argb32, RenderSurfaceWidth, RenderSurfaceHeight))
  33. using (var context = new Cairo.Context(surface))
  34. {
  35. context.SetSourceRGBA(1, 1, 1, 1);
  36. context.Rectangle(0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
  37. context.Fill();
  38. // The background color must be from the main Window because entry uses a different color.
  39. parent.StyleContext.RenderBackground(context, 0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
  40. DefaultBackgroundColor = ToThemeColor(surface.Data);
  41. context.SetSourceRGBA(1, 1, 1, 1);
  42. context.Rectangle(0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
  43. context.Fill();
  44. // Use the background color of the list box row when selected as the text box frame color because they are the
  45. // same in the default theme.
  46. row.StyleContext.RenderBackground(context, 0, 0, RenderSurfaceWidth, RenderSurfaceHeight);
  47. DefaultBorderColor = ToThemeColor(surface.Data);
  48. }
  49. // Use the border color as the text selection color.
  50. SelectionBackgroundColor = DefaultBorderColor;
  51. }
  52. private ThemeColor ToThemeColor(byte[] data)
  53. {
  54. Debug.Assert(data.Length == 4 * RenderSurfaceWidth * RenderSurfaceHeight);
  55. // Take the center-bottom pixel of the surface.
  56. int position = 4 * (RenderSurfaceWidth * (RenderSurfaceHeight - 1) + RenderSurfaceWidth / 2);
  57. if (position + 4 > data.Length)
  58. {
  59. return new ThemeColor(1, 0, 0, 0);
  60. }
  61. float a = data[position + 3] / 255.0f;
  62. float r = data[position + 2] / 255.0f;
  63. float g = data[position + 1] / 255.0f;
  64. float b = data[position + 0] / 255.0f;
  65. return new ThemeColor(a, r, g, b);
  66. }
  67. }
  68. }