Any steps I should take before upgrading from a 30 series RTX card to a 9070xt?

I'm using Kubunutu 26.04LTS in a dual boot configuration with Windows 10 in a separate drive. I'm upgrading my GPU since I got a pretty great deal on a 9070xt and it's basically the last card I can get with triple 8 pin connectors. I'd rather avoid the 12 pin for as long as I can, plus I got custom sleeved cables I don't want to replace or hide behind an adapter.

For windows I know I should use DDU to remove my Nvidia drivers before I swap the card, but I wanted to ask if there's any such steps I need to take in my Linux side. I'm fairly new to the distro so I don't know all the details on how these things work.

I'm running a 9700x, 48GB DDR5, NVME SSD and a 850W gold PSU.

reddit.com
u/Blackirean — 13 hours ago
🔥 Hot ▲ 7.6k r/TopCharacterTropes

[Funny Trope] Against their deepest wishes, they keep winning

Catch-22: Yossarian is a pilot who above anything wants to not die in the war. To that extent he does everything in his power to sabotage his missions. Only for his superiors to recontextualize many of his actions into those of heroism, thus preventing him from leaving his position much to his disappointment.

The world of otome games is tough for mobs: Leon Bartfort is a man who reincarnated in the world of a dating sim game he played on behalf of his sister, restarting his life from a young age. Using his knowledge he planned to acquire riches and powers to get his own island, and live in peace alone away from the war, conflict and drama he knew would happen this world. But every action he took was nothing but another achievement that added complexity to his plans. Obtain riches? He gets titles that make his family send him to the main school of the story, obtain advance weaponry? forced to fight in a war, then decorated and tasked with even more responsibility, want nothing to do with the plot? get the main girl, the villainess, the protagonist of the sequel and even the Queen to fall in love with him.

Uncle Mo (real life example): An old man in china who has a small shop where he made chicken pot mixed with medicinal herbs he manually harvested from the mountains. Problem is that vloggers made their way to his tiny shop and caused it to explode in popularity. Suddenly he's inundated with customers, sometimes hundreds of them, who wait hours in line to have his food. The shop is small and managed only with him and sometimes family members so managing that amount of customers is arduous, even obtaining the ingredients has become a chore. He has openly protested against the vloggers trying to bring more fame to his shop, has shared the recipe openly for everyone to make, claimed that the food will make people feel bad or that their stool would be loose. All to no avail, as his popularity grew even more and even the government of his province forbade him from stopping as the business and attention his shop brings are good for the province.

u/Blackirean — 1 day ago
▲ 4 r/linuxhardware+1 crossposts

Bluetooth Controller not working after BIOS update

So I'm running Kubuntu 26.04 and recently updated my motherboard's BIOS. I'm using the Gigabyte B850i Aorus pro Rev 1.0 motherboard. Before the update everything worked fine but after installing the latest BIOS available from the website my game controller no longer works when connected via Bluetooth. It works when connected using a cable so I know the controller is not the problem.

I tried everything. From unisntalling and resintalling xpadneo, to running sudo rfkill unblock bluetooth and even doing a full power down by disconnecting my PC PSU. Can anybody help me fix this?

My PC has a R7 9700x, 48G of DDR5 and as mentioned the motherboard is the Gigabyte B850i Aorus Pro Rev 1.0.

Please help

Edit: Fixed the problem. Turns out that after the BIOS update secure boot was turned on in the BIOS without me noticing. I turned it off and the controller works perfectly.

I Was about to completely reinstall Kubuntu until I decided to give a try to get xpadneo working. When I tried to manually get it started I got an error. After googling, it turned out that the error comes from having secure boot on and it was preventing the xpadneo driver from recognizing the controller input even though it was properly connected via Bluetooth.

reddit.com
u/Blackirean — 4 days ago

Should I upgrade to 5070ti or 9070xt?

Recently decided to switch to Linux after windows 10 died and windows 11 was enshittified. After some distro hopping I ended with kubuntu for long term support, stability and KDE plasma. Maybe thinking on trying fedora KDE later on if I feel like I'm missing on some bleeding edge stuff but that's not the point.

I managed to refresh my PC last year before prices went insane, new CPU, MOBO, 48GB of RAM, 14TB HDD and 4TB SSD. The only thing that didn't move was my trusty EVGA RTX 3080 10GB I've had since late 2020 and my 850W gold PSU.

I've been thinking of finally upgrading the card to compensate for some of the loss in performance that comes with Linux, and my options are to go for the 5070ti or the 9070XT.

I will admit I've only ever used Nvidia cards, I'm used to the software and was an overall fan. I've never tried any radeon cards so I don't know what I'm getting into or what features I might be giving up if I switch cards. Codecs, resolution, features, no idea I was a plug and play guy that simply updated game ready drivers.

I know the 9070xt is almost on par with the 5070ti, with the exception of ray tracing. And from the looks of it much better price wise. After some cashback, selling old hardware and the such I can basically get one for about 360$ (and can finance those to about 120 a month for 3 months no interest), whereas I would have to shell about twice that much for a 5070ti especially since I would need an SFF version to fit in my case. I would also have to rely on the infamous 12pin cable, while the 9070xt would still allow me to keep the 3 8pins (and as a bonus I can keep using my custom sleeved 8pin cables)

I don't know if the extra money would be worth it in the long term with the 5070ti.

Am I being too paranoid about abandoning Nvidia? Is there any unseen downsides or better, benefits to using an AMD card?

My specs are:

Ryzen 7 9700x

Gigabyte Aorus B850I Pro

48GB DDR5 6400 MT/s

Samsung 970 EVO Plus 2TB

Samsung 990 Pro 4TB

EVGA RTX 3080 FTW3 10GB LHR

Cooler Master V850 SFX

reddit.com
u/Blackirean — 6 days ago
🔥 Hot ▲ 9.4k r/TopCharacterTropes

[Rare trope] Discriminating, but for an actually good reason

Frieren, Beyond Journey's end: In the anime/manga the eponymous Frieren is an Elf who's spent the better part of a millennia learning magic specifically to kill demons. She's learned countless spells, tricks and even spent most of her life suppressing her power all for the purpose of killing them. At first we simply see that humanity is at war with them, and even question if her crusade against demon-kind is justified, after all it's hard to antagonize an entire sentient species. But no, demons are very much a species to be feared; they are not normal animals or creatures, they are monsters (shown by how they disintegrate when they die), they are predators that evolved speech for the sole purpose of tricking and catching humans off guard, are naturally extremely powerful and possess magic that humanity often can't use. While they feel emotions to some extent, their way of thinking is so fundamentally incompatible with humanity's mindset that the series shows many mages with the ability to read minds struggle or find it painful and harmful to try and read a demon's thoughts. Tools that are meant to control them fail not because they're faulty but because simple order such as "hold no ill will or commit no malicious acts" don't compute the same way in their brains, as what we consider evil is normal for them.

