def main(): # exit if already running, thanks to Slava V at https://stackoverflow.com/a/384493/4040598 pid_file = os.path.join(tempfile.gettempdir(), 'sgtk-bar.pid') fp = open(pid_file, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: subprocess.run("pkill -f sgtk-bar", shell=True) sys.exit(2) global build_from_file parser = argparse.ArgumentParser(description="Button bar for sgtk-menu") placement = parser.add_mutually_exclusive_group() parser.add_argument( "-bf", type=str, help="build from file (default: {})".format(build_from_file)) parser.add_argument("-bw", type=int, default=90, help="minimum button width (default: 90)") parser.add_argument("-bh", type=int, default=90, help="minimum button height (default: 90)") placement.add_argument("-b", "--bottom", action="store_true", help="display bar at the bottom") placement.add_argument("-t", "--top", action="store_true", help="display bar at the top") parser.add_argument("-x", type=int, default=0, help="horizontal offset from edge") parser.add_argument("-y", type=int, default=0, help="vertical offset from edge") parser.add_argument("-v", "--vertical", action="store_true", help="arrange buttons vertically") parser.add_argument("-p", type=int, default=20, help="button padding (default: 20)") parser.add_argument("-s", type=int, default=32, help="icon size (min: 16, max: 48, default: 32)") parser.add_argument( "-d", type=int, default=100, help="bar delay in milliseconds (default: 100; sway & i3 only)") parser.add_argument( "-o", type=float, default=0.3, help="overlay opacity (min: 0.0, max: 1.0, default: 0.3)") parser.add_argument( "-css", type=str, default="style.css", help="use alternative {} style sheet instead of style.css".format( os.path.join(config_dir, '<CSS>'))) global args args = parser.parse_args() # Create default config files if not found create_default_configs(config_dir) css_file = os.path.join(config_dirs()[0], args.css) if os.path.exists( os.path.join(config_dirs()[0], 'style.css')) else None if args.s < 16: args.s = 16 elif args.s > 48: args.s = 48 # We do not need any delay in other WMs if other_wm: args.d = 0 # Replace appendix file name with custom - if any if args.bf: build_from_file = os.path.join(config_dirs()[0], args.bf) if css_file: screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() try: provider.load_from_path(css_file) Gtk.StyleContext.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) except Exception as e: print(e) screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() style_context = Gtk.StyleContext() style_context.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) # Overlay window global win win = MainWindow() if other_wm: # We need the window to be visible to obtain the screen geometry when i3ipc module unavailable win.resize(1, 1) win.show_all() global geometry # If we're not on sway neither i3, this won't return values until the window actually shows up. # Let's try as many times as needed. The retries int protects from an infinite loop. retries = 0 while geometry[0] == 0 and geometry[1] == 0 and geometry[ 2] == 0 and geometry[3] == 0: geometry = display_geometry(win, wm, mouse_pointer) retries += 1 if retries > 50: print("\nFailed to get the current screen geometry, exiting...\n") sys.exit(2) x, y, w, h = geometry win.resize(w, h) win.set_skip_taskbar_hint(True) if other_wm: win.move(x, y) win.show_all() GLib.timeout_add(args.d, show_bar) Gtk.main()
def main(): # exit if already running, thanks to Slava V at https://stackoverflow.com/a/384493/4040598 pid_file = os.path.join(tempfile.gettempdir(), 'sgtk-grid.pid') fp = open(pid_file, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: subprocess.run("pkill -f sgtk-grid", shell=True) sys.exit(2) global build_from_file parser = argparse.ArgumentParser( description="Application grid for sgtk-menu") parser.add_argument( '-d', type=str, default="", help="use alternate folder list (: delimited) for .Desktop files") parser.add_argument('-c', type=int, default=6, help="number of grid columns (default: 6)") parser.add_argument('-t', type=int, default=30, help="top margin width in px (default: 30)") parser.add_argument('-b', type=int, default=15, help="bottom margin width in px (default: 15)") favourites = parser.add_mutually_exclusive_group() favourites.add_argument( "-f", action="store_true", help="prepend 1 row of favourites (most used items)") favourites.add_argument('-fn', default=0, type=int, help="prepend <FN> rows of favourites") parser.add_argument("-l", type=str, help="force language (e.g. \"de\" for German)") parser.add_argument("-s", type=int, default=72, help="menu icon size (min: 16, max: 96, default: 72)") parser.add_argument( "-o", type=float, default=0.9, help="overlay opacity (min: 0.0, max: 1.0, default: 0.9)") parser.add_argument( "-css", type=str, default="grid.css", help="use alternative {} style sheet instead of grid.css".format( os.path.join(config_dir, '<CSS>'))) global args args = parser.parse_args() # Create default config files if not found create_default_configs(config_dir) css_file = os.path.join(config_dirs()[0], args.css) if os.path.exists( os.path.join(config_dirs()[0], 'style.css')) else None if args.s < 16: args.s = 16 elif args.s > 96: args.s = 96 if css_file: screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() try: provider.load_from_path(css_file) Gtk.StyleContext.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) except Exception as e: print(e) # cache stores number of clicks on each item global cache cache = load_json(cache_file) if not cache: save_json(cache, cache_file) global sorted_cache sorted_cache = sorted(cache.items(), reverse=True, key=lambda x: x[1]) global locale locale = get_locale_string(args.l) screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() style_context = Gtk.StyleContext() style_context.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) # find all .desktop entries, create AppButton class instances; list_entries() # find favourites in the list above if args.f or args.fn > 0: list_favs() # Overlay window global win win = MainWindow() geometry = (0, 0, 0, 0) # If we're not on sway neither i3, this won't return values until the window actually shows up. # Let's try as many times as needed. The retries int protects from an infinite loop. retries = 0 while geometry[0] == 0 and geometry[1] == 0 and geometry[ 2] == 0 and geometry[3] == 0: geometry = display_geometry(win, wm, mouse_pointer) retries += 1 if retries > 50: print("\nFailed to get the current screen geometry, exiting...\n") sys.exit(2) x, y, w, h = geometry if wm == "sway": win.resize(w, h) # align width of all buttons max_width = 0 for item in all_apps: width = item.get_allocated_width() if width > max_width: max_width = width for item in all_favs: item.set_size_request(max_width, max_width / 2) for item in all_apps: item.set_size_request(max_width, max_width / 2) win.search_box.set_size_request(max_width, 0) if all_favs: win.sep1.set_size_request(w / 3, 1) win.show_all() # If done inside the constructor on Openbox, stops the window from grabbing focus! win.set_skip_taskbar_hint(True) # Necessary in FVWM, otherwise it always gets on screen 0 win.move(x, y) Gtk.main()
def main(): # exit if already running, thanks to Slava V at https://stackoverflow.com/a/384493/4040598 pid_file = os.path.join(tempfile.gettempdir(), 'sgtk-menu.pid') fp = open(pid_file, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: subprocess.run("pkill -f sgtk-menu", shell=True) sys.exit(2) global build_from_file if not sys.stdin.isatty(): global pipe_menu pipe_menu = [] for line in sys.stdin: pipe_menu.append(line.rstrip()) parser = argparse.ArgumentParser(description="GTK menu for sway, i3 and some other WMs") placement = parser.add_mutually_exclusive_group() placement.add_argument("-b", "--bottom", action="store_true", help="display menu at the bottom") placement.add_argument("-c", "--center", action="store_true", help="center menu on the screen") placement.add_argument("-p", "--pointer", action="store_true", help="display at mouse pointer (not-sway only)") favourites = parser.add_mutually_exclusive_group() favourites.add_argument("-f", "--favourites", action="store_true", help="prepend 5 most used items") favourites.add_argument('-fn', type=int, help="prepend <FN> most used items") appendix = parser.add_mutually_exclusive_group() appendix.add_argument("-a", "--append", action="store_true", help="append custom menu from {}".format(build_from_file)) appendix.add_argument("-af", type=str, help="append custom menu from {}".format(os.path.join(config_dir, '<AF>'))) parser.add_argument("-n", "--no-menu", action="store_true", help="skip menu, display appendix only") parser.add_argument("-l", type=str, help="force language (e.g. \"de\" for German)") parser.add_argument("-s", type=int, default=20, help="menu icon size (min: 16, max: 48, default: 20)") parser.add_argument("-w", type=int, help="menu width in px (integer, default: screen width / 8)") parser.add_argument("-d", type=int, default=100, help="menu delay in milliseconds (default: 100; sway & i3 only)") parser.add_argument("-o", type=float, default=0.3, help="overlay opacity (min: 0.0, max: 1.0, default: 0.3; sway only)") parser.add_argument("-t", type=int, default=30, help="sway submenu lines limit (default: 30)") parser.add_argument("-y", type=int, default=0, help="y offset from edge to display menu at") parser.add_argument("-css", type=str, default="style.css", help="use alternative {} style sheet instead of style.css" .format(os.path.join(config_dir, '<CSS>'))) parser.add_argument("-v", "--version", action="store_true", help="display version and exit") parser.add_argument("-wm", action="store_true", help="display detected Window Manager and exit") global args args = parser.parse_args() if args.version: print_version() sys.exit(0) if args.wm: print(wm) sys.exit(0) if pipe_menu: args.no_menu = True if not wm == "sway" and not args.d == 100: args.d = 0 print("[-d] argument ignored if not-sway") # Create default config files if not found create_default_configs(config_dir) css_file = os.path.join(config_dirs()[0], args.css) if os.path.exists( os.path.join(config_dirs()[0], 'style.css')) else None if args.s < 16: args.s = 16 elif args.s > 48: args.s = 48 # Replace appendix file name with custom - if any if args.af: build_from_file = os.path.join(config_dirs()[0], args.af) if css_file: screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() try: provider.load_from_path(css_file) Gtk.StyleContext.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) except Exception as e: print(e) # cache stores number of clicks on each item global cache cache = load_json(cache_file) if not cache: save_json(cache, cache_file) global sorted_cache sorted_cache = sorted(cache.items(), reverse=True, key=lambda x: x[1]) global locale locale = get_locale_string(args.l) category_names_dictionary = localized_category_names(locale) # replace additional category names with main ones for name in category_names: main_category_name = additional_to_main(name) try: localized_names_dictionary[main_category_name] = category_names_dictionary[main_category_name] except: pass screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() style_context = Gtk.StyleContext() style_context.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # find all .desktop entries, create DesktopEntry class instances; # DesktopEntry adds itself to the proper List in the class constructor list_entries() # Overlay window global win win = MainWindow() geometry = (0, 0, 0, 0) # If we're not on sway neither i3, this won't return values until the window actually shows up. # Let's try as many times as needed. The retries int protects from an infinite loop. retries = 0 while geometry[0] == 0 and geometry[1] == 0 and geometry[2] == 0 and geometry[3] == 0: geometry = display_geometry(win, wm, mouse_pointer) retries += 1 if retries > 50: print("\nFailed to get the current screen geometry, exiting...\n") sys.exit(2) x, y, w, h = geometry if wm == "sway": # resize to current screen dimensions on sway win.resize(w, h) else: win.resize(0, 0) if args.center: x = x + (w // 2) y = y + (h // 2) elif args.bottom: y = h - args.y elif args.pointer: if mouse_pointer: x, y = mouse_pointer.position else: print("\nYou need the python-pynput package!\n") else: y = y + args.y win.move(x, y) win.menu = build_menu() win.menu.set_property("name", "menu") global menu_items_list menu_items_list = win.menu.get_children() win.menu.propagate_key_event = False win.menu.connect("key-release-event", win.search_items) # Let's reserve some width for long entries found with the search box if args.w: win.menu.set_property("width_request", args.w) else: win.menu.set_property("width_request", int(win.screen_dimensions[0] / 8)) win.show_all() GLib.timeout_add(args.d, open_menu) Gtk.main()
def main(): # exit if already running, thanks to Slava V at https://stackoverflow.com/a/384493/4040598 pid_file = os.path.join(tempfile.gettempdir(), 'sgtk-dmenu.pid') fp = open(pid_file, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: subprocess.run("pkill -f sgtk-dmenu", shell=True) sys.exit(2) global build_from_file parser = argparse.ArgumentParser( description="GTK menu for sway, i3 and some floating WMs") placement = parser.add_mutually_exclusive_group() placement.add_argument("-b", "--bottom", action="store_true", help="display menu at the bottom (sway & i3 only)") placement.add_argument("-c", "--center", action="store_true", help="center menu on the screen (sway & i3 only)") appendix = parser.add_mutually_exclusive_group() appendix.add_argument( "-a", "--append", action="store_true", help="append custom menu from {}".format(build_from_file)) appendix.add_argument("-af", type=str, help="append custom menu from {}".format( os.path.join(config_dir, '<AF>'))) parser.add_argument("-s", type=int, default=20, help="menu icon size (min: 16, max: 48, default: 20)") parser.add_argument( "-w", type=int, help="menu width in px (integer, default: screen width / 8)") parser.add_argument( "-d", type=int, default=100, help="menu delay in milliseconds (default: 100; sway & i3 only)") parser.add_argument( "-o", type=float, default=0.3, help="overlay opacity (min: 0.0, max: 1.0, default: 0.3; " "sway & i3 only)") parser.add_argument("-t", type=int, default=15, help="lines limit (default: 20)") parser.add_argument( "-y", type=int, default=0, help="y offset from edge to display menu at (sway & i3 only)") parser.add_argument( "-css", type=str, default="style.css", help="use alternative {} style sheet instead of style.css".format( os.path.join(config_dir, '<CSS>'))) global args args = parser.parse_args() # Copy default templates and style sheet - if not found create_default_configs(config_dir) css_file = os.path.join(config_dirs()[0], args.css) if os.path.exists( os.path.join(config_dirs()[0], 'style.css')) else None if args.s < 16: args.s = 16 elif args.s > 48: args.s = 48 # We do not need any delay in other WMs if other_wm: args.d = 0 # Replace appendix template file name with custom - if any if args.af: build_from_file = os.path.join(config_dirs()[0], args.af) if css_file: screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() try: provider.load_from_path(css_file) Gtk.StyleContext.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) except Exception as e: print(e) screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() style_context = Gtk.StyleContext() style_context.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) global all_commands_list all_commands_list = list_commands() all_commands_list.sort() # Overlay window global win win = MainWindow() if other_wm: # We need this to obtain the screen geometry when i3ipc module unavailable win.resize(1, 1) win.show_all() global geometry # If we're not on sway neither i3, this won't return values until the window actually shows up. # Let's try as many times as needed. The retries int protects from an infinite loop. retries = 0 while geometry[0] == 0 and geometry[1] == 0 and geometry[ 2] == 0 and geometry[3] == 0: geometry = display_geometry(win, wm, mouse_pointer) retries += 1 if retries > 50: print("\nFailed to get the current screen geometry, exiting...\n") sys.exit(2) x, y, w, h = geometry if not other_wm: # resize to the active screen dimensions on sway/i3 win.resize(w, h) else: win.resize(1, 1) win.set_gravity(Gdk.Gravity.CENTER) if mouse_pointer: x, y = mouse_pointer.position win.move(x, y) else: win.move(0, 0) print("\nYou need the python-pynput package!\n") # hide window from panel on Openbox win.set_skip_taskbar_hint(True) win.menu = build_menu(all_commands_list) win.menu.set_property("name", "menu") global menu_items_list menu_items_list = win.menu.get_children() win.menu.propagate_key_event = False win.menu.connect("key-release-event", win.search_items) # Let's reserve some width for long entries found with the search box if args.w: win.menu.set_property("width_request", args.w) else: win.menu.set_property("width_request", int(win.screen_dimensions[0] / 8)) win.show_all() # on sway/i3 we need a timeout for window to appear in the proper place; for other_wm args.d has been zeroed GLib.timeout_add(args.d, open_menu) Gtk.main()