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