Ein Grid Select Menu für den Awesome Windowmanager

Nach dem Umstieg auf den awesome Windowmanager, bin ich echt begeistert, nur eins fehlte mir, ein Grid Select Menu, wie ich es von xmonad kannte. Ein Grid Select Menu zeigt mir als Overlay eine tabellarische Anordnung von Menüeinträgen / Anwendungsnamen aus denen ich dann auswählen kann und durch Klick oder Enter auf dem jeweiligen Eintrag die Anwendung starten kann.

Der awesome Windowmanager läßt sich in der Programmiersprache Lua erweitern und so habe ich eine kleine Routine geschrieben, mit der man awesome um ein Grid Select erweitern kann.

Dieses awesome widget kann bis zu 50 Menueinträge anzeigen und wird direkt über die rc.lua (Konfigurationsdatei von awesome und normalerweise im Verzeichnis ~/.config/awesome abgelegt).

Zuerst definiert man sich die gewünschten Menüeinträge und zugehörige Programme. Dabei ist der erste String der Text, der im Menü angezeigt wird und der zweite Stringe das Kommando, das bei Auswahl des Menüeintrages ausgeführt wird.

Das sieht dann z.B. so aus:

local my_appgrid = { {"Chromium", "chromium"}, {"Thunderbird", "thunderbird"} , {"Firefox", "firefox"}, {"Urxvt", "urxvt"} , {"LibreOffice Calc", "localc"}, {"LibreOffice Writer", "lowriter"} , {"PCManFM", "pcmanfm"} }
Code-Sprache: JavaScript (javascript)

Um das Menü auch aufrufen zu können verknüpft man es dann mit einer Tastenkombination. Im folgenden Beispiel ist das <Mod4> + g.

awful.key({ modkey }, "g", function() grid_select.launch({appgrid = my_appgrid}) end, {description = "Show grid selection menu", group = "custom"} )
Code-Sprache: JavaScript (javascript)

Dies Verknüpfung mit der Tastenkombination wird in rc.lua im Abschnitt globalkeys = mytable.join( … ) eingebaut.

Wer möchte kann sich auch eine andere Menge an Farben definieren. Dazu definiert man sich eine Tabelle von Farben und gibt diese als Parameter an das Widget mit.

