-
-
Save endolith/74192 to your computer and use it in GitHub Desktop.
| This is a Python script to extract GNOME/GTK's color scheme and apply it to Wine, so that the themes (approximately) match. | |
| Instructions: | |
| 1. Set your Gnome theme as you would like it | |
| 2. Run with a command like "python wine_colors_from_gtk.py" | |
| 3. Restart any apps running in Wine. They should match the Gnome theme colors now. | |
| Better description with screenshots here: http://www.endolith.com/wordpress/2008/08/03/wine-colors/ | |
| This is also stored on https://code.launchpad.net/~endolith/+junk/wine-color-scraper | |
| Just trying out gist.github.com... | |
| To do: | |
| * Needs to separate out scrapers for each GTK engine where necessary. (Can't an interface for this just be built into the engines instead?) | |
| * Copy Gnome fonts as well as colors. (Not sure where Wine stores these settings.) | |
| * Something would need to call this script every time the Gnome theme is changed. | |
| Everything else is working for me. | |
| Other previous discussions: | |
| http://ubuntuforums.org/showthread.php?t=55286&page=3#29 | |
| http://ubuntuforums.org/showthread.php?t=878068 | |
| http://www.mail-archive.com/[email protected]/msg16400.html | |
| http://www.mail-archive.com/[email protected]/msg12076.html | |
| http://www.wine-doors.org/trac/ticket/411 | |
| wineconfig.py and winewrite.py scripts in Guidance package for KDE do the same things: | |
| http://kde-guidance.sourcearchive.com/documentation/0.8.0-0ubuntu5/dir_b125788d4a71372d5142465501c18d05.html | |
| Similar code is built into Mozilla: | |
| http://www.google.com/codesearch/p?hl=en#e_ObwTAVPyo/widget/src/gtk2/nsLookAndFeel.cpp&q=nsLookAndFeel.cpp | |
| Will be integrated into Wine Doors? http://www.wine-doors.org/trac/changeset/1536 | |
| All of Wine's 31 possible user.reg color values | |
| Asterisk * next to comment if I've found a value that works for most themes | |
| Question mark ? next to comment if not sure or can't find anywhere to scrape from | |
| Some descriptions: | |
| http://www.quimp.net/gamemaker/system-colors | |
| http://www.endolith.com/wordpress/2008/08/03/wine-colors/ | |
| http://support.microsoft.com/kb/58336 | |
| http://msdn.microsoft.com/en-us/library/system.drawing.systemcolors_properties(VS.80).aspx | |
| TitleText Active title bar text | |
| ActiveTitle Left end of active title bar | |
| GradientActiveTitle Right end of active title bar | |
| ActiveBorder Active window border | |
| InactiveTitleText Inactive title bar text | |
| InactiveTitle Left end of inactive title bar | |
| GradientInactiveTitle Right end of inactive title bar | |
| InactiveBorder Inactive window border | |
| AppWorkSpace Background color of multiple-document interface | |
| Background Desktop solid color | |
| ButtonText Button/tab text and glyphs | |
| ButtonHilight Outermost button higlight / Grayed-out button text shadow | |
| ButtonLight Inner button highlight, usually same as ButtonFace | |
| ButtonFace Background for buttons and all 3D objects | |
| ButtonAlternateFace ??? | |
| ButtonShadow Shadows of buttons / Grayed-out button text | |
| ButtonDkShadow Outermost shadow of buttons | |
| GrayText Grayed out text in windows, like labels for unavailable widgets | |
| Hilight Background of selected text | |
| HilightText Selected text | |
| HotTrackingColor Single-click navigation hover color | |
| InfoText ToolTip text | |
| InfoWindow ToolTip background | |
| Menu Background for menus, also background for menu bars in 3D mode | |
| MenuBar Background for menu bars - rarely seen due to 3D menus | |
| MenuHilight Highlight for flat menus - in 3D mode, Hilight is used instead | |
| MenuText Menu text | |
| Scrollbar Background color of scrollbar, but only in some apps | |
| Window Background color of notepad, for instance | |
| WindowFrame Glow around focused widget | |
| WindowText Text in notepad, for instance | |
| These were all found by trial and error. Please point out any mistakes. | |
| 2011-04: I use Windows 7 as my main OS now, so I won't be making many updates to this script. Fork it and improve it! | |
| MIT License | |
| Copyright (c) 2009 [email protected] | |
| Permission is hereby granted, free of charge, to any person obtaining a copy | |
| of this software and associated documentation files (the "Software"), to deal | |
| in the Software without restriction, including without limitation the rights | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| copies of the Software, and to permit persons to whom the Software is | |
| furnished to do so, subject to the following conditions: | |
| The above copyright notice and this permission notice shall be included in all | |
| copies or substantial portions of the Software. | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| SOFTWARE. |
| #!/usr/bin/env python | |
| # Scrape colors from GTK and import them into Wine through the registry | |
| # | |
| # [email protected] 2009-02-06 | |
| # | |
| # Based on script by KillerKiwi [Ubuntu Forums] October 29th, 2007 | |
| # http://ubuntuforums.org/showthread.php?t=55286&page=3#23 | |
| # | |
| # which is based on patch by Johannes Roith [Mono-winforms-list] Wed, 27 Aug 2003 | |
| # http://lists.ximian.com/pipermail/mono-winforms-list/2003-August/000469.html | |
| import pygtk | |
| import gtk | |
| import os | |
| from tempfile import NamedTemporaryFile | |
| from gconf import Client | |
| import re | |
| # TODO: command line switch | |
| debug_mode = False | |
| def format_color_string(Color): | |
| """ Convert 48-bit gdk.Color to 24-bit 'RRR GGG BBB' triple. """ | |
| if type(Color) is gtk.gdk.Color: | |
| return '%s %s %s' % (Color.red/256, Color.green/256, Color.blue/256) | |
| else: | |
| print('Not a GdkColor: ' + str(Color)) | |
| return None | |
| def format_hex_color(color): | |
| """ Convert from hex color string to decimal 'RRR GGG BBB' triple. """ | |
| if re.match('^#[0-9a-fA-F]{12}$', color): | |
| r, g, b = color[1:3], color[5:7], color[9:11] #rrrrggggbbbb | |
| elif re.match('^#[0-9a-fA-F]{6}$', color): | |
| r, g, b = color[1:3], color[3:5], color[5:7] #RRGGBB | |
| elif re.match('^#[0-9a-fA-F]{3}$', color): | |
| r, g, b = color[1]*2, color[2]*2, color[3]*2 #09C becomes 0099CC. | |
| else: | |
| print('Cannot understand color string format: ' + str(color)) | |
| return None | |
| return '%s %s %s' % (int(r,16), int(g,16), int(b,16)) | |
| # TODO: fonts | |
| # Get some colors from GTK | |
| # gtk.Style object: | |
| # http://www.moeraki.com/pygtkreference/pygtk2reference/class-gtkstyle.html | |
| # Create a window to scrape colors from | |
| window = gtk.Window() | |
| button = gtk.Button() | |
| vbox = gtk.VBox() | |
| vbox.add(button) | |
| scrollbar = gtk.VScrollbar() | |
| vbox.add(scrollbar) | |
| menubar = gtk.MenuBar() | |
| menuitem = gtk.MenuItem() | |
| menubar.add(menuitem) | |
| vbox.add(menubar) | |
| window.add(vbox) | |
| # On show_all(), these are all converted from gtk.Style objects with wrong | |
| # colors into __main__.EngineStyle objects with correct colors. | |
| window.show_all() | |
| # Tooltips | |
| # http://www.daa.com.au/pipermail/pygtk/2005-November/011353.html | |
| tooltip = gtk.Window() | |
| tooltip.set_name('gtk-tooltips') | |
| tooltip.show_all() | |
| # Mappings for all the color values (described in readme.txt) | |
| # TODO: Need to mark which colors do not work with which themes and double-check EVERYTHING | |
| # * = Confirmed to work exactly for all themes (except Darklooks) | |
| # + = Not perfect, but close? | |
| # ? = Nothing to scrape? - Chose something similar | |
| gtk_colors = { | |
| # Title bars can't be accessed from PyGTK(?) so I just guessed to | |
| # make it work reasonably well with themes like Human. | |
| # Default Windows theme: Darker on left, light on right | |
| 'TitleText': window.style.white , #? White since we're guessing on dark selection color for titlebar | |
| 'InactiveTitleText': window.style.white , #? White since we're guessing on dark selection color for titlebar | |
| 'ActiveTitle': window.style.dark[gtk.STATE_SELECTED] , #? Guess on selection color like Clearlooks | |
| 'InactiveTitle': window.style.dark[gtk.STATE_NORMAL] , #? Darker color for gradient | |
| 'GradientActiveTitle': window.style.light[gtk.STATE_SELECTED], #? Lighter version for gradient | |
| 'GradientInactiveTitle': window.style.base[gtk.STATE_NORMAL] , #? Guess on base color | |
| 'ActiveBorder': button.style.bg[gtk.STATE_INSENSITIVE], #? Same as ButtonFace like Clearlooks | |
| 'InactiveBorder': button.style.bg[gtk.STATE_INSENSITIVE], #? Same as ButtonFace | |
| 'AppWorkSpace': window.style.base[gtk.STATE_NORMAL], #? MDI not used in GTK; use same color as Window, like Glade | |
| 'Background': None , #* Scraped from gconf below | |
| 'ButtonText': button.style.fg[gtk.STATE_NORMAL] , #* | |
| 'ButtonHilight': button.style.light[gtk.STATE_INSENSITIVE], #* | |
| 'ButtonLight': button.style.bg[gtk.STATE_INSENSITIVE] , #* Usually same as ButtonFace? | |
| 'ButtonFace': button.style.bg[gtk.STATE_INSENSITIVE] , #* | |
| 'ButtonAlternateFace': button.style.bg[gtk.STATE_INSENSITIVE] , #* Set to same as ButtonFace for now | |
| 'ButtonShadow': button.style.dark[gtk.STATE_INSENSITIVE] , #* | |
| 'ButtonDkShadow': button.style.black , #* | |
| 'GrayText': window.style.fg[gtk.STATE_INSENSITIVE], #* | |
| 'Hilight': window.style.base[gtk.STATE_SELECTED] , #* | |
| 'HilightText': window.style.fg[gtk.STATE_SELECTED] , #* | |
| 'HotTrackingColor': window.style.light[gtk.STATE_NORMAL] , #? Doesn't seem to exist in GTK; use lighter ButtonFace color, like CompizConfig Settings Manager | |
| 'InfoText': tooltip.style.fg[gtk.STATE_NORMAL], | |
| 'InfoWindow': tooltip.style.bg[gtk.STATE_NORMAL], | |
| 'Menu': menuitem.style.light[gtk.STATE_ACTIVE], | |
| 'MenuBar': menubar.style.bg[gtk.STATE_NORMAL] , | |
| 'MenuHilight': menuitem.style.bg[gtk.STATE_SELECTED] , | |
| 'MenuText': menuitem.style.fg[gtk.STATE_NORMAL] , | |
| 'Scrollbar': scrollbar.style.bg[gtk.STATE_ACTIVE], #+ Not right, even though gtk.RcStyle documentation says it is | |
| 'Window': window.style.base[gtk.STATE_NORMAL] , #* base or bg? | |
| 'WindowFrame': button.style.mid[gtk.STATE_SELECTED], #+ bg selected or light selected? | |
| 'WindowText': window.style.text[gtk.STATE_NORMAL] , #* | |
| } | |
| # As far as I know, there is no way to programmatically extract colors from GTK for the same elements in any engine, so we'll have to add engine-specific scrapers. | |
| # "Engines can and do whatever they want with the colors from the rc file ... A theme includes both the colors, and the code that paints using colors. So the code can use any of the colors it wants." | |
| # TODO: something like this: | |
| print "GTK engine:", | |
| if 'ClearlooksStyle' in repr(window.style): # kludgy, but works | |
| print "Clearlooks" | |
| # assign different colors to some elements | |
| elif 'MurrineStyle' in repr(window.style): | |
| print "Murrine" | |
| gtk_colors.update({'Window': window.style.base[gtk.STATE_NORMAL]}) | |
| elif 'CruxStyle' in repr(window.style): | |
| print "Crux" | |
| else: | |
| print "unknown" | |
| # QtPixbufStyle GlideStyle PixbufStyle HcStyle IndustrialStyle MistStyle ThiniceStyle darklooks = gtk.Style | |
| # Create list of formatted color value pair strings | |
| # Windows registry values are in the form "name"="data" with no spaces | |
| color_pairs = [] | |
| for name, data in gtk_colors.iteritems(): | |
| if data: | |
| color_pairs.append('"%s"="%s"' % (name, format_color_string(data))) | |
| # Get Desktop background color from Gnome's GConf, append to color pair list | |
| c = Client() | |
| desktop_color = format_hex_color(c.get_value('/desktop/gnome/background/primary_color')) | |
| if desktop_color: | |
| color_pairs.append('"Background"="%s"' % desktop_color) | |
| # TODO: Get Desktop background color from Xfce | |
| # import xfce4? | |
| # "i see, yes xfce does have something like that. you find it in /home/$USER/.config/xfce4/mcs_settings/desktop.xml" | |
| # Create a temporary Windows .reg registry file with the new values | |
| # I'm not sure of the meaning of S-1-5-4. This may not work on all systems? | |
| # I do know it is the same number under multiple accounts. | |
| try: | |
| wineprefix = os.environ['WINEPREFIX'] | |
| except KeyError: | |
| wineprefix = os.path.join(os.environ['HOME'],'.wine') | |
| winetemp = os.path.join(wineprefix, 'drive_c','windows','temp') | |
| f = NamedTemporaryFile(prefix = 'winecolors', suffix = '.reg', dir = winetemp, mode = 'w+') | |
| f.write("""REGEDIT4 | |
| [HKEY_USERS\S-1-5-4\Control Panel] | |
| [HKEY_USERS\S-1-5-4\Control Panel\Colors] | |
| """) | |
| # Alphabetize list (purely so that user.reg is easy to read; Wine doesn't care) | |
| color_pairs = sorted(color_pairs) | |
| # Append list to file, with newlines | |
| f.writelines(line + '\n' for line in color_pairs) | |
| f.flush() | |
| # Debugging | |
| if debug_mode: | |
| print '---- [' + f.name + '] ----' | |
| f.seek(0) | |
| for line in f: | |
| print line, | |
| print '--------\n' | |
| # Import values into Wine registry using regedit command | |
| print('Using regedit to import colors into registry...\n') | |
| os.system('regedit ' + f.name) | |
| # TODO: Check if this worked correctly. | |
| # Delete temporary file | |
| f.close() | |
| print('Done importing colors') | |
| # TODO: catch errors from regedit not working? |
This script gives this error whenever I try to execute it
File "./wine_colors_from_gtk.py", line 26
""" Convert 48-bit gdk.Color to 24-bit 'RRR GGG BBB' triple. """
^
IndentationError: expected an indented block
Any clue how to solve this?
@ENigma885: Make sure you use Download Gist, not copy and paste. In Python, whitespace matters, and copy and pasting from websites often doesn't preserve it.
GTK engine: unknown
Traceback (most recent call last):
File "./wine_colors_from_gtk.py", line 160, in
desktop_color = format_hex_color(c.get_value('/desktop/gnome/background/primary_color'))
ValueError: gconf key /desktop/gnome/background/primary_color has no value
@JoelSjogren, thanks, it's helpfull!
Nice script ! Now with this and the Luna theme, my Wine apps look much more integrated. :)
By the way, I also had the problem with 'S-1-5-4' beeing the wrong ID. It worked when using the hive HKEY_CURRENT_USER instead, and this also seems more robust.
My fork: https://gist.github.com/simonbru/d681a4fd98b34924e8c3
I don't use Ubuntu anymore, so this version will not get any updates/fixes. Use the forks, Luke.
Suggest: change HKEY_USERS\S-1-5-4 to HKEY_CURRENT_USER or HKCU.
S-1-5-4 is pointing to your local user.
Damn. I need this, but syntax complains:
Traceback (most recent call last):
File "wine_colors_from_gtk.py", line 16, in <module>
from gconf import Client
File "/home/maus/.local/lib/python2.7/site-packages/gconf/__init__.py", line 15
_merged_dict: dict = {}
^
SyntaxError: invalid syntax
Python 2.7
I hope, you can do something about this ;)
Thanks!
I don't use Linux anymore, so try one of the forks. That looks like a syntax error in gconf, though, not in my script. Wrong Python version?
First of all, thank you for commenting your code so well.
I tried using your script and although it seemed to finish successfully it did not. Then I changed "HKEY_USERS\S-1-5-4" to "HKEY_USERS\S-1-5-21-0-0-0-1000" everywhere (2 places). Now it works.
To find the new value i started regedit in wine and looked in HKEY_USERS:
HKEY_USERS.Default
HKEY_USERS\S-1-5-21-0-0-0-1000
I hope this will help someone.