Marvel Comics: In a run of the Storm solo series, she visits an underground superhuman hospital run by Night nurse and Doctor Daye, a mutant with the power to diagnose any illness. When she requires treatment she is in turn reject by the doctor, she of course assumes this is blatant discrimination to which the doctor agrees. Storm assumes the doctor refuses to treat mutants, something they are very much used to in Marvel. But he ends up revealing that about 80% of everyone he treats are mutants, and that he simply refuses to treat any member of the X-men. Why? because his special hospital was built via several donations by the superhero community. From the Avengers, to the Defenders, Fantastic 4, heroes for hire. Hell, even Moonknight of all people contributed to the hospital. But the X-men never once gave anything to it, even though they preach the safety of mutant-kind and such a hospital is essential for those who can't seek medical treatment out of fear of prosecution.

u/Blackirean — 15 days ago
🔥 Hot ▲ 11.7k r/TopCharacterTropes

Character sacrifices themselves because they know the consequences won't be as dire for them

Avengers Endgame: After the time heist and regathering the infinity stones, the team assembles a new infinity gauntlet. When it is time to make another snap they try to decide who'll take the gauntlet and the possibly deadly feedback. In the end, Banner in the form of professor Hulk decides to be the one, saying that much of the energy out of the gauntlet is gamma, similar to what's empowering. That plus his durability makes him the most likely to survive the snap. And later we see this to be the case when Tony uses them and ends up far worse.

Malcolm in the Middle: In a cold open, Dewey and Hal are trying to get rid of a spider. When things get out of control and Hal begins to frantically try to not let it go, they desperately run towards the door. When they throw the spider out, it is revealed that Lois was outside and the spider lands on her. Dewey proceeds to close the door immediately and tell Hal to run, saying that the worst she can do is ground him, while Hal will have to face the full strength of her Fury. Hal thanks him before running away in justified panic.

u/Blackirean — 23 days ago

Anybody know how to create custom emojis?

so the new update brings a really nice feature to use letters, some Chinese characters or emojis as the main fingerprint sensor icon. I experimented and ended with this fire symbol in japanese

but I got thinking. if we can add more emojis there's basically no limit on what image we can use as the fingerprint icon.

anybody got any ideas?

u/Blackirean — 1 month ago

How to I fix controller rumble in Skul the hero slayer (non-steam)

So I have an instance of the game Skul the hero slayer. The game has a native linux version, I run it from a folder by opening a run.sh file.

Problem is that rumble seems to not work at all. No matter the setting I choose.

I'm using an xbox elite controller 2, in Kubuntu 26.04. I have xpadneo installed and I have been able to use rumble in any other game I launch from steam, just not this one. Maybe cause I launch it directly instead of through steam?

I need some help please.

reddit.com
u/Blackirean — 1 month ago

Command to bring app to focus and/or open it?

I'm trying to create some widget shortcuts for apps and I'm having problems finding a command to focus/maximize firefox if I have it open, or open a new instance if I don't have firefox open.

Looking online I found these main ways:

wmctrl -xa firefox || firefox

wmctrl -xa firefox || firefox&

xdotool search --onlyvisible --class firefox  windowactivate ||firefox

Neither of these three was able to achieve what I was looking for, none brought minimized firefox to focus. They either not work or they simply open a whole new Firefox window. Regardless if I have another one open.

I am running the default version of firefox that comes with Kubuntu LTS. What can I do?

reddit.com
u/Blackirean — 1 month ago

Made a quick script to create draggable honeycomb icons

As the title explains I made this script to create some honeycombs since I missed having them and rainmeter doesn't work on linux. they can be dragged, freely resized, launch custom apps or commands and they remember their position after the script is killed or the computer turned off. Left clicking any gives you the options to edit the config file to add more honeycombs, open the folder to make more icons, refresh the layout after adding or removing instances, reset the honeycombs to the middle of the screen to rearrange or straight up stop the script and kill them.

Below are the instructions to implement it, I am planning on maybe putting it on github with ready made downloadable files but first I'm trying to get it to work on KDE since I no longer use mint and switched to Kubuntu. In the config code below I have the honeycombs to launch the terminal, open the download folder and either launch firefox or bring it to focus if it's already open.

The script was tested in a linux mint cinammon VM. It may work better or worse depending on the computer I don't know. If anyone finds any problems please let me know, I would appreciate the feedback.

There are a couple of known bugs, first is that if you click a hexagon to open an app or run a command and quickly try to click a different hexagon that is next to it, it might launch the first honeycomb command instead of the new one. Waiting for a little bit before clicking is usually the best or maybe keep them separated.

You can see it in action here:

https://imgur.com/a/IwXJAOH

Linux Mint Cinnamon: Floating Pointy-Top Honeycomb Launcher Guide:

# 1. System Dependencies

Open your terminal and run this command to install the required GTK3 and Cairo libraries:

sudo apt update && sudo apt install python3-gi gir1.2-gtk-3.0 python3-cairo -y

# 2. Directory Layout

For the script to run cleanly, create this folder structure in your Home directory:

/home/YOUR_USERNAME/Honeycomb/

├── honeycomb.py

├── honeycomb_config.json

└── icons/

├── steam_hex.png

├── firefox_hex.png

└── discord_hex.png

Place your honeycomb png or ico files here int he icons folder. You can get them form google or make your own, but they have to be here. I only had the discord, rainmeter and firefox icons so that's what you see in the gif above.

# 3. Configuration File (honeycomb_config.json)

Create this file inside the Honeycomb folder. Add or remove hexagons by editing this JSON layout. Replace yourusername with your actual Linux Mint username.

[
  {
    "id": "steam",
    "image_path": "/home/yourusername/Honeycomb/icons/steam_hex.png",
    "command": "gnome-terminal",
    "size": 120
  },
  {
    "id": "firefox",
    "image_path": "/home/yourusername/Honeycomb/icons/firefox_hex.png",
    "command": "wmctrl -a firefox || firefox &",
    "size": 120
  },
  {
    "id": "discord",
    "image_path": "/home/yourusername/Honeycomb/icons/discord_hex.png",
    "command": "xdg-open /home/osboxes/Downloads",
    "size": 120
  }
]

# 4. The Python Script (honeycomb.py)

Create hoenycomb.py inside the Honeycomb folder. Paste the following code block into it:

#!/usr/bin/env python3
import sys
import os
import subprocess
import math
import json
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib
import cairo

LAYOUT_DIR = os.path.expanduser("~/.config/hex_launchers")
LAYOUT_FILE = os.path.join(LAYOUT_DIR, "positions.json")

ACTIVE_WIDGETS = []
IMAGE_CACHE = {}
MENU_PROTOTYPE = None

