2007-08-28 Jonathan Pobst <monkey@jpobst.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
32 namespace System.Windows.Forms {
33         internal class X11DesktopColors {
34                 #region Structs & Enums
35                 [StructLayout(LayoutKind.Sequential)]   
36                 internal struct GdkColorStruct {
37                         internal int pixel;
38                         internal short red;
39                         internal short green;
40                         internal short blue;
41                 }
42
43                 [StructLayout(LayoutKind.Sequential)]   
44                 internal struct GObjectStruct {
45                         public IntPtr Instance;
46                         public IntPtr ref_count;
47                         public IntPtr data;
48                 }
49
50                 [StructLayout(LayoutKind.Sequential)]
51                 internal struct GtkStyleStruct {
52                         internal GObjectStruct obj;
53                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
54                         internal GdkColorStruct[] fg;
55                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
56                         internal GdkColorStruct[] bg;
57                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
58                         internal GdkColorStruct[] light;
59                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
60                         internal GdkColorStruct[] dark;
61                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
62                         internal GdkColorStruct[] mid;
63                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
64                         internal GdkColorStruct[] text;
65                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
66                         internal GdkColorStruct[] baseclr;
67                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
68                         internal GdkColorStruct[] text_aa;              /* Halfway between text/base */
69
70                         internal GdkColorStruct black;
71                         internal GdkColorStruct white;
72
73                         /* TODO: There is more stuff that we will add when we need it*/
74                 }
75
76                 private enum Desktop {
77                         Gtk,
78                         KDE,
79                         Unknown
80                 }
81                 #endregion      // Structs & Enums
82
83                 #region Local Variables
84                 static private Desktop          desktop;
85                 #endregion      // Local Variables
86
87                 #region Constructors
88                 static X11DesktopColors() {
89                         FindDesktopEnvironment();
90                         
91                         switch(desktop) {
92                                 case Desktop.Gtk: {
93                                         //IntPtr                dispmgr;
94                                         //IntPtr                gdkdisplay;
95                                         IntPtr          widget;
96                                         IntPtr          style_ptr;
97                                         GtkStyleStruct  style;
98
99                                         try {
100                                                 gtk_init_check (IntPtr.Zero, IntPtr.Zero);
101                                                 //dispmgr =  gdk_display_manager_get ();
102                                                 //gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
103
104                                                 widget = gtk_invisible_new ();
105                                                 gtk_widget_ensure_style (widget);
106                                                 style_ptr = gtk_widget_get_style (widget);
107
108                                                 style = (GtkStyleStruct) Marshal.PtrToStructure (style_ptr, typeof (GtkStyleStruct));
109                                                 
110                                                 ThemeEngine.Current.ColorControl = ColorFromGdkColor (style.bg[0]);
111                                                 ThemeEngine.Current.ColorControlText = ColorFromGdkColor (style.fg[0]);
112                                                 ThemeEngine.Current.ColorControlDark = ColorFromGdkColor (style.dark[0]);
113                                                 ThemeEngine.Current.ColorControlLight = ColorFromGdkColor (style.light[0]);
114                                                 ThemeEngine.Current.ColorControlLightLight = ControlPaint.Light(ColorFromGdkColor (style.light[0]));
115                                                 ThemeEngine.Current.ColorControlDarkDark = ControlPaint.Dark(ColorFromGdkColor (style.dark[0]));
116
117                                                 widget = gtk_menu_new ();
118                                                 gtk_widget_ensure_style (widget);
119                                                 style_ptr = gtk_widget_get_style (widget);
120
121                                                 style = (GtkStyleStruct) Marshal.PtrToStructure (style_ptr, typeof (GtkStyleStruct));
122
123                                                 ThemeEngine.Current.ColorMenu = ColorFromGdkColor (style.bg [0]);
124                                                 ThemeEngine.Current.ColorMenuText = ColorFromGdkColor (style.text [0]);
125                                         }
126
127                                         catch (DllNotFoundException) {
128                                                 Console.Error.WriteLine("Gtk not found (missing LD_LIBRARY_PATH to libgtk-x11-2.0.so.0?), using built-in colorscheme");
129                                         }
130
131                                         catch {
132                                                 Console.Error.WriteLine("Gtk colorscheme read failure, using built-in colorscheme");
133                                         }
134                                         break;
135                                 }
136                                         
137                                 case Desktop.KDE: {
138                                                 if (! ReadKDEColorsheme() )
139                                                         Console.Error.WriteLine("KDE colorscheme read failure, using built-in colorscheme");
140                                                 break;
141                                         }
142                                         
143                                 default: {
144                                         break;
145                                 }
146                         }
147                 }
148                 #endregion      // Constructors
149
150                 #region Properties
151                 static void FindDesktopEnvironment() {
152                         desktop = Desktop.Gtk;
153                         string session =  Environment.GetEnvironmentVariable("DESKTOP_SESSION");
154                                 
155                         if ( session != null ) {
156                                 session = session.ToUpper( );
157                                         
158                                 if ( session == "DEFAULT" ) {
159                                         string helper = Environment.GetEnvironmentVariable("KDE_FULL_SESSION");
160                                                 
161                                         if ( helper != null )
162                                                 desktop = Desktop.KDE;
163                                 } else
164                                 if ( session.StartsWith("KDE") )
165                                         desktop = Desktop.KDE;
166                         }
167                 }
168                 #endregion      // Properties
169
170                 #region Methods
171                 static internal void Initialize() {
172                         // Do nothing; all is done in our static ctor
173                 }
174
175                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor) {
176                         return Color.FromArgb (255, 
177                                 (gtkcolor.red >> 8)  & 0xff, 
178                                 (gtkcolor.green  >> 8) & 0xff,
179                                 (gtkcolor.blue >> 8) & 0xff );
180                 }
181                 
182                 private static bool ReadKDEColorsheme() {
183                         string full_kdegloabals_filename = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
184                                 + "/"
185                                 + ".kde/share/config/kdeglobals";
186                         
187                         if (!File.Exists(full_kdegloabals_filename)) 
188                                 return false;
189                         
190                         StreamReader sr = new StreamReader(full_kdegloabals_filename);
191                         
192                         string line = sr.ReadLine();
193                         
194                         Color tmp_color;
195                         
196                         while (line != null) {
197                                 line = line.Trim();
198                                 
199                                 if (line.StartsWith( "background=")) {
200                                         tmp_color = GetColorFromKDEString(line);
201                                         
202                                         if (tmp_color != Color.Empty) {
203                                                 ThemeEngine.Current.ColorControl = tmp_color;
204                                                 ThemeEngine.Current.ColorMenu = tmp_color;
205                                         }
206                                 } else
207                                 if (line.StartsWith( "foreground=")) {
208                                         tmp_color = GetColorFromKDEString(line);
209                                         
210                                         if (tmp_color != Color.Empty) {
211                                                 ThemeEngine.Current.ColorControlText = tmp_color;
212                                                 ThemeEngine.Current.ColorMenuText = tmp_color;                                          
213                                         }
214                                 } else
215                                 if (line.StartsWith("selectBackground")) {
216                                         tmp_color = GetColorFromKDEString(line);
217                                         
218                                         if (tmp_color != Color.Empty) {
219                                                 ThemeEngine.Current.ColorHighlight = tmp_color;
220                                         }
221                                 } else
222                                 if (line.StartsWith("selectForeground")) {
223                                         tmp_color = GetColorFromKDEString(line);
224                                         
225                                         if (tmp_color != Color.Empty) {
226                                                 ThemeEngine.Current.ColorHighlightText = tmp_color;
227                                         }
228                                 }
229                                 
230                                 line = sr.ReadLine();
231                         }
232                         
233                         sr.Close();
234                         
235                         return true;
236                 }
237                 
238                 private static Color GetColorFromKDEString(string line) {
239                         string[] split = line.Split(new char[] {'='});
240                         
241                         if (split.Length > 0) {
242                                 line = split[1];
243                                 
244                                 split = line.Split(new char[] {','});
245                                 
246                                 if (split.Length == 3) {
247                                         int r = System.Convert.ToInt32(split[0]);
248                                         int g = System.Convert.ToInt32(split[1]);
249                                         int b = System.Convert.ToInt32(split[2]);
250                                         
251                                         return Color.FromArgb(r, g, b);
252                                 }
253                         }
254                         
255                         return Color.Empty;
256                 }
257                 #endregion      // Methods
258
259                 #region DllImports
260                 const string libgdk = "libgdk-x11-2.0.so.0";
261                 const string libgtk = "libgtk-x11-2.0.so.0";
262                 
263                 [DllImport(libgtk)]
264                 static extern bool gtk_init_check (IntPtr argc, IntPtr argv);
265
266                 [DllImport(libgdk)]
267                 internal static extern IntPtr gdk_display_manager_get ();
268
269                 [DllImport(libgdk)]
270                 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
271
272                 [DllImport(libgtk)]
273                 static extern IntPtr gtk_invisible_new ();
274
275                 [DllImport(libgtk)]
276                 static extern IntPtr gtk_menu_new ();
277
278                 //[DllImport(libgtk)]
279                 //static extern IntPtr gtk_menu_item_new_with_label (string label);
280
281                 [DllImport(libgtk)]
282                 static extern void gtk_widget_ensure_style (IntPtr raw);
283
284                 [DllImport(libgtk)]
285                 static extern IntPtr gtk_widget_get_style (IntPtr raw);
286                 #endregion      // DllImports
287         }
288 }