local myColors = { „#9BB7D4“, „#C74375“, „#BF1932“, „#7BC4C4“, „#E2583E“, „#53B0AE“ }

Die Verknüpfung mit der Tastenkombination sieht dann so aus:

awful.key({ modkey }, "g", function() grid_select.launch({appgrid = my_appgrid, colors = myColors}) end, {description = "Show grid selection menu", group = "custom"} )
Code-Sprache: JavaScript (javascript)

Das Widget wird wie folgt in rc.lua eingebunden:

local grid_select = require("grid-select-widget.grid-select")
Code-Sprache: JavaScript (javascript)

Zum Abschluss der Sourcecode des Widgets, den man z.B. im Verzeichnis ~/.config/awesoem/grid-select/grid-select.lua ablegt.

------------------------------------------------- – Grid select widget for Awesome Window Manager – @author tuxlogger – @copyright 2022 Tuxlogger ------------------------------------------------- -- local awful = require("awful") local capi = {keygrabber = keygrabber } local wibox = require("wibox") local gears = require("gears") local HOME_DIR = os.getenv("HOME") – default appgrid entries to have something to start with local myAppGrid = { {"Chromium", "chromium"} , {"Thunderbird", "thunderbird"} , {"Firefox", "firefox"} , {"Urxvt", "urxvt"} , {"LibreOffice Calc", "localc"} , {"LibreOffice Writer", "lowriter"} , {"PCManFM", "pcmanfm"} } – default color palette from the pantene colors of the year local myColors = { "#9BB7D4", "#C74375", "#BF1932", "#7BC4C4", "#E2583E", "#53B0AE", "#9B1B30", "#5A5B9F", "#F0C05A", "#45B5AA", "#D94F70", "#DD4124", "#009473", "#B163A3", "#955251", "#92A8D1", "#88B04B", "#5F4B8B", "#FF6F61", "#0F4C81" } – create overlay parent widget - default local w = wibox {} – create button widget with text label, connected to command with background color bg_color local function create_button(label, command, bg_color) – create button local but = wibox.widget{ { { markup = '<span size="14000" >' .. label ..'</span>', – font size 14 align = 'center', valign = 'center', widget = wibox.widget.textbox }, top = 8, bottom = 8, left = 8, right = 8, widget = wibox.container.margin }, shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 4) end, widget = wibox.container.background } – set colors of button but:set_bg(bg_color) but:set_fg("#222222") – change button layout on enter and leave mouse focus but:connect_signal("mouse::enter", function(c) c:set_fg("#ffffff") but:set_shape( function(cr, width, height) gears.shape.hexagon(cr, width, height) end) end) but:connect_signal("mouse::leave", function(c) c:set_fg("#222222") but:set_shape( function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 4) end) end) but:connect_signal("button::press", function() awful.spawn(command) w.visible = false capi.keygrabber.stop() end) return but end – calculate the distriution of the entries to the columns – currently this works with a max of 50 entries local function calc_entry_distribution( count ) local ca= {} – pattern of the grid select layout, giving the max entries for eacht col local col_patterns = { { 1 } ,{ 2 } ,{ 1, 3, 1 } ,{ 2, 4, 2 } ,{ 1, 3, 5, 3, 1 } ,{ 2, 4, 6, 4, 2 } ,{ 1, 3, 5, 7, 5, 3, 1 } ,{ 2, 4, 6, 8, 6, 4, 2 } ,{ 1, 3, 5, 7, 9, 7, 5, 3, 1 } ,{ 2, 4, 6, 8, 10, 8, 6, 4, 2 } } – max number of entries for the patterns defined in col_patterns local max_entries = { 1, 2, 5, 8, 13, 18, 25, 32, 41, 50 } – get the index of col_patterns for the given number of entries in count local i = 1 while(max_entries[i] < count) do i = i + 1 end – return the selected pattern return col_patterns[i] end – launch grid select menu local function launch(args) args = args or {} local bg_color = args.bg_color or "#333333" local appgrid = args.appgrid or myAppGrid local colors = args.colors or myColors local default_app = args.default_app or nil – maximum elements in the middle stack of the gridselect, dirty have to fix it local maxstack = math.floor( math.log(#appgrid/2) / math.log(2) ) – update overlay parent widget, doing this here because we have to change the size w = wibox { --opacity = 0.8, max_widget_size = 1000, ontop = true, width = 130 * math.pow(maxstack,2), height = 100 * maxstack, shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 8) end } w:set_bg(bg_color) – build button widget array local button_array = {} for i = 1, #appgrid do table.insert( button_array, create_button(appgrid[i][1], appgrid[i][2], colors[i % #colors]) ) end – create container widget local l = wibox.widget { homogeneous = true, spacing = 15, min_cols_size = 10, min_rows_size = 10, expand = true, layout = wibox.layout.grid, } – get entry distribution local cols = calc_entry_distribution(#appgrid) – add buttons to the container widget using the given pattern local cc = 1 local offset = 0 local defx = 0 local defy = 0 for i = 1, #cols do – loop for columns offset = math.floor( ( math.max(table.unpack(cols)) - cols[i]) /2) for j = 1, cols[i] do – loop for rows if (button_array[cc] ~= nil) then l:add_widget_at(button_array[cc], j + offset, i) if (cc == default_app) then defx = j + offset defy = i end end cc = cc + 1 end end – show it w:set_widget(l) w.screen = mouse.screen w.visible = true awful.placement.centered(w) – focus on middle button if (default_app == nil) then x = math.ceil(#cols / 2) y = math.floor(cols[x] / 2) else x = defx y = defy end curr_button = l:get_widgets_at(x,y) curr_button[1]:emit_signal('mouse::enter') – connect to every button but default button to reformat default button on enter for i = 1, #button_array do if (i ~= default_app) then button_array[i]:connect_signal("mouse::enter", function(c) c:set_fg("#222222") button_array[default_app]:set_shape( function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 4) end) end) end end – add keyboard grabber capi.keygrabber.run(function(_, key, event) if event == "release" then return end if key then if key == 'Escape' then capi.keygrabber.stop() w.visible = false elseif key == 'Return' then curr_button[1]:emit_signal( 'button::press' ) elseif key == 'Up' then local new_x = x - 1 if new_x < 1 then new_x = 1 end local new_curr_button = l:get_widgets_at(new_x,y) if new_curr_button and new_curr_button[1] then curr_button[1]:emit_signal('mouse::leave') new_curr_button[1]:emit_signal('mouse::enter') curr_button = new_curr_button x = new_x end elseif key == 'Down' then local cmax = math.max(table.unpack(cols)) local new_x = x + 1 if new_x > cmax then new_x = cmax end local new_curr_button = l:get_widgets_at(new_x,y) if new_curr_button and new_curr_button[1] then curr_button[1]:emit_signal('mouse::leave') new_curr_button[1]:emit_signal('mouse::enter') curr_button = new_curr_button x = new_x end elseif key == 'Left' then local new_y = y - 1 if new_y < 1 then new_y = 1 end local new_curr_button = l:get_widgets_at(x,new_y) if new_curr_button and new_curr_button[1] then curr_button[1]:emit_signal('mouse::leave') new_curr_button[1]:emit_signal('mouse::enter') curr_button = new_curr_button y = new_y end elseif key == 'Right' then local new_y = y + 1 if new_y > #cols then new_y = #cols end local new_curr_button = l:get_widgets_at(x,new_y) if new_curr_button and new_curr_button[1] then curr_button[1]:emit_signal('mouse::leave') new_curr_button[1]:emit_signal('mouse::enter') curr_button = new_curr_button y = new_y end end if key == 'Escape' or string.match("Return", key) then capi.keygrabber.stop() w.visible = false end end end) end – start it return { launch = launch }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

:bye: 
:good: 
:negative:  
:scratch: 
:wacko:  
:yahoo: 
B-) 
mehr...
 


   Mit der Nutzung dieses Formulars erklärst Du Dich mit der Speicherung und Verarbeitung Deiner Daten durch diese Website einverstanden. Mehr Informationen dazu findest Du in der Datenschutzerklärung.

Jooble.de ALL-INKL.COM - Webhosting Server Hosting Domain Provider TinyURL.com - Free URL Shortener

Powered by WordPress und SoftPress-Theme by MyThemeShop.

Diese Seite verwendet Cookies. Mit der Nutzung von tuxlog erklärst Du Dich mit der Verwendung von Cookies einverstanden. Detaillierte Informationen über die Verwendung von Cookies auf dieser Website findest Du in der Datenschutzerklärung.