class HexagonalWidget(Gtk.Window):
    _slots_ = ('widget_id', 'image_path', 'command', 'height', 'width', 
                 'drag_start_x', 'drag_start_y', 'has_moved', 'pixbuf')
    
    def _init_(self, config, saved_pos):
        super()._init_(type=Gtk.WindowType.TOPLEVEL)
        
        self.widget_id = config["id"]
        self.image_path = config["image_path"]
        self.command = config["command"]
        self.height = config.get("size", 120)
        self.width = int(self.height * (math.sqrt(3) / 2))
        
        self.set_title("")
        self.set_decorated(False)
        self.set_app_paintable(True)
        self.set_keep_above(True)
        self.set_skip_taskbar_hint(True)
        self.set_skip_pager_hint(True)
        self.set_type_hint(Gdk.WindowTypeHint.DESKTOP)
        self.set_default_size(self.width, self.height)
        
        screen = self.get_screen()
        visual = screen.get_rgba_visual()
        if visual and screen.is_composited():
            self.set_visual(visual)
        
        self.drag_start_x = 0
        self.drag_start_y = 0
        self.has_moved = False
        
        self.connect("draw", HexagonalWidget.on_draw)
        self.connect("button-press-event", HexagonalWidget.on_button_press)
        self.connect("button-release-event", HexagonalWidget.on_button_release)
        self.connect("motion-notify-event", HexagonalWidget.on_motion_notify)
        self.connect("realize", HexagonalWidget.on_realize)
        self.connect("destroy", HexagonalWidget.on_destroy)
        
        self.pixbuf = IMAGE_CACHE.get(self.image_path)
        if not self.pixbuf and os.path.exists(self.image_path):
            try:
                self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                    self.image_path, self.width, self.height, True
                )
                IMAGE_CACHE[self.image_path] = self.pixbuf
            except Exception:
                self.pixbuf = None

        if saved_pos and self.widget_id in saved_pos:
            pos = saved_pos[self.widget_id]
            self.move(pos['x'], pos['y'])
        else:
            self.move(200, 200)

        ACTIVE_WIDGETS.append(self)
        self.show_all()

    u/staticmethod
    def draw_pointy_hexagon(cr, width, height):
        center_x = width / 2
        center_y = height / 2
        radius = height / 2
        cos_60 = math.sqrt(3) / 2
        
        cr.move_to(center_x + radius * cos_60, center_y - radius)
        for angle in (math.pi/6, math.pi/2, 5*math.pi/6, 7*math.pi/6, 3*math.pi/2):
            cr.line_to(center_x + radius * cos_60 * math.cos(angle), 
                      center_y + radius * math.sin(angle) / cos_60)

    u/staticmethod
    def on_realize(widget):
        width, height = widget.width, widget.height
        surface = cairo.ImageSurface(cairo.FORMAT_A1, width, height)
        cr = cairo.Context(surface)
        HexagonalWidget.draw_pointy_hexagon(cr, width, height)
        cr.set_source_rgba(1, 1, 1, 1)
        cr.fill()
        
        region = Gdk.cairo_region_create_from_surface(surface)
        widget.get_window().input_shape_combine_region(region, 0, 0)

    u/staticmethod
    def on_draw(widget, cr):
        cr.set_source_rgba(0, 0, 0, 0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()
        cr.set_operator(cairo.OPERATOR_OVER)
        
        if widget.pixbuf:
            Gdk.cairo_set_source_pixbuf(cr, widget.pixbuf, 0, 0)
            cr.paint()
        else:
            HexagonalWidget.draw_pointy_hexagon(cr, widget.width, widget.height)
            cr.set_source_rgba(0.2, 0.6, 0.8, 0.8)
            cr.fill()

    u/staticmethod
    def on_button_press(widget, event):
        if event.button == 1:
            widget.drag_start_x, widget.drag_start_y = event.x, event.y
            widget.has_moved = False
        elif event.button == 3:
            widget.show_context_menu(event)
        else:
            return False
        return True

    def show_context_menu(self, event):
        global MENU_PROTOTYPE
        if not MENU_PROTOTYPE:
            MENU_PROTOTYPE = Gtk.Menu()
            items = [
                ("Edit Cluster", self.on_edit_triggered),
                ("Reset Cluster", self.on_reset_triggered),
                ("Open Folder", self.on_open_folder_triggered),
                ("Refresh Layout", self.on_refresh_triggered),
                ("Open Script", self.on_open_script_triggered),
                ("Stop Script", self.on_stop_triggered)
            ]
            for label, callback in items:
                item = Gtk.MenuItem(label=label)
                item.connect("activate", callback)
                MENU_PROTOTYPE.append(item)
            MENU_PROTOTYPE.show_all()
        
        MENU_PROTOTYPE.popup_at_pointer(event)

    u/staticmethod
    def on_refresh_triggered(menu_item):
        global ACTIVE_WIDGETS
        for widget in ACTIVE_WIDGETS[:]:
            if widget:
                widget.destroy()
        ACTIVE_WIDGETS.clear()
        
        script_dir = os.path.dirname(os.path.abspath(_file_))
        config_file = os.path.join(script_dir, "honeycomb_config.json")
        
        try:
            with open(config_file, 'r') as f:
                widgets_config = json.load(f)
            saved_positions = load_all_positions()
            for config in widgets_config:
                HexagonalWidget(config, saved_positions)
        except Exception as e:
            print(f"Error refreshing: {e}")

    u/staticmethod
    def on_reset_triggered(menu_item):
        if not ACTIVE_WIDGETS:
            return
            
        widget = next(w for w in ACTIVE_WIDGETS if w)
        display = Gdk.Display.get_default()
        monitor = display.get_monitor_at_window(widget.get_window())
        geometry = monitor.get_geometry()
        
        center_x = geometry.width // 2
        center_y = geometry.height // 2
        total_widgets = len(ACTIVE_WIDGETS)
        spacing = 15
        
        total_width = (total_widgets * widget.width) + ((total_widgets - 1) * spacing)
        start_x = center_x - (total_width // 2)
        
        for idx, widget in enumerate(ACTIVE_WIDGETS):
            new_x = start_x + (idx * (widget.width + spacing))
            new_y = center_y - (widget.height // 2)
            widget.move(new_x, new_y)
            global_save_position(widget.widget_id, (new_x, new_y))

    u/staticmethod
    def on_stop_triggered(menu_item):
        Gtk.main_quit()

    u/staticmethod
    def on_open_script_triggered(menu_item):
        script_file = os.path.join(os.path.dirname(os.path.abspath(_file_)), "honeycomb.py")
        subprocess.Popen(['xdg-open', script_file], close_fds=True)

    u/staticmethod
    def on_edit_triggered(menu_item):
        config_file = os.path.join(os.path.dirname(os.path.abspath(_file_)), "honeycomb_config.json")
        subprocess.Popen(['xdg-open', config_file], close_fds=True)

    u/staticmethod
    def on_open_folder_triggered(menu_item):
        folder_path = os.path.dirname(os.path.abspath(_file_))
        subprocess.Popen(['xdg-open', folder_path], close_fds=True)

    u/staticmethod
    def on_motion_notify(widget, event):
        if event.state & Gdk.ModifierType.BUTTON1_MASK:
            widget.has_moved = True
            widget.move(int(event.x_root - widget.drag_start_x),
                       int(event.y_root - widget.drag_start_y))
            return True
        return False

    u/staticmethod
    def on_button_release(widget, event):
        if event.button == 1:
            if not widget.has_moved:
                try:
                    subprocess.Popen(widget.command, shell=True, close_fds=True)
                except Exception as e:
                    print(f"[{widget.widget_id}] Launch failed: {e}")
            else:
                widget.has_moved = False
                global_save_position(widget.widget_id, widget.get_position())
            return True
        return False

    u/staticmethod
    def on_destroy(widget):
        try:
            ACTIVE_WIDGETS.remove(widget)
        except ValueError:
            pass

def load_all_positions():
    try:
        if os.path.exists(LAYOUT_FILE):
            with open(LAYOUT_FILE, 'r') as f:
                return json.load(f)
    except Exception:
        pass
    return {}

def global_save_position(widget_id, coords):
    try:
        os.makedirs(LAYOUT_DIR, exist_ok=True)
        positions = load_all_positions()
        positions[widget_id] = {'x': int(coords[0]), 'y': int(coords[1])}
        with open(LAYOUT_FILE, 'w') as f:
            json.dump(positions, f)
    except Exception as e:
        print(f"Failed to save positions: {e}")

if _name_ == "_main_":
    script_dir = os.path.dirname(os.path.abspath(_file_))
    config_file = os.path.join(script_dir, "honeycomb_config.json")
    
    if not os.path.exists(config_file):
        print(f"Error: Config file not found at {config_file}")
        sys.exit(1)
    
    try:
        with open(config_file, 'r') as f:
            widgets_config = json.load(f)
        
        saved_positions = load_all_positions()
        
        for config in widgets_config:
            HexagonalWidget(config, saved_positions)
        
        Gtk.main()
    except KeyboardInterrupt:
        pass
    except Exception as e:
        print(f"Fatal error: {e}")

# 5. Implementation Steps

  1. Make the script executable by running this in your terminal:chmod +x ~/Honeycomb/honeycomb.py
  2. Run it to test:~/Honeycomb/honeycomb.py

# 6. How to Use Features

* *Drag and Drop:* Hold Left-Click on any hexagon to reposition it. Release to save its position permanently.

* *Launch:* Single Left-Click on any hexagon to open the game/app you defined in teh config file.

* *Un-Clutter Feature:* Right-Click any hexagon and select "Reset Cluster" to snap all elements into a row in the center of your monitor.

## 7. Enable Auto-Start on Boot

  1. Open the Menu and launch "Startup Applications".
  2. Click the "+" icon and choose "Custom Command".
  3. Name: Honeycomb Launcher (or whatever you want)
  4. Command: python3 /home/yourusername/Honeycomb/honeycomb.py
  5. Startup Delay: Set to 3 seconds (to let Mint's desktop graphics manager finish rendering transparency before loading the hexagons)
  6. Click Save.
i.redd.it
u/Blackirean — 1 month ago

Made a quick script to create draggable honeycomb icons

As the title explains I made this script to create some honeycombs since I missed having them and rainmeter doesn't work on linux. they can be dragged, freely resized, launch custom apps or commands and they remember their position after the script is killed or the computer turned off. Left clicking any gives you the options to edit the config file to add more honeycombs, open the folder to make more icons, refresh the layout after adding or removing instances, reset the honeycombs to the middle of the screen to rearrange or straight up stop the script and kill them.

Below are the instructions to implement it, I am planning on maybe putting it on github with ready made downloadable files but first I'm trying to get it to work on KDE since I no longer use mint and switched to Kubuntu. In the config code below I have the honeycombs to launch the terminal, open the download folder and either launch firefox or bring it to focus if it's already open.

The script was tested in a linux mint cinammon VM. It may work better or worse depending on the computer I don't know. If anyone finds any problems please let me know, I would appreciate the feedback.

There are a couple of known bugs, first is that if you click a hexagon to open an app or run a command and quickly try to click a different hexagon that is next to it, it might launch the first honeycomb command instead of the new one. Waiting for a little bit before clicking is usually the best or maybe keep them separated.

Linux Mint Cinnamon: Floating Pointy-Top Honeycomb Launcher Guide:

# 1. System Dependencies

Open your terminal and run this command to install the required GTK3 and Cairo libraries:

sudo apt update && sudo apt install python3-gi gir1.2-gtk-3.0 python3-cairo -y

# 2. Directory Layout

For the script to run cleanly, create this folder structure in your Home directory:

/home/YOUR_USERNAME/Honeycomb/

├── honeycomb.py

├── honeycomb_config.json

└── icons/

├── steam_hex.png

├── firefox_hex.png

└── discord_hex.png

Place your honeycomb png or ico files here int he icons folder. You can get them form google or make your own, but they have to be here. I only had the discord, rainmeter and firefox icons so that's what you see in the gif above.

# 3. Configuration File (honeycomb_config.json)

Create this file inside the Honeycomb folder. Add or remove hexagons by editing this JSON layout. Replace yourusername with your actual Linux Mint username.

[
  {
    "id": "steam",
    "image_path": "/home/yourusername/Honeycomb/icons/steam_hex.png",
    "command": "gnome-terminal",
    "size": 120
  },
  {
    "id": "firefox",
    "image_path": "/home/yourusername/Honeycomb/icons/firefox_hex.png",
    "command": "wmctrl -a firefox || firefox &",
    "size": 120
  },
  {
    "id": "discord",
    "image_path": "/home/yourusername/Honeycomb/icons/discord_hex.png",
    "command": "xdg-open /home/osboxes/Downloads",
    "size": 120
  }
]

# 4. The Python Script (honeycomb.py)

Create hoenycomb.py inside the Honeycomb folder. Paste the following code block into it:

#!/usr/bin/env python3
import sys
import os
import subprocess
import math
import json
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib
import cairo

LAYOUT_DIR = os.path.expanduser("~/.config/hex_launchers")
LAYOUT_FILE = os.path.join(LAYOUT_DIR, "positions.json")

ACTIVE_WIDGETS = []
IMAGE_CACHE = {}
MENU_PROTOTYPE = None

class HexagonalWidget(Gtk.Window):
    _slots_ = ('widget_id', 'image_path', 'command', 'height', 'width', 
                 'drag_start_x', 'drag_start_y', 'has_moved', 'pixbuf')
    
    def _init_(self, config, saved_pos):
        super()._init_(type=Gtk.WindowType.TOPLEVEL)
        
        self.widget_id = config["id"]
        self.image_path = config["image_path"]
        self.command = config["command"]
        self.height = config.get("size", 120)
        self.width = int(self.height * (math.sqrt(3) / 2))
        
        self.set_title("")
        self.set_decorated(False)
        self.set_app_paintable(True)
        self.set_keep_above(True)
        self.set_skip_taskbar_hint(True)
        self.set_skip_pager_hint(True)
        self.set_type_hint(Gdk.WindowTypeHint.DESKTOP)
        self.set_default_size(self.width, self.height)
        
        screen = self.get_screen()
        visual = screen.get_rgba_visual()
        if visual and screen.is_composited():
            self.set_visual(visual)
        
        self.drag_start_x = 0
        self.drag_start_y = 0
        self.has_moved = False
        
        self.connect("draw", HexagonalWidget.on_draw)
        self.connect("button-press-event", HexagonalWidget.on_button_press)
        self.connect("button-release-event", HexagonalWidget.on_button_release)
        self.connect("motion-notify-event", HexagonalWidget.on_motion_notify)
        self.connect("realize", HexagonalWidget.on_realize)
        self.connect("destroy", HexagonalWidget.on_destroy)
        
        self.pixbuf = IMAGE_CACHE.get(self.image_path)
        if not self.pixbuf and os.path.exists(self.image_path):
            try:
                self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                    self.image_path, self.width, self.height, True
                )
                IMAGE_CACHE[self.image_path] = self.pixbuf
            except Exception:
                self.pixbuf = None

        if saved_pos and self.widget_id in saved_pos:
            pos = saved_pos[self.widget_id]
            self.move(pos['x'], pos['y'])
        else:
            self.move(200, 200)

        ACTIVE_WIDGETS.append(self)
        self.show_all()

    u/staticmethod
    def draw_pointy_hexagon(cr, width, height):
        center_x = width / 2
        center_y = height / 2
        radius = height / 2
        cos_60 = math.sqrt(3) / 2
        
        cr.move_to(center_x + radius * cos_60, center_y - radius)
        for angle in (math.pi/6, math.pi/2, 5*math.pi/6, 7*math.pi/6, 3*math.pi/2):
            cr.line_to(center_x + radius * cos_60 * math.cos(angle), 
                      center_y + radius * math.sin(angle) / cos_60)

    u/staticmethod
    def on_realize(widget):
        width, height = widget.width, widget.height
        surface = cairo.ImageSurface(cairo.FORMAT_A1, width, height)
        cr = cairo.Context(surface)
        HexagonalWidget.draw_pointy_hexagon(cr, width, height)
        cr.set_source_rgba(1, 1, 1, 1)
        cr.fill()
        
        region = Gdk.cairo_region_create_from_surface(surface)
        widget.get_window().input_shape_combine_region(region, 0, 0)

    u/staticmethod
    def on_draw(widget, cr):
        cr.set_source_rgba(0, 0, 0, 0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()
        cr.set_operator(cairo.OPERATOR_OVER)
        
        if widget.pixbuf:
            Gdk.cairo_set_source_pixbuf(cr, widget.pixbuf, 0, 0)
            cr.paint()
        else:
            HexagonalWidget.draw_pointy_hexagon(cr, widget.width, widget.height)
            cr.set_source_rgba(0.2, 0.6, 0.8, 0.8)
            cr.fill()

    u/staticmethod
    def on_button_press(widget, event):
        if event.button == 1:
            widget.drag_start_x, widget.drag_start_y = event.x, event.y
            widget.has_moved = False
        elif event.button == 3:
            widget.show_context_menu(event)
        else:
            return False
        return True

    def show_context_menu(self, event):
        global MENU_PROTOTYPE
        if not MENU_PROTOTYPE:
            MENU_PROTOTYPE = Gtk.Menu()
            items = [
                ("Edit Cluster", self.on_edit_triggered),
                ("Reset Cluster", self.on_reset_triggered),
                ("Open Folder", self.on_open_folder_triggered),
                ("Refresh Layout", self.on_refresh_triggered),
                ("Open Script", self.on_open_script_triggered),
                ("Stop Script", self.on_stop_triggered)
            ]
            for label, callback in items:
                item = Gtk.MenuItem(label=label)
                item.connect("activate", callback)
                MENU_PROTOTYPE.append(item)
            MENU_PROTOTYPE.show_all()
        
        MENU_PROTOTYPE.popup_at_pointer(event)

    u/staticmethod
    def on_refresh_triggered(menu_item):
        global ACTIVE_WIDGETS
        for widget in ACTIVE_WIDGETS[:]:
            if widget:
                widget.destroy()
        ACTIVE_WIDGETS.clear()
        
        script_dir = os.path.dirname(os.path.abspath(_file_))
        config_file = os.path.join(script_dir, "honeycomb_config.json")
        
        try:
            with open(config_file, 'r') as f:
                widgets_config = json.load(f)
            saved_positions = load_all_positions()
            for config in widgets_config:
                HexagonalWidget(config, saved_positions)
        except Exception as e:
            print(f"Error refreshing: {e}")

    u/staticmethod
    def on_reset_triggered(menu_item):
        if not ACTIVE_WIDGETS:
            return
            
        widget = next(w for w in ACTIVE_WIDGETS if w)
        display = Gdk.Display.get_default()
        monitor = display.get_monitor_at_window(widget.get_window())
        geometry = monitor.get_geometry()
        
        center_x = geometry.width // 2
        center_y = geometry.height // 2
        total_widgets = len(ACTIVE_WIDGETS)
        spacing = 15
        
        total_width = (total_widgets * widget.width) + ((total_widgets - 1) * spacing)
        start_x = center_x - (total_width // 2)
        
        for idx, widget in enumerate(ACTIVE_WIDGETS):
            new_x = start_x + (idx * (widget.width + spacing))
            new_y = center_y - (widget.height // 2)
            widget.move(new_x, new_y)
            global_save_position(widget.widget_id, (new_x, new_y))

    u/staticmethod
    def on_stop_triggered(menu_item):
        Gtk.main_quit()

    u/staticmethod
    def on_open_script_triggered(menu_item):
        script_file = os.path.join(os.path.dirname(os.path.abspath(_file_)), "honeycomb.py")
        subprocess.Popen(['xdg-open', script_file], close_fds=True)

    u/staticmethod
    def on_edit_triggered(menu_item):
        config_file = os.path.join(os.path.dirname(os.path.abspath(_file_)), "honeycomb_config.json")
        subprocess.Popen(['xdg-open', config_file], close_fds=True)

    u/staticmethod
    def on_open_folder_triggered(menu_item):
        folder_path = os.path.dirname(os.path.abspath(_file_))
        subprocess.Popen(['xdg-open', folder_path], close_fds=True)

    u/staticmethod
    def on_motion_notify(widget, event):
        if event.state & Gdk.ModifierType.BUTTON1_MASK:
            widget.has_moved = True
            widget.move(int(event.x_root - widget.drag_start_x),
                       int(event.y_root - widget.drag_start_y))
            return True
        return False

    u/staticmethod
    def on_button_release(widget, event):
        if event.button == 1:
            if not widget.has_moved:
                try:
                    subprocess.Popen(widget.command, shell=True, close_fds=True)
                except Exception as e:
                    print(f"[{widget.widget_id}] Launch failed: {e}")
            else:
                widget.has_moved = False
                global_save_position(widget.widget_id, widget.get_position())
            return True
        return False

    u/staticmethod
    def on_destroy(widget):
        try:
            ACTIVE_WIDGETS.remove(widget)
        except ValueError:
            pass

def load_all_positions():
    try:
        if os.path.exists(LAYOUT_FILE):
            with open(LAYOUT_FILE, 'r') as f:
                return json.load(f)
    except Exception:
        pass
    return {}

def global_save_position(widget_id, coords):
    try:
        os.makedirs(LAYOUT_DIR, exist_ok=True)
        positions = load_all_positions()
        positions[widget_id] = {'x': int(coords[0]), 'y': int(coords[1])}
        with open(LAYOUT_FILE, 'w') as f:
            json.dump(positions, f)
    except Exception as e:
        print(f"Failed to save positions: {e}")

if _name_ == "_main_":
    script_dir = os.path.dirname(os.path.abspath(_file_))
    config_file = os.path.join(script_dir, "honeycomb_config.json")
    
    if not os.path.exists(config_file):
        print(f"Error: Config file not found at {config_file}")
        sys.exit(1)
    
    try:
        with open(config_file, 'r') as f:
            widgets_config = json.load(f)
        
        saved_positions = load_all_positions()
        
        for config in widgets_config:
            HexagonalWidget(config, saved_positions)
        
        Gtk.main()
    except KeyboardInterrupt:
        pass
    except Exception as e:
        print(f"Fatal error: {e}")

# 5. Implementation Steps

  1. Make the script executable by running this in your terminal:

    chmod +x ~/Honeycomb/honeycomb.py

  2. Run it to test:

    ~/Honeycomb/honeycomb.py

# 6. How to Use Features

* *Drag and Drop:* Hold Left-Click on any hexagon to reposition it. Release to save its position permanently.

* *Launch:* Single Left-Click on any hexagon to open the game/app you defined in teh config file.

* *Un-Clutter Feature:* Right-Click any hexagon and select "Reset Cluster" to snap all elements into a row in the center of your monitor.

## 7. Enable Auto-Start on Boot

  1. Open the Menu and launch "Startup Applications".

  2. Click the "+" icon and choose "Custom Command".

  3. Name: Honeycomb Launcher (or whatever you want)

  4. Command: python3 /home/yourusername/Honeycomb/honeycomb.py

  5. Startup Delay: Set to 3 seconds (to let Mint's desktop graphics manager finish rendering transparency before loading the hexagons)

  6. Click Save.

u/Blackirean — 1 month ago

[Fun trope when done right] The Overly capable protagonist

Better Off Ted: In the short lived comedy the main Character of Ted is a very handsome, likeable, charming, smart and capable man that excels at his job at meridian dynamics. Everyone likes him and he's a genuinely good dude. so much so that one episode focuses on the fact that only a select group of people dislike him and that's cause they're awful.

Kim Possible: The Eponymous main character is by all means an incredibly capable person. Excellent grades, head cheerleader, popular, likeable, genuinely good, athletic to the point she constantly battles supervillains. She has the occasional teen drama or insecurities but she's almost always great at whatever she does and it never deters from the show. If anything it adds weight whenever a not so capable character rises to the occasion.

Quantum leap: The main protagonist Sam Beckett is almost overpowered by normal standards. He has six doctoral degrees, a black belt in kung fu, a photographic memory, and near-virtuosic musical talent. Together with great acting skills it allows him to easily slip into the shoes of almost anyone in the past. And to be fair to make a premise like that to work you need an almost impossibly capable man.

u/Blackirean — 1 month ago
▲ 2 r/Kubuntu+2 crossposts

I need some help adapting this widget code from Linux mint cinnamon to make it work in KDE

So I recently switched from Linux mint cinnamon to Kubuntu 26.04 since I wanted to have KDE again. On mint I wanted to recreate honeycomb widgets from rainmeter for launching apps so I used some AI to come up with a script and install method that would let me do that.

I managed to do it and got it working like I wanted in my mint virtual machine at work. but the script does not work in KDE and even the same AI that helped me make it cannot make a KDE version. Any attempt has the hexagons badly rendered, pixelated or it straight up doesn't allow you to drag and organize them.

I do not know how to adapt the code and I wanted to ask for help with the matter. It took a while to get it where it is, so that the widgets are draggable, a click launches whatever command I want and right click gives me multiple options to kill it, refresh it in case I change the config file or decluster them to reorganize.

Below are the instructions and code I used to make the widgets. the PNG files were just transparent hexagonal icons for the apps I wanted:

MINT honeycomb V6

# Linux Mint Cinnamon: Floating Pointy-Top Honeycomb Launcher Guide

This guide contains everything you need to create borderless, transparent, pointy-side-up hexagonal desktop launchers that can stack into a honeycomb pattern.

---

## 1. System Dependencies

Open your terminal (Ctrl + Alt + T) and run this command to install the required GTK3 and Cairo libraries:

sudo apt update && sudo apt install python3-gi gir1.2-gtk-3.0 python3-cairo -y

---

## 2. Directory Layout

For the script to run cleanly, create this folder structure in your Home directory:

/home/YOUR_USERNAME/Honeycomb/

├── honeycomb.py

├── honeycomb_config.json

└── icons/

├── steam_hex.png

├── firefox_hex.png

└── discord_hex.png

---

## 3. Configuration File (honeycomb_config.json)

Create this file inside the Honeycomb folder. Add or remove apps by editing this JSON layout. Replace yourusername with your actual Linux Mint username.

[

{

"id": "steam",

"image_path": "/home/osboxes/Honeycomb/icons/steam_hex.png",

"command": "gnome-terminal",

"size": 120

},

{

"id": "firefox",

"image_path": "/home/osboxes/Honeycomb/icons/firefox_hex.png",

"command": "wmctrl -a firefox || firefox &",

"size": 120

},

{

"id": "discord",

"image_path": "/home/osboxes/Honeycomb/icons/discord_hex.png",

"command": "xdg-open /home/osboxes/Downloads",

"size": 120

}

]

---

## 4. The Python Script (honeycomb.py)

Create this file inside the Honeycomb folder. Paste the following complete, bug-free code block into it:

#!/usr/bin/env python3

import sys

import os

import subprocess

import math

import json

import gi

gi.require_version('Gtk', '3.0')

from gi.repository import Gtk, Gdk, GdkPixbuf, GLib

import cairo

LAYOUT_DIR = os.path.expanduser("~/.config/hex_launchers")

LAYOUT_FILE = os.path.join(LAYOUT_DIR, "positions.json")

ACTIVE_WIDGETS = []

class HexagonalWidget(Gtk.Window):

def __init__(self, config, saved_pos):

super().__init__(type=Gtk.WindowType.TOPLEVEL)

self.widget_id = config["id"]

self.image_path = config["image_path"]

self.command = config["command"]

self.height = config.get("size", 120)

self.width = int(self.height * (math.sqrt(3) / 2))

self.set_decorated(False)

self.set_app_paintable(True)

self.set_keep_above(True)

self.set_type_hint(Gdk.WindowTypeHint.DESKTOP)

self.set_default_size(self.width, self.height)

screen = self.get_screen()

visual = screen.get_rgba_visual()

if visual and screen.is_composited():

self.set_visual(visual)

self.drag_start_x = 0

self.drag_start_y = 0

self.has_moved = False

self.connect("draw", self.on_draw)

self.connect("button-press-event", self.on_button_press)

self.connect("button-release-event", self.on_button_release)

self.connect("motion-notify-event", self.on_motion_notify)

self.connect("realize", self.on_realize)

self.pixbuf = None

print(f"[{self.widget_id}] Image path: {self.image_path}")

if os.path.exists(self.image_path):

try:

self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(

self.image_path, self.width, self.height, True

)

except Exception as e:

print(f"[{self.widget_id}] Error loading image: {e}")

if saved_pos and self.widget_id in saved_pos:

pos = saved_pos[self.widget_id]

self.move(pos.get('x', 200), pos.get('y', 200))

else:

self.move(200, 200)

ACTIVE_WIDGETS.append(self)

self.show_all()

def draw_pointy_hexagon(self, cr):

center_x = self.width / 2

center_y = self.height / 2

radius = self.height / 2

start_angle = -math.pi / 2

cr.move_to(center_x + radius * math.cos(start_angle) * (math.sqrt(3)/2),

center_y + radius * math.sin(start_angle))

for i in range(1, 6):

angle = start_angle + i * (math.pi / 3)

cr.line_to(center_x + radius * math.cos(angle) * (math.sqrt(3)/2),

center_y + radius * math.sin(angle))

cr.close_path()

def on_realize(self, widget):

surface = cairo.ImageSurface(cairo.FORMAT_A1, self.width, self.height)

cr = cairo.Context(surface)

self.draw_pointy_hexagon(cr)

cr.set_source_rgba(1, 1, 1, 1)

cr.fill()

region = Gdk.cairo_region_create_from_surface(surface)

self.get_window().input_shape_combine_region(region, 0, 0)

def on_draw(self, widget, cr):

if not self.get_window():

print("Invalid window context, skipping draw.")

return

try:

cr.set_source_rgba(0, 0, 0, 0)

cr.set_operator(cairo.OPERATOR_SOURCE)

cr.paint()

cr.set_operator(cairo.OPERATOR_OVER)

if self.pixbuf:

Gdk.cairo_set_source_pixbuf(cr, self.pixbuf, 0, 0)

cr.paint()

else:

self.draw_pointy_hexagon(cr)

cr.set_source_rgba(0.2, 0.6, 0.8, 0.8)

cr.fill()

except Exception as e:

print(f"Error during drawing: {e}")

# Optionally, you can reset the widget or log the error for further analysis

def on_button_press(self, widget, event):

if event.button == 1:

self.drag_start_x = event.x

self.drag_start_y = event.y

self.has_moved = False

return True

elif event.button == 3:

self.show_context_menu(event)

return True

return False

def show_context_menu(self, event):

menu = Gtk.Menu()

# Option to Edit Honeycomb cluster

edit_item = Gtk.MenuItem(label="Edit Cluster (Add/Remove Hexagons)")

edit_item.connect("activate", self.on_edit_triggered)

menu.append(edit_item)

# Option to reset the honeycomb cluster

reset_item = Gtk.MenuItem(label="Reset Honeycomb Cluster (Un-cluster)")

reset_item.connect("activate", self.on_reset_triggered)

menu.append(reset_item)

# Option to open the main Honeycomb folder

open_folder_item = Gtk.MenuItem(label="Open Honeycomb Folder")

open_folder_item.connect("activate", self.on_open_folder_triggered)

menu.append(open_folder_item)

# Option to refresh the layout

refresh_item = Gtk.MenuItem(label="Refresh Layout")

refresh_item.connect("activate", self.on_refresh_triggered)

menu.append(refresh_item)

# Add a line spacer

menu.append(Gtk.SeparatorMenuItem())

# Option to open the main script in the default text editor

open_script_item = Gtk.MenuItem(label="Open Main Script (honeycomb.py)")

open_script_item.connect("activate", self.on_open_script_triggered)

menu.append(open_script_item)

# Option to stop the script

stop_item = Gtk.MenuItem(label="Stop Script")

stop_item.connect("activate", self.on_stop_triggered)

menu.append(stop_item)

menu.show_all()

menu.popup_at_pointer(event)

def on_refresh_triggered(self, menu_item):

# Clear existing widgets

for widget in ACTIVE_WIDGETS:

widget.destroy()

ACTIVE_WIDGETS.clear()

# Reload configuration and recreate widgets

script_dir = os.path.dirname(os.path.abspath(__file__))

config_file_path = os.path.join(script_dir, "honeycomb_config.json")

with open(config_file_path, 'r') as f:

widgets_config = json.load(f)

saved_positions = load_all_positions()

for config in widgets_config:

HexagonalWidget(config, saved_positions)

def on_reset_triggered(self, menu_item):

display = Gdk.Display.get_default()

monitor = display.get_monitor_at_window(self.get_window())

geometry = monitor.get_geometry()

center_x = geometry.width // 2

center_y = geometry.height // 2

total_widgets = len(ACTIVE_WIDGETS)

spacing = 15

row_width = (total_widgets * self.width) + ((total_widgets - 1) * spacing)

start_x = center_x - (row_width // 2)

for idx, widget in enumerate(ACTIVE_WIDGETS):

new_x = start_x + (idx * (widget.width + spacing))

new_y = center_y - (widget.height // 2)

widget.move(new_x, new_y)

global_save_position(widget.widget_id, (new_x, new_y))

def on_stop_triggered(self, menu_item):

# Logic to stop the script

Gtk.main_quit()

print("Script stopped.")

def on_open_script_triggered(self, menu_item):

# Open the primary script honeycomb.py file in the default text editor

script_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "honeycomb.py")

try:

subprocess.Popen(['xdg-open', script_file_path])

except Exception as e:

print(f"Failed to open script file: {e}")

def on_edit_triggered(self, menu_item):

# Open the honeycomb_config.json file in the default text editor

config_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "honeycomb_config.json")

try:

subprocess.Popen(['xdg-open', config_file_path])

except Exception as e:

print(f"Failed to open config file: {e}")

def on_open_folder_triggered(self, menu_item):

# Open the main Honeycomb folder in the default file manager

folder_path = os.path.dirname(os.path.abspath(__file__))

try:

subprocess.Popen(['xdg-open', folder_path])

except Exception as e:

print(f"Failed to open folder: {e}")

def on_motion_notify(self, widget, event):

if event.state & Gdk.ModifierType.BUTTON1_MASK:

self.has_moved = True

new_x = int(event.x_root - self.drag_start_x)

new_y = int(event.y_root - self.drag_start_y)

self.move(new_x, new_y)

return True

return False

def on_button_release(self, widget, event):

if event.button == 1:

if not self.has_moved:

try:

result = subprocess.run(self.command, shell=True, check=True)

if result.returncode != 0:

print(f"[{self.widget_id}] Command failed with return code: {result.returncode}")

except subprocess.CalledProcessError as e:

print(f"[{self.widget_id}] Launch failed: {e}")

except Exception as e:

print(f"[{self.widget_id}] Unexpected error: {e}")

else:

global_save_position(self.widget_id, self.get_position())

self.has_moved = False # Reset the flag after handling the release

return True

return False

def load_all_positions():

if os.path.exists(LAYOUT_FILE):

try:

with open(LAYOUT_FILE, 'r') as f:

return json.load(f)

except Exception:

return {}

return {}

def global_save_position(widget_id, coords):

try:

os.makedirs(LAYOUT_DIR, exist_ok=True)

positions = load_all_positions()

# Correctly parses x and y values from the tuple tracking window position

positions[widget_id] = {'x': int(coords[0]), 'y': int(coords[1])}

with open(LAYOUT_FILE, 'w') as f:

json.dump(positions, f, indent=4)

except Exception as e:

print(f"Failed to save positions: {e}")

if __name__ == "__main__":

script_dir = os.path.dirname(os.path.abspath(__file__)) # Corrected from _file_ to __file__

config_file_path = os.path.join(script_dir, "honeycomb_config.json")

if not os.path.exists(config_file_path):

print(f"Error: Could not find config file at {config_file_path}")

sys.exit(1)

with open(config_file_path, 'r') as f:

widgets_config = json.load(f)

saved_positions = load_all_positions()

for config in widgets_config:

HexagonalWidget(config, saved_positions)

Gtk.main()

---

## 5. Implementation Steps

  1. Make the script executable by running this in your terminal:

    chmod +x ~/Honeycomb/honeycomb.py

  2. Run it to test:

    ~/Honeycomb/honeycomb.py

## 6. How to Use Features

* *Drag and Drop:* Hold Left-Click on any hexagon to reposition it. Release to save its position permanently.

* *Launch:* Single Left-Click on any hexagon to open the game/app.

* *Un-Clutter Feature:* Right-Click any hexagon and select "Reset Honeycomb Cluster" to snap all elements into a neat row in the dead center of your monitor.

## 7. Enable Auto-Start on Boot

  1. Open the Linux Mint Menu and launch "Startup Applications".

  2. Click the "+" icon at the bottom and choose "Custom Command".

  3. Name: Honeycomb Launcher

  4. Command: python3 /home/yourusername/Honeycomb/honeycomb.py

  5. Startup Delay: Set to 3 seconds (important to let Mint's desktop graphics manager finish rendering transparency before loading the hexagons).

  6. Click Save.

reddit.com
u/Blackirean — 1 month ago

Need help mounting a drive

I recently installed Kubuntu after some rough tries with CachyOs and mint

everything is going well except for one annoyance

Mi Kubuntu install sits on my second SSD. a 4Tb drive I mainly use for games. I created 3 partitions, one for the OS, another for Linux specific storage and one for swap. The other 3.7TB left on the drive are still NTFS since I dual boot from my other SSD to Windows and that is still my game drive.

my problem is that for no apparent reason, Kubuntu is having trouble reading that partition, my other SSD, HDD and external HDD are all read properly and after setting up auto mount they also always appear mounted on boot.

however the NTFS partition on the drive where I have Linus refuses to be read. keeps telling me wrong fs type and that it cannot be mounted.

I have to run an NTFS fix command for the drive to be recognized and then automatically mounted. this did not happen on CachyOS or mint, in both I was able to have the drive automatically mounted. and both were also installed in partitions inside that same drive.

does anyone know why this is happening and how I can fix it?

I tried the NTFS fix command

went to my windows install and deactivated hibernation and everything.

I do not know what to do now.

reddit.com
u/Blackirean — 1 month ago

[Awesome trope] Tattoos with hidden/important/dangerous information

Prison Break: The Min character's upper torso is covered with a tattoo that has the prison blueprints necessary for escape.

WaterWorld: The child character Enola is branded with a tattoo that has the supposed coordinates to the only piece of dryland left on earth

Fulmetal Alchemist: Riza Hawkeye's back is tattooed with her father's research and the secrets of flame alchemy, considered one of the most dangerous types of alchemy in the world.

Space Cobra: The back of Dominique and her two other sisters are adorned with tattoos that together hold the secret location of a massive treasure.

u/Blackirean — 1 month ago

Is there any way to create widgets or shortcuts like these?

I'm new to Linux, I've been running Linux Mint Cinnamon this past week after a somewhat chaotic attempt at CachyOS. All because windows is going down a bad path.

I love that I can do most if not all the things I could do in windows. Except for one thing I'm trying to recreate.

In windows I'm a heavy user of rainmeter. Particularly to create custom icons/widgets that are on my screen at all times.

I can drag these to wherever I can, make them way bigger than most icons and with just a click I can open an .exe in whatever location I set in the .ini file, open a specific folder or straight up just set it to launch a game from steam

I've held onto these for over 15 years and while I am loving Linux I cannot be without stuff like this. How can I create something like them? I need all the help I can get. I am not above switching distros if I need to change to a more feature rich desktop environment.

I don't care about slightly lower performance in games. I don't miss the folder previews in the file explorer. Hell, I enjoy learning how to use the terminal. I JUST MISS THESE SUCKERS

For example I have this running on both monitors:

date and Time with custom font and size

And more important I have these all over my screen to launch my favorite apps and programs:

Main Honeycombs to launch games

Or these that hovers above the taskbar as some sort of makeshift dock, but one that matches the other icons on my desktop:

https://preview.redd.it/x8f3daypccch1.png?width=839&format=png&auto=webp&s=257ce95090be6788b7c286e659ffed4290e68008

Please please help. I want to abandon windows and this is my last holdout.

reddit.com
u/Blackirean — 1 month ago

Make all tabs float and only change color when actively selected

So I'm using Material Fox Updated with the latest version of firefox. The updates seem to have broken the way the tabs are connected to the toolbar.

For a while I've been locking to do some changes to the CSS and have all my tabs be floating tabs with the selected active tab simply be in a different color.

I managed to add some variables to my custom.css but I was only able to remove the curves that used to join the tabs tot he toolbar. The selected tab still moves slightly upwards when it is selected and moves down when I change tab, with the new tab also getting elevated. I want them all to be static, and only change color when selected.

Selected tab slightly higher than unselected

Hovering changes background (desired) but elevates text to same height as active tab

How can I make it so that the tabs don't move up or down when hovered or selected?

reddit.com
u/Blackirean — 1 month ago
▲ 3 r/linux4noobs+1 crossposts

NordVPN issues, does not connect on fresh install

So I just did a fresh install of CachyOS in my PC, I decided to use my secondary drive. Everything seems to be working fine, and I am trying to find alternatives to many apps that I had on windows. This is my first time using Linux in any way shape or form.

But I seem to be having problems with one in particular. And that is trying to get NordVPN to actually connect.

I am used to run a VPN at all times, not only for my browser but for everything really. I was excited to see that nordvpn had a desktop app and GUI for Linux. I followed all the steps and tried two different ways to install the app but no matter what I do I get this message:

https://preview.redd.it/szr29tmwgjbh1.png?width=900&format=png&auto=webp&s=d8354bdbf2054b71caf424d0163d86e329d39682

I have tried multiple fixes I've seen online, from uninstalling it, to trying to set the DNS in IPv4 and disabling the IPv6, turning off firewall in nord or uninstalling and reinstalling the app. And I cannot connect to Nord no matter what

I followed this guide here to install Nordvpn to an Arch based distro. This is my first time using linux and I am completely lost on what to do.

Can someone please help me?

reddit.com
u/Blackirean — 2 months ago

[Hilarious Trope] Bullet magnets aka characters that often and improbably get hit by one specific projectile way too many times

Archer: In the first few seasons of Archer the character Brett Bunsen is another employee at the spy company the main cast works at. And he has the unfortunate luck of getting shot very very often. In his birthday, at a random meeting, in the most impressive scenario he got hit by a bullet shot by Archer while he was on a different floor, it ricochet at least five times went downstairs and hit him.

Pokemon: In the Diamond an Pearl season of the anime, Dawn's Piplup is inexplicably always hit whenever Ash's Gible tries to use the move Draco Meteor, in Gible's defense he is trying to master the move. But whenever it is used it will most certainly fail and hit Piplup. The one time it worked well against an Empoleon it was deflected and it still landed on Piplup. The move has such penguin destroying accuracy that while the team was lost and separated inside a cave, Gible purposely used the move as a homing beacon; shooting it and following the blast to find Piplup in the dark cave.

Star Trek Lower Decks: In the episode Something Borrowed, Something Green Mariner, Tendi and T'Lyn travel to Orion to fin Tendi's sister. Orions are primarily known for being space pirates and as soon as they get to the planet they proceed to throw knives at the girls, hitting Mariner. At first it seemed like just another weird cultural thing Orions do, but as the episode goes every time a knife is thrown it proceeds to embed itself in Mariner's shoulder. With the last knife bouncing off a wall and embedding itself on her shoulder while she was hidden away behind a table.

u/Blackirean — 2 months ago