a1389ca77c36ad96c25bf345afa686fdcd7cc3f8
[mono.git] / mcs / class / System.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 (ThemeEngine.Current.ColorControlLight);
116                                                 ThemeEngine.Current.ColorControlDarkDark = ControlPaint.Dark (ThemeEngine.Current.ColorControlDark);
117
118                                                 // We don't want ControlLight to disappear on a white background!
119                                                 if (ThemeEngine.Current.ColorControlLight.ToArgb () == Color.White.ToArgb ()) {
120                                                         ThemeEngine.Current.ColorControlLight = Color.FromArgb (255, 227, 227, 227);
121                                                 }
122                                                 widget = gtk_menu_new ();
123                                                 gtk_widget_ensure_style (widget);
124                                                 style_ptr = gtk_widget_get_style (widget);
125
126                                                 style = (GtkStyleStruct) Marshal.PtrToStructure (style_ptr, typeof (GtkStyleStruct));
127
128                                                 ThemeEngine.Current.ColorMenu = ColorFromGdkColor (style.bg [0]);
129                                                 ThemeEngine.Current.ColorMenuText = ColorFromGdkColor (style.text [0]);
130                                         }
131
132                                         catch (DllNotFoundException) {
133                                                 Console.Error.WriteLine("Gtk not found (missing LD_LIBRARY_PATH to libgtk-x11-2.0.so.0?), using built-in colorscheme");
134                                         }
135
136                                         catch {
137                                                 Console.Error.WriteLine("Gtk colorscheme read failure, using built-in colorscheme");
138                                         }
139                                         break;
140                                 }
141                                         
142                                 case Desktop.KDE: {
143                                                 if (! ReadKDEColorsheme() )
144                                                         Console.Error.WriteLine("KDE colorscheme read failure, using built-in colorscheme");
145                                                 break;
146                                         }
147                                         
148                                 default: {
149                                         break;
150                                 }
151                         }
152                 }
153
154                 static void GtkInit ()
155                 {
156                         gtk_init_check (IntPtr.Zero, IntPtr.Zero);
157                 }
158                 #endregion      // Constructors
159
160                 #region Properties
161                 static void FindDesktopEnvironment() {
162                         desktop = Desktop.Gtk;
163                         string session =  Environment.GetEnvironmentVariable("DESKTOP_SESSION");
164                                 
165                         if ( session != null ) {
166                                 session = session.ToUpper( );
167                                         
168                                 if ( session == "DEFAULT" ) {
169                                         string helper = Environment.GetEnvironmentVariable("KDE_FULL_SESSION");
170                                                 
171                                         if ( helper != null )
172                                                 desktop = Desktop.KDE;
173                                 } else
174                                 if ( session.StartsWith("KDE") )
175                                         desktop = Desktop.KDE;
176                         }
177                 }
178                 #endregion      // Properties
179
180                 #region Methods
181                 static internal void Initialize() {
182                         // Do nothing; all is done in our static ctor
183                 }
184
185                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor) {
186                         return Color.FromArgb (255, 
187                                 (gtkcolor.red >> 8)  & 0xff, 
188                                 (gtkcolor.green  >> 8) & 0xff,
189                                 (gtkcolor.blue >> 8) & 0xff );
190                 }
191                 
192                 private static bool ReadKDEColorsheme() {
193                         string full_kdegloabals_filename = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
194                                 + "/"
195                                 + ".kde/share/config/kdeglobals";
196                         
197                         if (!File.Exists(full_kdegloabals_filename)) 
198                                 return false;
199                         
200                         StreamReader sr = new StreamReader(full_kdegloabals_filename);
201                         
202                         string line = sr.ReadLine();
203                         
204                         Color tmp_color;
205                         
206                         while (line != null) {
207                                 line = line.Trim();
208                                 
209                                 if (line.StartsWith( "background=")) {
210                                         tmp_color = GetColorFromKDEString(line);
211                                         
212                                         if (tmp_color != Color.Empty) {
213                                                 ThemeEngine.Current.ColorControl = tmp_color;
214                                                 ThemeEngine.Current.ColorMenu = tmp_color;
215                                         }
216                                 } else
217                                 if (line.StartsWith( "foreground=")) {
218                                         tmp_color = GetColorFromKDEString(line);
219                                         
220                                         if (tmp_color != Color.Empty) {
221                                                 ThemeEngine.Current.ColorControlText = tmp_color;
222                                                 ThemeEngine.Current.ColorMenuText = tmp_color;                                          
223                                         }
224                                 } else
225                                 if (line.StartsWith("selectBackground")) {
226                                         tmp_color = GetColorFromKDEString(line);
227                                         
228                                         if (tmp_color != Color.Empty) {
229                                                 ThemeEngine.Current.ColorHighlight = tmp_color;
230                                         }
231                                 } else
232                                 if (line.StartsWith("selectForeground")) {
233                                         tmp_color = GetColorFromKDEString(line);
234                                         
235                                         if (tmp_color != Color.Empty) {
236                                                 ThemeEngine.Current.ColorHighlightText = tmp_color;
237                                         }
238                                 }
239                                 
240                                 line = sr.ReadLine();
241                         }
242                         
243                         sr.Close();
244                         
245                         return true;
246                 }
247                 
248                 private static Color GetColorFromKDEString(string line) {
249                         string[] split = line.Split(new char[] {'='});
250                         
251                         if (split.Length > 0) {
252                                 line = split[1];
253                                 
254                                 split = line.Split(new char[] {','});
255                                 
256                                 if (split.Length == 3) {
257                                         int r = System.Convert.ToInt32(split[0]);
258                                         int g = System.Convert.ToInt32(split[1]);
259                                         int b = System.Convert.ToInt32(split[2]);
260                                         
261                                         return Color.FromArgb(r, g, b);
262                                 }
263                         }
264                         
265                         return Color.Empty;
266                 }
267                 #endregion      // Methods
268
269                 #region DllImports
270                 const string libgdk = "libgdk-x11-2.0.so.0";
271                 const string libgtk = "libgtk-x11-2.0.so.0";
272                 
273                 [DllImport(libgtk)]
274                 static extern bool gtk_init_check (IntPtr argc, IntPtr argv);
275
276                 [DllImport(libgdk)]
277                 internal static extern IntPtr gdk_display_manager_get ();
278
279                 [DllImport(libgdk)]
280                 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
281
282                 [DllImport(libgtk)]
283                 static extern IntPtr gtk_invisible_new ();
284
285                 [DllImport(libgtk)]
286                 static extern IntPtr gtk_menu_new ();
287
288                 //[DllImport(libgtk)]
289                 //static extern IntPtr gtk_menu_item_new_with_label (string label);
290
291                 [DllImport(libgtk)]
292                 static extern void gtk_widget_ensure_style (IntPtr raw);
293
294                 [DllImport(libgtk)]
295                 static extern IntPtr gtk_widget_get_style (IntPtr raw);
296                 #endregion      // DllImports
297         }
298 }