0

My goal is to get the icon which is currently on the window. (Then using some img tools I'll modify that icon, then save it to a location, I can do this part no need for help here please). Then I would like to set the window icon to the icon i have saved at a location on hard drive.

I do this in js-ctypes so it takes me a long time so if I am going in wrong direction I waste a ton of time so it really helps to ask about it. As I can't do a quick test. If you all can just point me in right direction I would really appreciate it.

Here was how I was thinking of doing it:

  1. I already have an array of windows (got it with XQuerySubtree)
  2. Get RGBA data of currently applied icon with XGetWindowProperty and atom of _NET_WM_ICON
  3. (use my img tools to modify the icon and save to hard drive, lets take for example on the desktop /usr/noida/Desktop/new icon.png)
  4. Apply icon from /usr/noida/Desktop/new icon.png to all of the windows in the array, so it changes icon displayed on window (if there is one, in ubuntu there isnt) and changes icon in Alt + Tab menu, and changes icon on dock.
    • apply path of icon with XSendEvent of a XClientMessageEvent with atom _NET_WM_ICON?

Am I thinking in the right direction?

Thanks


Image of goal - we see here that the window doesnt have an icon dispplayed on it, but its icon is displayed in the dock at the left. And in the Alt + Tab menu. So i was hoping by changing icon on all windows to my customized icon it will change on the dock and alt+tab menu. And for linux distributions that do show icon in window I hope that to be changed as well. In image here the blue arrow points to the three related icon areas.

showing i want to change which icons

Noitidart
  • 417
  • It can be me, but it is totally unclear to me what you want to achieve. Windows are grouped under the icon (application) that owns the window, they don't have an icon of its own per window. – Jacob Vlijm Oct 09 '14 at 16:23
  • I want to change that application icon. So if window dispalys icon it would be the one i changed it to, and the icon also should be the new one changed to in alt tabmenu and dock please. I accomplished this on windows xp here: http://img.photobucket.com/albums/v135/noitidart/winxp-badging-progress_zps1f5d6661.png – Noitidart Oct 09 '14 at 16:35
  • I am afraid it is (nearly) impossible. It is by design that windows are grouped in one icon, to serve coherence of the unity launcher. I can imagine a trick, but it would require lots of work. – Jacob Vlijm Oct 09 '14 at 16:44
  • @JacobVlijm Oh i just want to change the icon. I was hoping the new icon i change it too will show in all of those places. Not different icons per window or something. :) – Noitidart Oct 09 '14 at 19:14
  • sorry for asking, but what do you mean by "the icon which is currently on the window"? the application's icon? – Jacob Vlijm Oct 09 '14 at 19:46
  • Thanks so much @JacobVlijm for your persistance to help me. Basically i just want to change the icon. Programatically during run time. further explanation, please ignore if it gets confusing, english isnt my strong point: There is no icon on the window in ubuntu but other linux distros might. But in ubuntu it is showing the icon in the dock and alt+tab menu. – Noitidart Oct 09 '14 at 20:10
  • No problem :) that can be done, but what event would be the trigger to change the icon? – Jacob Vlijm Oct 09 '14 at 20:26
  • @JacobVlijm Oh phew I was worried it wasn't possible. I'm not sure about the event but I was reading here to find an answer to that: http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472702304 – Noitidart Oct 11 '14 at 19:33
  • what I mean is: on what occasion would you have the icon changed? – Jacob Vlijm Oct 11 '14 at 21:01
  • @JacobVlijm oh when user creates an image in my firefox addon and they click a button to "set as icon", it will then change the icon of that firefox profile. – Noitidart Oct 12 '14 at 00:20
  • @JacobVlijm forgive the pestering :( But I was wondering if my last comment answerd your question so you can share solution please :) – Noitidart Oct 15 '14 at 17:20
  • I oversaw the fact that you try to change the icon of a running application, which cannot be done (well, it can be done, but you won't see the difference then). – Jacob Vlijm Oct 15 '14 at 20:09
  • Thanks for fast reply @JacobVlijm Aw dang dang :( I was able to do it in windows and mac though :( Mac is similar to linux right? Are you sure no way? :( – Noitidart Oct 15 '14 at 20:10
  • Well, nothing is impossible I guess, but not with an acceptable amount effort. Unity is not quite Mac-like I think. – Jacob Vlijm Oct 15 '14 at 20:13
  • Haha @JacobVlijm no problem about effort, it took me two months to get it done on windows :P what about XChangeProperty with _NET_WM_ICON? Would that update the icon? – Noitidart Oct 15 '14 at 20:18
  • 1
    OK, but on windows, it is quite normal you don't get anything done within two months :) (just kidding, seriously, I have no problem with Windows). I am not that familiar with XChangeProperty, but to change the icon of a launcher in the Unity launcher, you need to refresh it (see: http://askubuntu.com/a/500609/72216), which will not happen on the icon of a running application. – Jacob Vlijm Oct 15 '14 at 20:24
  • Hahaha! @JacobVlijm ok thanks man I'll resach XChangeProperty I just found this: http://lists.kde.org/?l=kwin&m=115435217715650&w=2 do you think it will ork. The unity launcher is the dock on left huh? – Noitidart Oct 15 '14 at 21:22
  • Can you show me your method of changing icon please, ill then hamme that out (might take me awhile (few days) as i do it in js-ctypes), then Ill see where all the icon is changing, its ok for first rev if its doesnt apply till afte rrestart. Thanks man! – Noitidart Oct 15 '14 at 21:26
  • 1
    I will do that tonight (late). I have to run. Afterwards we probably should remove most of the comments above, it is a bit much :) – Jacob Vlijm Oct 16 '14 at 07:07
  • Notidart, I am really going to give you an answer, almost done, but I have a few very busy days and want to do it right, have to write an explanation and have to get back to you (will do it soon). – Jacob Vlijm Oct 16 '14 at 22:20
  • No problem at all @JacobVlijm don't rush yourself please. Pleas do when you can. I really appreciate it. Even if its a week or more out, I was only sendning reminders above because I thought you forgot about the topic but thakns for your committment won't worry Ill just check back when i get a msg with post in this topic :) Thank you sir! – Noitidart Oct 16 '14 at 22:33

1 Answers1

2

Where the icon is defined

The representation of an application in Dash and the the Unity launcher is defined in a .desktop file. Such a .desktop files includes a line to set the command to run the application, a line to set the icon of the application and a varying number of possible lines to set additional properties.

To see the current Unity launcher's content by command:

gsettings get com.canonical.Unity.Launcher favorites 

If you run this command, you will (a.o.) get a list of references to .desktop files, in the order like they appear in the launcher. An application's mention in the list looks like: application://thunderbird.desktop. It refers (in this example) to the file, thunderbird.desktop.

When Unity gathers its information on login, it first looks into the local directory for .desktop files, (~/.local/share/applications), and secondly in /usr/share/applications. If a .desktop file exists in both directory, the local one has preference. Normally, during your session, the launcher's icon stays linked to the .desktop file in either one of these directories.

When the content of the linked desktop file is edited during your session, the result is applied immediately. However, the icon as it appears in the Unity launcher does not change until you either:

  • log out / login
  • remove the icon from the launcher and lock it again

Since you cannot remove the icon of a running application from the launcher, changing the icon of a running application is not possible.
To change the icon of an application in the launcher which is not running however, you can use the two scripts below.
The first one copies the .desktop file to the local directory and edits the Icon= line in the local copy. The second one refreshes the icon in the launcher (and relinks it if necessary).


Script 1; change the icon

how to use

Copy the script below into an empty file, save it as change_icon.py, run it by the command:

python3 change_icon.py <applicationnamme.desktop> </path/to/new/icon>

for example:

python3 change_icon.py thunderbird.desktop </path/to/new/icon>

for smoother use:

create a directory ~/bin, copy the script into the directory, remove the language extension from the script, make it executable and (after logout / login), you can simly use the script by the command:

change_icon <applicationnamme.desktop> </path/to/new/icon>

More info on where to store and how to define icons, you can find here

The script

#!/usr/bin/env python3

import os import shutil import sys

file = sys.argv[1] new_icon = sys.argv[2]

user_home = os.environ["HOME"] dir_1 = user_home+"/.local/share/applications/" dir_2 = "/usr/share/applications/" dtfile_list1 = os.listdir(dir_1) dtfile_list2 = os.listdir(dir_2)

subject = dir_1+file

if not os.path.exists(subject): try: shutil.copyfile(dir_2+file, dir_1+file) except FileNotFoundError: print("the file "+file+" does not exist")

def read_file(file): with open(file) as edit: return edit.readlines()

def write_file(file, linelist): with open(file, "wt") as edit: for line in linelist: edit.write(line)

subject_lines = read_file(subject) index = [i for i in range(len(subject_lines))
if subject_lines[i].startswith("Icon=")][0] subject_lines[index] = "Icon="+new_icon+"\n" write_file(subject, subject_lines)


Script 2; refresh the icon in the launcher

how to use

Copy the script below into an empty file, save it as refresh.py, run it by the command:

python3 refresh.py <applicationnamme.desktop>

for smoother use:

Like in the script above, copy the script into ~/bin, remove the language extension, make it executable and (after logout / login), you can simly use the script by the command:

refresh <applicationnamme.desktop>

for example:

refresh thunderbird.desktop

The script

#!/usr/bin/env python3

import subprocess import time import sys

desktopfile = sys.argv[-1]

def read_currentlauncher(): # reads the current launcher contents return subprocess.check_output([ "gsettings", "get", "com.canonical.Unity.Launcher", "favorites" ]).decode("utf-8")

def set_launcher(llist): # sets a defined unity launcher list current_launcher = str(llist).replace(", ", ",") subprocess.Popen([ "gsettings", "set", "com.canonical.Unity.Launcher", "favorites", current_launcher, ])

def refresh_icon(desktopfile): current_launcher = read_currentlauncher() current_launcher_temp = eval(current_launcher) item = [item for item in current_launcher_temp if desktopfile in item][0] index = current_launcher_temp.index(item) current_launcher_temp.pop(index) set_launcher(current_launcher_temp) time.sleep(2) set_launcher(current_launcher)

refresh_icon(desktopfile)

Jacob Vlijm
  • 83,767
  • Such an incredibly detailed answer Its 208am here i have to sleep but I so so so appreciate this!!!!!!!!! So much to learn from this, thank you!! I notice this version requires changing the desktop file. Is there any hacky way where I can just determine the location of the launcher in the unity thing and like overlay an icon top of it? My goal really is just to put a badge on the icon. – Noitidart Oct 20 '14 at 09:08
  • Just some more commentary to see if I can get the badge/emblem to apply during runtime. My current goal isn't to change the icon of the desktop file its associated with, just add an overlay on top of the icon really. But this is spectacular and I have a use for it as my addon allows for creating shortcuts. – Noitidart Oct 20 '14 at 09:13
  • 1
    Thanks! my pleasure. As far as my knowledge goes, I don't see a possibility to add an overlay. However, dynamic icons exist, think of the progress icons of nautilus when it copies a file. I will keep it in mind, if some escape pops into my mind, I will post it! – Jacob Vlijm Oct 20 '14 at 09:21
  • Thank you sir very very much!! I will first use this to do my shortcut creation with custom icon for seperate profile then I will also look into it and report to you if I can accomplish it :) – Noitidart Oct 20 '14 at 09:22
  • Hey @JacobV I was working more on this and now was a point i needed the dynamic icon :( I found code here but Im not a c guy so i cant extract just the barebones specific functions i need to replicate this (im replicating in ctypes) please see here: http://stackoverflow.com/questions/27112040/dynamic-icon-ubuntu-nautilus – Noitidart Nov 24 '14 at 19:04
  • @Noitidart I'll keep an eye on possible answers... – Jacob Vlijm Nov 24 '14 at 20:41
  • Thank you very much sir! I found some awesome code which Im trying to study here: https://code.launchpad.net/~3v1n0/ubuntu/oneiric/nautilus/unity-launcher-support/+merge/70685 – Noitidart Nov 24 '14 at 20:44
  • Is it possible to have different icons for instances of the same application? For example, if I have 10 terminal windows open, I could write a script that changes the icon before starting a new instance, and then I could have terminal windows visually separated from each other (for example I'd style root, chat, tunnel etc differently for easier navigating)? – ramtam Dec 22 '16 at 17:32
  • @ramtam kind of; you can make Unity show an additional icon for the window. The default one will however also show... – Jacob Vlijm Dec 22 '16 at 17:34