-
-
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/pygtk@daa.com.au/msg16400.html | |
http://www.mail-archive.com/gtk-app-devel-list@gnome.org/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 endolith@gmail.com | |
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 | |
# | |
# endolith@gmail.com 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? |
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?
@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.