获取窗口的图标,然后更改图标

获取窗口的图标,然后更改图标

我的目标是获取当前在窗口上的图标。(然后使用一些 img 工具,我将修改该图标,然后将其保存到某个位置,我可以完成这一部分,无需帮助)。然后我想将窗口图标设置为我已保存在硬盘驱动器上某个位置的图标。

我在 js-ctypes 中执行此操作,因此需要很长时间,如果我走错了方向,我会浪费大量时间,所以询问一下真的很有帮助。因为我无法进行快速测试。如果你们都能给我指明正确的方向,我将不胜感激。

我当时想这样做:

  1. 我已经有一个窗口数组(用 得到它XQuerySubtree
  2. 获取当前应用图标的 RGBA 数据XGetWindowProperty以及原子_NET_WM_ICON
  3. (使用我的 img 工具修改图标并保存到硬盘,以桌面为例/usr/noida/Desktop/new icon.png
  4. 将图标应用/usr/noida/Desktop/new icon.png到数组中的所有窗口,因此它会改变窗口上显示的图标(如果有的话,在 ubuntu 中没有)并改变Alt+Tab菜单中图标,并改变 dock 上的图标。
    • 使用原子XSendEvent应用图标的路径吗?XClientMessageEvent_NET_WM_ICON

我思考的方向正确吗?

谢谢


目标图像 - 我们在这里看到窗口上没有显示图标,但其图标显示在左侧的停靠栏中。并在Alt+Tab菜单中。所以我希望通过将所有窗口上的图标更改为我的自定义图标,它将在停靠栏和 alt+tab 菜单上更改。对于在窗口中显示图标的 Linux 发行版,我希望这也能改变。在此处的图像中,蓝色箭头指向三个相关的图标区域。

显示我想更改哪些图标

答案1

图标定义的位置

应用程序在 Dash 和 Unity 启动器中的表示形式在 .desktop 文件中定义。此类 .desktop 文件包括一行用于设置运行应用程序的命令、一行用于设置应用程序的图标以及不同数量的用于设置其他属性的可能行。

通过命令查看当前Unity启动器的内容:

gsettings get com.canonical.Unity.Launcher favorites 

如果您运行此命令,您将获得对 .desktop 文件的引用列表,其顺序与启动器中显示的顺序相同。列表中的应用程序提及如下所示:application://thunderbird.desktop。它(在此示例中)引用文件thunderbird.desktop

当 Unity 收集登录信息时,它首先在本地目录中查找 .desktop 文件(~/.local/share/applications),然后在 中查找/usr/share/applications。如果两个目录中都存在 .desktop 文件,则优先使用本地文件。通常,在您的会话期间,启动器的图标会保持链接到其中一个目录中的 .desktop 文件。

在会话期间编辑链接的桌面文件的内容时,结果会立即应用。但是,图标它在 Unity 启动器中显示不会改变,直到您执行以下操作:

  • 登出/登录
  • 从启动器中删除图标并再次锁定

由于您无法从启动器中删除正在运行的应用程序的图标,改变的图标跑步无法更改应用程序的图标。
要更改启动器中应用程序的图标,没有运行但是,您可以使用以下两个脚本。
第一个脚本将 .desktop 文件复制到本地目录,并Icon=在本地副本中编辑该行。第二个脚本刷新启动器中的图标(并在必要时重新链接它)。


脚本1;更改图标

如何使用

将下面的脚本复制到一个空文件中,另存为change_icon.py,通过以下命令运行:

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

例如:

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

为了更顺畅地使用:

创建一个目录~/bin,将脚本复制到该目录中,从脚本中删除语言扩展,使其可执行,并且(注销/登录后),您可以通过以下命令轻松使用该脚本:

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

关于存储位置和如何定义图标的更多信息,你可以找到这里

剧本

#!/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)

脚本2;刷新启动器中的图标

如何使用

将下面的脚本复制到一个空文件中,另存为refresh.py,通过以下命令运行:

python3 refresh.py <applicationnamme.desktop>

为了更顺畅地使用:

像上面的脚本一样,将脚本复制到~/bin,删除语言扩展,使其可执行,并且(注销/登录后),您可以通过以下命令轻松使用该脚本:

refresh <applicationnamme.desktop>

例如:

refresh thunderbird.desktop

剧本

#!/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)

相关内容