BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / X11DesktopColors.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Dennis Bartok     (pbartok@novell.com)
24 //      Alexander Olk           (alex.olk@googlemail.com)
25 //
26 //
27
28 using System.Drawing;
29 using System.Runtime.InteropServices;
30 using System.IO;
31 using System;
32
33 namespace System.Windows.Forms {
34         internal class X11DesktopColors {
35                 #region Structs & Enums
36                 [StructLayout(LayoutKind.Sequential)]   
37                 internal struct GdkColorStruct {
38                         internal int pixel;
39                         internal short red;
40                         internal short green;
41                         internal short blue;
42                 }
43
44                 [StructLayout(LayoutKind.Sequential)]   
45                 internal struct GObjectStruct {
46                         public IntPtr Instance;
47                         public IntPtr ref_count;
48                         public IntPtr data;
49                 }
50
51                 [StructLayout(LayoutKind.Sequential)]
52                 internal struct GtkStyleStruct {
53                         internal GObjectStruct obj;
54                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
55                         internal GdkColorStruct[] fg;
56                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
57                         internal GdkColorStruct[] bg;
58                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
59                         internal GdkColorStruct[] light;
60                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
61                         internal GdkColorStruct[] dark;
62                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
63                         internal GdkColorStruct[] mid;
64                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
65                         internal GdkColorStruct[] text;
66                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
67                         internal GdkColorStruct[] baseclr;
68                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
69                         internal GdkColorStruct[] text_aa;              /* Halfway between text/base */
70
71                         internal GdkColorStruct black;
72                         internal GdkColorStruct white;
73
74                         /* TODO: There is more stuff that we will add when we need it*/
75                 }
76
77                 private enum Desktop {
78                         Gtk,
79                         KDE,
80                         Unknown
81                 }
82                 #endregion      // Structs & Enums
83
84                 #region Local Variables
85                 static private Desktop          desktop;
86                 #endregion      // Local Variables
87
88                 #region Constructors
89                 static X11DesktopColors() {
90                         FindDesktopEnvironment();
91                         
92                         switch(desktop) {
93                                 case Desktop.Gtk: {
94                                         //IntPtr                dispmgr;
95                                         //IntPtr                gdkdisplay;
96                                         IntPtr          widget;
97                                         IntPtr          style_ptr;
98                                         GtkStyleStruct  style;
99
100                                         try {
101                                                 GtkInit();
102                                                 //dispmgr =  gdk_display_manager_get ();
103                                                 //gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
104
105                                                 widget = gtk_invisible_new ();
106                                                 gtk_widget_ensure_style (widget);
107                                                 style_ptr = gtk_widget_get_style (widget);
108
109                                                 style = (GtkStyleStruct) Marshal.PtrToStructure (style_ptr, typeof (GtkStyleStruct));
110                                                 
111                                                 ThemeEngine.Current.ColorControl = ColorFromGdkColor (style.bg[0]);
112                                                 ThemeEngine.Current.ColorControlText = ColorFromGdkColor (style.fg[0]);
113                                                 ThemeEngine.Current.ColorControlDark = ColorFromGdkColor (style.dark[0]);
114                                                 ThemeEngine.Current.ColorControlLight = ColorFromGdkColor (style.light[0]);
115                                                 ThemeEngine.Current.ColorControlLightLight = ControlPaint.Light(ColorFromGdkColor (style.light[0]));
116                                                 ThemeEngine.Current.ColorControlDarkDark = ControlPaint.Dark(ColorFromGdkColor (style.dark[0]));
117
118                                                 // We don't want ControlLight and ControlLightLight to disappear on a white background!
119                                                 Color white = Color.FromArgb(255, 255, 255, 255);
120                                                 if (ThemeEngine.Current.ColorControlLight.ToArgb() == white.ToArgb()) {
121                                                         ThemeEngine.Current.ColorControlLight = Color.FromArgb (255, 190, 190, 190);
122                                                 }
123                                                 if (ThemeEngine.Current.ColorControlLightLight.ToArgb() == white.ToArgb()) {
124                                                         ThemeEngine.Current.ColorControlLightLight = Color.FromArgb (255, 220, 220, 220);
125                                                 }
126                                                 widget = gtk_menu_new ();
127                                                 gtk_widget_ensure_style (widget);
128                                                 style_ptr = gtk_widget_get_style (widget);
129
130                                                 style = (GtkStyleStruct) Marshal.PtrToStructure (style_ptr, typeof (GtkStyleStruct));
131
132                                                 ThemeEngine.Current.ColorMenu = ColorFromGdkColor (style.bg [0]);
133                                                 ThemeEngine.Current.ColorMenuText = ColorFromGdkColor (style.text [0]);
134                                         }
135
136                                         catch (DllNotFoundException) {
137                                                 Console.Error.WriteLine("Gtk not found (missing LD_LIBRARY_PATH to libgtk-x11-2.0.so.0?), using built-in colorscheme");
138                                         }
139
140                                         catch {
141                                                 Console.Error.WriteLine("Gtk colorscheme read failure, using built-in colorscheme");
142                                         }
143                                         break;
144                                 }
145                                         
146                                 case Desktop.KDE: {
147                                                 if (! ReadKDEColorsheme() )
148                                                         Console.Error.WriteLine("KDE colorscheme read failure, using built-in colorscheme");
149                                                 break;
150                                         }
151                                         
152                                 default: {
153                                         break;
154                                 }
155                         }
156                 }
157
158                 static void GtkInit ()
159                 {
160                         gtk_init_check (IntPtr.Zero, IntPtr.Zero);
161                 }
162                 #endregion      // Constructors
163
164                 #region Properties
165                 static void FindDesktopEnvironment() {
166                         desktop = Desktop.Gtk;
167                         string session =  Environment.GetEnvironmentVariable("DESKTOP_SESSION");
168                                 
169                         if ( session != null ) {
170                                 session = session.ToUpper( );
171                                         
172                                 if ( session == "DEFAULT" ) {
173                                         string helper = Environment.GetEnvironmentVariable("KDE_FULL_SESSION");
174                                                 
175                                         if ( helper != null )
176                                                 desktop = Desktop.KDE;
177                                 } else
178                                 if ( session.StartsWith("KDE") )
179                                         desktop = Desktop.KDE;
180                         }
181                 }
182                 #endregion      // Properties
183
184                 #region Methods
185                 static internal void Initialize() {
186                         // Do nothing; all is done in our static ctor
187                 }
188
189                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor) {
190                         return Color.FromArgb (255, 
191                                 (gtkcolor.red >> 8)  & 0xff, 
192                                 (gtkcolor.green  >> 8) & 0xff,
193                                 (gtkcolor.blue >> 8) & 0xff );
194                 }
195                 
196                 private static bool ReadKDEColorsheme() {
197                         string full_kdegloabals_filename = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
198                                 + "/"
199                                 + ".kde/share/config/kdeglobals";
200                         
201                         if (!File.Exists(full_kdegloabals_filename)) 
202                                 return false;
203                         
204                         StreamReader sr = new StreamReader(full_kdegloabals_filename);
205                         
206                         string line = sr.ReadLine();
207                         
208                         Color tmp_color;
209                         
210                         while (line != null) {
211                                 line = line.Trim();
212                                 
213                                 if (line.StartsWith( "background=")) {
214                                         tmp_color = GetColorFromKDEString(line);
215                                         
216                                         if (tmp_color != Color.Empty) {
217                                                 ThemeEngine.Current.ColorControl = tmp_color;
218                                                 ThemeEngine.Current.ColorMenu = tmp_color;
219                                         }
220                                 } else
221                                 if (line.StartsWith( "foreground=")) {
222                                         tmp_color = GetColorFromKDEString(line);
223                                         
224                                         if (tmp_color != Color.Empty) {
225                                                 ThemeEngine.Current.ColorControlText = tmp_color;
226                                                 ThemeEngine.Current.ColorMenuText = tmp_color;                                          
227                                         }
228                                 } else
229                                 if (line.StartsWith("selectBackground")) {
230                                         tmp_color = GetColorFromKDEString(line);
231                                         
232                                         if (tmp_color != Color.Empty) {
233                                                 ThemeEngine.Current.ColorHighlight = tmp_color;
234                                         }
235                                 } else
236                                 if (line.StartsWith("selectForeground")) {
237                                         tmp_color = GetColorFromKDEString(line);
238                                         
239                                         if (tmp_color != Color.Empty) {
240                                                 ThemeEngine.Current.ColorHighlightText = tmp_color;
241                                         }
242                                 }
243                                 
244                                 line = sr.ReadLine();
245                         }
246                         
247                         sr.Close();
248                         
249                         return true;
250                 }
251                 
252                 private static Color GetColorFromKDEString(string line) {
253                         string[] split = line.Split(new char[] {'='});
254                         
255                         if (split.Length > 0) {
256                                 line = split[1];
257                                 
258                                 split = line.Split(new char[] {','});
259                                 
260                                 if (split.Length == 3) {
261                                         int r = System.Convert.ToInt32(split[0]);
262                                         int g = System.Convert.ToInt32(split[1]);
263                                         int b = System.Convert.ToInt32(split[2]);
264                                         
265                                         return Color.FromArgb(r, g, b);
266                                 }
267                         }
268                         
269                         return Color.Empty;
270                 }
271                 #endregion      // Methods
272
273                 #region DllImports
274                 const string libgdk = "libgdk-x11-2.0.so.0";
275                 const string libgtk = "libgtk-x11-2.0.so.0";
276                 
277                 [DllImport(libgtk)]
278                 static extern bool gtk_init_check (IntPtr argc, IntPtr argv);
279
280                 [DllImport(libgdk)]
281                 internal static extern IntPtr gdk_display_manager_get ();
282
283                 [DllImport(libgdk)]
284                 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
285
286                 [DllImport(libgtk)]
287                 static extern IntPtr gtk_invisible_new ();
288
289                 [DllImport(libgtk)]
290                 static extern IntPtr gtk_menu_new ();
291
292                 //[DllImport(libgtk)]
293                 //static extern IntPtr gtk_menu_item_new_with_label (string label);
294
295                 [DllImport(libgtk)]
296                 static extern void gtk_widget_ensure_style (IntPtr raw);
297
298                 [DllImport(libgtk)]
299                 static extern IntPtr gtk_widget_get_style (IntPtr raw);
300                 #endregion      // DllImports
301         }
302 }