diff options
Diffstat (limited to 'config/ags/modules/overview')
| -rw-r--r-- | config/ags/modules/overview/actions.js | 28 | ||||
| -rw-r--r-- | config/ags/modules/overview/main.js | 18 | ||||
| -rw-r--r-- | config/ags/modules/overview/miscfunctions.js | 155 | ||||
| -rw-r--r-- | config/ags/modules/overview/overview_hyprland.js | 423 | ||||
| -rw-r--r-- | config/ags/modules/overview/searchbuttons.js | 163 | ||||
| -rw-r--r-- | config/ags/modules/overview/searchitem.js | 65 | ||||
| -rw-r--r-- | config/ags/modules/overview/windowcontent.js | 262 |
7 files changed, 0 insertions, 1114 deletions
diff --git a/config/ags/modules/overview/actions.js b/config/ags/modules/overview/actions.js deleted file mode 100644 index 766cf454..00000000 --- a/config/ags/modules/overview/actions.js +++ /dev/null @@ -1,28 +0,0 @@ -import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; - -function moveClientToWorkspace(address, workspace) { - Utils.execAsync(['bash', '-c', `hyprctl dispatch movetoworkspacesilent ${workspace},address:${address} &`]); -} - -export function dumpToWorkspace(from, to) { - if (from == to) return; - Hyprland.clients.forEach(client => { - if (client.workspace.id == from) { - moveClientToWorkspace(client.address, to); - } - }); -} - -export function swapWorkspace(workspaceA, workspaceB) { - if (workspaceA == workspaceB) return; - const clientsA = []; - const clientsB = []; - Hyprland.clients.forEach(client => { - if (client.workspace.id == workspaceA) clientsA.push(client.address); - if (client.workspace.id == workspaceB) clientsB.push(client.address); - }); - - clientsA.forEach((address) => moveClientToWorkspace(address, workspaceB)); - clientsB.forEach((address) => moveClientToWorkspace(address, workspaceA)); -}
\ No newline at end of file diff --git a/config/ags/modules/overview/main.js b/config/ags/modules/overview/main.js deleted file mode 100644 index 1f5348d9..00000000 --- a/config/ags/modules/overview/main.js +++ /dev/null @@ -1,18 +0,0 @@ -import Widget from 'resource:///com/github/Aylur/ags/widget.js'; -import { SearchAndWindows } from "./windowcontent.js"; -import PopupWindow from '../.widgethacks/popupwindow.js'; - -export default (id = '') => PopupWindow({ - name: `overview${id}`, - exclusivity: 'ignore', - keymode: 'exclusive', - visible: false, - // anchor: ['middle'], - layer: 'overlay', - child: Widget.Box({ - vertical: true, - children: [ - SearchAndWindows(), - ] - }), -}) diff --git a/config/ags/modules/overview/miscfunctions.js b/config/ags/modules/overview/miscfunctions.js deleted file mode 100644 index 187ee6ec..00000000 --- a/config/ags/modules/overview/miscfunctions.js +++ /dev/null @@ -1,155 +0,0 @@ -const { Gio, GLib } = imports.gi; -import App from 'resource:///com/github/Aylur/ags/app.js'; -import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; -const { execAsync, exec } = Utils; -// import Todo from "../../services/todo.js"; -import { darkMode } from '../.miscutils/system.js'; - -export function hasUnterminatedBackslash(inputString) { - // Use a regular expression to match a trailing odd number of backslashes - const regex = /\\+$/; - return regex.test(inputString); -} - -export function launchCustomCommand(command) { - const args = command.toLowerCase().split(' '); - if (args[0] == '>raw') { // Mouse raw input - Utils.execAsync('hyprctl -j getoption input:accel_profile') - .then((output) => { - const value = JSON.parse(output)["str"].trim(); - if (value != "[[EMPTY]]" && value != "") { - execAsync(['bash', '-c', `hyprctl keyword input:accel_profile '[[EMPTY]]'`]).catch(print); - } - else { - execAsync(['bash', '-c', `hyprctl keyword input:accel_profile flat`]).catch(print); - } - }) - } - else if (args[0] == '>img') { // Change wallpaper - execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchwall.sh`, `&`]).catch(print); - } - else if (args[0] == '>color') { // Generate colorscheme from color picker - execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchcolor.sh --pick`, `&`]).catch(print); - } - else if (args[0] == '>light') { // Light mode - darkMode.value = false; - execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && sed -i "1s/.*/light/" ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`]) - .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`])) - .catch(print); - } - else if (args[0] == '>dark') { // Dark mode - darkMode.value = true; - execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && sed -i "1s/.*/dark/" ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`]) - .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`])) - .catch(print); - } - else if (args[0] == '>badapple') { // Black and white - execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && sed -i "3s/.*/monochrome/" ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`]) - .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`])) - .catch(print); - } - else if (args[0] == '>material') { // Use material colors - execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "material" > ${GLib.get_user_cache_dir()}/ags/user/colorbackend.txt`]).catch(print) - .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchwall.sh --noswitch`]).catch(print)) - .catch(print); - } - else if (args[0] == '>pywal') { // Use Pywal (ik it looks shit but I'm not removing) - execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "pywal" > ${GLib.get_user_cache_dir()}/ags/user/colorbackend.txt`]).catch(print) - .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchwall.sh --noswitch`]).catch(print)) - .catch(print); - } - else if (args[0] == '>todo') { // Todo - Todo.add(args.slice(1).join(' ')); - } - else if (args[0] == '>shutdown') { // Shut down - execAsync([`bash`, `-c`, `systemctl poweroff || loginctl poweroff`]).catch(print); - } - else if (args[0] == '>reboot') { // Reboot - execAsync([`bash`, `-c`, `systemctl reboot || loginctl reboot`]).catch(print); - } - else if (args[0] == '>sleep') { // Sleep - execAsync([`bash`, `-c`, `systemctl suspend || loginctl suspend`]).catch(print); - } - else if (args[0] == '>logout') { // Log out - execAsync([`bash`, `-c`, `pkill Hyprland || pkill sway`]).catch(print); - } -} - -export function execAndClose(command, terminal) { - App.closeWindow('overview'); - if (terminal) { - execAsync([`bash`, `-c`, `${userOptions.apps.terminal} fish -C "${command}"`, `&`]).catch(print); - } - else - execAsync(command).catch(print); -} - -export function couldBeMath(str) { - const regex = /^[0-9.+*/-]/; - return regex.test(str); -} - -export function expandTilde(path) { - if (path.startsWith('~')) { - return GLib.get_home_dir() + path.slice(1); - } else { - return path; - } -} - -function getFileIcon(fileInfo) { - let icon = fileInfo.get_icon(); - if (icon) { - // Get the icon's name - return icon.get_names()[0]; - } else { - // Default icon for files - return 'text-x-generic'; - } -} - -export function ls({ path = '~', silent = false }) { - let contents = []; - try { - let expandedPath = expandTilde(path); - if (expandedPath.endsWith('/')) - expandedPath = expandedPath.slice(0, -1); - let folder = Gio.File.new_for_path(expandedPath); - - let enumerator = folder.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null); - let fileInfo; - while ((fileInfo = enumerator.next_file(null)) !== null) { - let fileName = fileInfo.get_display_name(); - let fileType = fileInfo.get_file_type(); - - let item = { - parentPath: expandedPath, - name: fileName, - type: fileType === Gio.FileType.DIRECTORY ? 'folder' : 'file', - icon: getFileIcon(fileInfo), - }; - - // Add file extension for files - if (fileType === Gio.FileType.REGULAR) { - let fileExtension = fileName.split('.').pop(); - item.type = `${fileExtension}`; - } - - contents.push(item); - contents.sort((a, b) => { - const aIsFolder = a.type.startsWith('folder'); - const bIsFolder = b.type.startsWith('folder'); - if (aIsFolder && !bIsFolder) { - return -1; - } else if (!aIsFolder && bIsFolder) { - return 1; - } else { - return a.name.localeCompare(b.name); // Sort alphabetically within folders and files - } - }); - } - } catch (e) { - if (!silent) console.log(e); - } - return contents; -} diff --git a/config/ags/modules/overview/overview_hyprland.js b/config/ags/modules/overview/overview_hyprland.js deleted file mode 100644 index 034d6c81..00000000 --- a/config/ags/modules/overview/overview_hyprland.js +++ /dev/null @@ -1,423 +0,0 @@ -// TODO -// - Make client destroy/create not destroy and recreate the whole thing -// - Active ws hook optimization: only update when moving to next group -// -const { Gdk, Gtk } = imports.gi; -const { Gravity } = imports.gi.Gdk; -import { SCREEN_HEIGHT, SCREEN_WIDTH } from '../../variables.js'; -import App from 'resource:///com/github/Aylur/ags/app.js'; -import Variable from 'resource:///com/github/Aylur/ags/variable.js'; -import Widget from 'resource:///com/github/Aylur/ags/widget.js'; -import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; - -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -const { execAsync, exec } = Utils; -import { setupCursorHoverGrab } from '../.widgetutils/cursorhover.js'; -import { dumpToWorkspace, swapWorkspace } from "./actions.js"; -import { substitute } from "../.miscutils/icons.js"; - -const NUM_OF_WORKSPACES_SHOWN = userOptions.overview.numOfCols * userOptions.overview.numOfRows; -const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; -const POPUP_CLOSE_TIME = 100; // ms - -const overviewTick = Variable(false); - -export default () => { - const clientMap = new Map(); - let workspaceGroup = 0; - const ContextMenuWorkspaceArray = ({ label, actionFunc, thisWorkspace }) => Widget.MenuItem({ - label: `${label}`, - setup: (menuItem) => { - let submenu = new Gtk.Menu(); - submenu.className = 'menu'; - - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - const startWorkspace = offset + 1; - const endWorkspace = startWorkspace + NUM_OF_WORKSPACES_SHOWN - 1; - for (let i = startWorkspace; i <= endWorkspace; i++) { - let button = new Gtk.MenuItem({ - label: `Workspace ${i}` - }); - button.connect("activate", () => { - // execAsync([`${onClickBinary}`, `${thisWorkspace}`, `${i}`]).catch(print); - actionFunc(thisWorkspace, i); - overviewTick.setValue(!overviewTick.value); - }); - submenu.append(button); - } - menuItem.set_reserve_indicator(true); - menuItem.set_submenu(submenu); - } - }) - - const Window = ({ address, at: [x, y], size: [w, h], workspace: { id, name }, class: c, title, xwayland }, screenCoords) => { - const revealInfoCondition = (Math.min(w, h) * userOptions.overview.scale > 70); - if (w <= 0 || h <= 0 || (c === '' && title === '') || c.endsWith('-dropterm')) return null; - // Non-primary monitors - if (screenCoords.x != 0) x -= screenCoords.x; - if (screenCoords.y != 0) y -= screenCoords.y; - // Other offscreen adjustments - if (x + w <= 0) x += (Math.floor(x / SCREEN_WIDTH) * SCREEN_WIDTH); - else if (x < 0) { w = x + w; x = 0; } - if (y + h <= 0) x += (Math.floor(y / SCREEN_HEIGHT) * SCREEN_HEIGHT); - else if (y < 0) { h = y + h; y = 0; } - // Truncate if offscreen - if (x + w > SCREEN_WIDTH) w = SCREEN_WIDTH - x; - if (y + h > SCREEN_HEIGHT) h = SCREEN_HEIGHT - y; - - const appIcon = Widget.Icon({ - icon: substitute(c), - size: Math.min(w, h) * userOptions.overview.scale / 2.5, - }); - return Widget.Button({ - attribute: { - address, x, y, w, h, ws: id, - updateIconSize: (self) => { - appIcon.size = Math.min(self.attribute.w, self.attribute.h) * userOptions.overview.scale / 2.5; - }, - }, - className: 'overview-tasks-window', - hpack: 'start', - vpack: 'start', - css: ` - margin-left: ${Math.round(x * userOptions.overview.scale)}px; - margin-top: ${Math.round(y * userOptions.overview.scale)}px; - margin-right: -${Math.round((x + w) * userOptions.overview.scale)}px; - margin-bottom: -${Math.round((y + h) * userOptions.overview.scale)}px; - `, - onClicked: (self) => { - App.closeWindow('overview'); - Utils.timeout(POPUP_CLOSE_TIME, () => Hyprland.messageAsync(`dispatch focuswindow address:${address}`)); - }, - onMiddleClickRelease: () => Hyprland.messageAsync(`dispatch closewindow address:${address}`), - onSecondaryClick: (button) => { - button.toggleClassName('overview-tasks-window-selected', true); - const menu = Widget.Menu({ - className: 'menu', - children: [ - Widget.MenuItem({ - child: Widget.Label({ - xalign: 0, - label: "Close (Middle-click)", - }), - onActivate: () => Hyprland.messageAsync(`dispatch closewindow address:${address}`), - }), - ContextMenuWorkspaceArray({ - label: "Dump windows to workspace", - actionFunc: dumpToWorkspace, - thisWorkspace: Number(id) - }), - ContextMenuWorkspaceArray({ - label: "Swap windows with workspace", - actionFunc: swapWorkspace, - thisWorkspace: Number(id) - }), - ], - }); - menu.connect("deactivate", () => { - button.toggleClassName('overview-tasks-window-selected', false); - }) - menu.connect("selection-done", () => { - button.toggleClassName('overview-tasks-window-selected', false); - }) - menu.popup_at_widget(button.get_parent(), Gravity.SOUTH, Gravity.NORTH, null); // Show menu below the button - button.connect("destroy", () => menu.destroy()); - }, - child: Widget.Box({ - homogeneous: true, - child: Widget.Box({ - vertical: true, - vpack: 'center', - className: 'spacing-v-5', - children: [ - appIcon, - // TODO: Add xwayland tag instead of just having italics - Widget.Revealer({ - transition: 'slide_down', - revealChild: revealInfoCondition, - child: Widget.Label({ - maxWidthChars: 10, // Doesn't matter what number - truncate: 'end', - className: `${xwayland ? 'txt txt-italic' : 'txt'}`, - css: ` - font-size: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * userOptions.overview.scale / 14.6}px; - margin: 0px ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * userOptions.overview.scale / 10}px; - `, - // If the title is too short, include the class - label: (title.length <= 1 ? `${c}: ${title}` : title), - }) - }) - ] - }) - }), - tooltipText: `${c}: ${title}`, - setup: (button) => { - setupCursorHoverGrab(button); - - button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.MOVE); - button.drag_source_set_icon_name(substitute(c)); - // button.drag_source_set_icon_gicon(icon); - - button.connect('drag-begin', (button) => { // On drag start, add the dragging class - button.toggleClassName('overview-tasks-window-dragging', true); - }); - button.connect('drag-data-get', (_w, _c, data) => { // On drag finish, give address - data.set_text(address, address.length); - button.toggleClassName('overview-tasks-window-dragging', false); - }); - }, - }); - } - - const Workspace = (index) => { - // const fixed = Widget.Fixed({ - // attribute: { - // put: (widget, x, y) => { - // fixed.put(widget, x, y); - // }, - // move: (widget, x, y) => { - // fixed.move(widget, x, y); - // }, - // } - // }); - const fixed = Widget.Box({ - attribute: { - put: (widget, x, y) => { - if (!widget.attribute) return; - // Note: x and y are already multiplied by userOptions.overview.scale - const newCss = ` - margin-left: ${Math.round(x)}px; - margin-top: ${Math.round(y)}px; - margin-right: -${Math.round(x + (widget.attribute.w * userOptions.overview.scale))}px; - margin-bottom: -${Math.round(y + (widget.attribute.h * userOptions.overview.scale))}px; - `; - widget.css = newCss; - fixed.pack_start(widget, false, false, 0); - }, - move: (widget, x, y) => { - if (!widget) return; - if (!widget.attribute) return; - // Note: x and y are already multiplied by userOptions.overview.scale - const newCss = ` - margin-left: ${Math.round(x)}px; - margin-top: ${Math.round(y)}px; - margin-right: -${Math.round(x + (widget.attribute.w * userOptions.overview.scale))}px; - margin-bottom: -${Math.round(y + (widget.attribute.h * userOptions.overview.scale))}px; - `; - widget.css = newCss; - }, - } - }) - const WorkspaceNumber = ({ index, ...rest }) => Widget.Label({ - className: 'overview-tasks-workspace-number', - label: `${index}`, - css: ` - margin: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * userOptions.overview.scale * userOptions.overview.wsNumMarginScale}px; - font-size: ${SCREEN_HEIGHT * userOptions.overview.scale * userOptions.overview.wsNumScale}px; - `, - setup: (self) => self.hook(Hyprland.active.workspace, (self) => { - // Update when going to new ws group - const currentGroup = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN); - self.label = `${currentGroup * NUM_OF_WORKSPACES_SHOWN + index}`; - }), - ...rest, - }) - const widget = Widget.Box({ - className: 'overview-tasks-workspace', - vpack: 'center', - css: ` - min-width: ${SCREEN_WIDTH * userOptions.overview.scale}px; - min-height: ${SCREEN_HEIGHT * userOptions.overview.scale}px; - `, - children: [Widget.EventBox({ - hexpand: true, - vexpand: true, - onPrimaryClick: () => { - App.closeWindow('overview'); - Utils.timeout(POPUP_CLOSE_TIME, () => Hyprland.messageAsync(`dispatch workspace ${index}`)); - }, - setup: (eventbox) => { - eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); - eventbox.connect('drag-data-received', (_w, _c, _x, _y, data) => { - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - Hyprland.messageAsync(`dispatch movetoworkspacesilent ${index + offset},address:${data.get_text()}`) - overviewTick.setValue(!overviewTick.value); - }); - }, - child: Widget.Overlay({ - child: Widget.Box({}), - overlays: [ - WorkspaceNumber({ index: index, hpack: 'start', vpack: 'start' }), - fixed - ] - }), - })], - }); - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - fixed.attribute.put(WorkspaceNumber(offset + index), 0, 0); - widget.clear = () => { - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - clientMap.forEach((client, address) => { - if (!client) return; - if ((client.attribute.ws <= offset || client.attribute.ws > offset + NUM_OF_WORKSPACES_SHOWN) || - (client.attribute.ws == offset + index)) { - client.destroy(); - client = null; - clientMap.delete(address); - } - }); - } - widget.set = (clientJson, screenCoords) => { - let c = clientMap.get(clientJson.address); - if (c) { - if (c.attribute?.ws !== clientJson.workspace.id) { - c.destroy(); - c = null; - clientMap.delete(clientJson.address); - } - else if (c) { - c.attribute.w = clientJson.size[0]; - c.attribute.h = clientJson.size[1]; - c.attribute.updateIconSize(c); - fixed.attribute.move(c, - Math.max(0, clientJson.at[0] * userOptions.overview.scale), - Math.max(0, clientJson.at[1] * userOptions.overview.scale) - ); - return; - } - } - const newWindow = Window(clientJson, screenCoords); - if (newWindow === null) return; - // clientMap.set(clientJson.address, newWindow); - fixed.attribute.put(newWindow, - Math.max(0, newWindow.attribute.x * userOptions.overview.scale), - Math.max(0, newWindow.attribute.y * userOptions.overview.scale) - ); - clientMap.set(clientJson.address, newWindow); - }; - widget.unset = (clientAddress) => { - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - let c = clientMap.get(clientAddress); - if (!c) return; - c.destroy(); - c = null; - clientMap.delete(clientAddress); - }; - widget.show = () => { - fixed.show_all(); - } - return widget; - }; - - const arr = (s, n) => { - const array = []; - for (let i = 0; i < n; i++) - array.push(s + i); - - return array; - }; - - const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) => Widget.Box({ - children: arr(startWorkspace, workspaces).map(Workspace), - attribute: { - monitorMap: [], - getMonitorMap: (box) => { - execAsync('hyprctl -j monitors').then(monitors => { - box.attribute.monitorMap = JSON.parse(monitors).reduce((acc, item) => { - acc[item.id] = { x: item.x, y: item.y }; - return acc; - }, {}); - }); - }, - update: (box) => { - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - if (!App.getWindow(windowName).visible) return; - Hyprland.messageAsync('j/clients').then(clients => { - const allClients = JSON.parse(clients); - const kids = box.get_children(); - kids.forEach(kid => kid.clear()); - for (let i = 0; i < allClients.length; i++) { - const client = allClients[i]; - const childID = client.workspace.id - (offset + startWorkspace); - if (offset + startWorkspace <= client.workspace.id && - client.workspace.id <= offset + startWorkspace + workspaces) { - const screenCoords = box.attribute.monitorMap[client.monitor]; - if (kids[childID]) { - kids[childID].set(client, screenCoords); - } - continue; - } - } - kids.forEach(kid => kid.show()); - }).catch(print); - }, - updateWorkspace: (box, id) => { - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - if (!( // Not in range, ignore - offset + startWorkspace <= id && - id <= offset + startWorkspace + workspaces - )) return; - // if (!App.getWindow(windowName).visible) return; - Hyprland.messageAsync('j/clients').then(clients => { - const allClients = JSON.parse(clients); - const kids = box.get_children(); - for (let i = 0; i < allClients.length; i++) { - const client = allClients[i]; - if (client.workspace.id != id) continue; - const screenCoords = box.attribute.monitorMap[client.monitor]; - kids[id - (offset + startWorkspace)]?.set(client, screenCoords); - } - kids[id - (offset + startWorkspace)]?.show(); - }).catch(print); - }, - }, - setup: (box) => { - box.attribute.getMonitorMap(box); - box - .hook(overviewTick, (box) => box.attribute.update(box)) - .hook(Hyprland, (box, clientAddress) => { - const offset = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN) * NUM_OF_WORKSPACES_SHOWN; - const kids = box.get_children(); - const client = Hyprland.getClient(clientAddress); - if (!client) return; - const id = client.workspace.id; - - box.attribute.updateWorkspace(box, id); - kids[id - (offset + startWorkspace)]?.unset(clientAddress); - }, 'client-removed') - .hook(Hyprland, (box, clientAddress) => { - const client = Hyprland.getClient(clientAddress); - if (!client) return; - box.attribute.updateWorkspace(box, client.workspace.id); - }, 'client-added') - .hook(Hyprland.active.workspace, (box) => { - // Full update when going to new ws group - const previousGroup = box.attribute.workspaceGroup; - const currentGroup = Math.floor((Hyprland.active.workspace.id - 1) / NUM_OF_WORKSPACES_SHOWN); - if (currentGroup !== previousGroup) { - box.attribute.update(box); - box.attribute.workspaceGroup = currentGroup; - } - }) - .hook(App, (box, name, visible) => { // Update on open - if (name == 'overview' && visible) box.attribute.update(box); - }) - }, - }); - - return Widget.Revealer({ - revealChild: true, - transition: 'slide_down', - transitionDuration: userOptions.animations.durationLarge, - child: Widget.Box({ - vertical: true, - className: 'overview-tasks', - children: Array.from({ length: userOptions.overview.numOfRows }, (_, index) => - OverviewRow({ - startWorkspace: 1 + index * userOptions.overview.numOfCols, - workspaces: userOptions.overview.numOfCols, - }) - ) - }), - }); -}
\ No newline at end of file diff --git a/config/ags/modules/overview/searchbuttons.js b/config/ags/modules/overview/searchbuttons.js deleted file mode 100644 index f5892f31..00000000 --- a/config/ags/modules/overview/searchbuttons.js +++ /dev/null @@ -1,163 +0,0 @@ -const { Gtk } = imports.gi; -import App from 'resource:///com/github/Aylur/ags/app.js'; -import Widget from 'resource:///com/github/Aylur/ags/widget.js'; -import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; -const { execAsync, exec } = Utils; -import { searchItem } from './searchitem.js'; -import { execAndClose, couldBeMath, launchCustomCommand } from './miscfunctions.js'; - -export const DirectoryButton = ({ parentPath, name, type, icon }) => { - const actionText = Widget.Revealer({ - revealChild: false, - transition: "crossfade", - transitionDuration: userOptions.animations.durationLarge, - child: Widget.Label({ - className: 'overview-search-results-txt txt txt-small txt-action', - label: 'Open', - }) - }); - const actionTextRevealer = Widget.Revealer({ - revealChild: false, - transition: "slide_left", - transitionDuration: userOptions.animations.durationSmall, - child: actionText, - }); - return Widget.Button({ - className: 'overview-search-result-btn', - onClicked: () => { - App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open '${parentPath}/${name}'`, `&`]).catch(print); - }, - child: Widget.Box({ - children: [ - Widget.Box({ - vertical: false, - children: [ - Widget.Box({ - className: 'overview-search-results-icon', - homogeneous: true, - child: Widget.Icon({ - icon: icon, - }), - }), - Widget.Label({ - className: 'overview-search-results-txt txt txt-norm', - label: name, - }), - Widget.Box({ hexpand: true }), - actionTextRevealer, - ] - }) - ] - }), - setup: (self) => self - .on('focus-in-event', (button) => { - actionText.revealChild = true; - actionTextRevealer.revealChild = true; - }) - .on('focus-out-event', (button) => { - actionText.revealChild = false; - actionTextRevealer.revealChild = false; - }) - , - }) -} - -export const CalculationResultButton = ({ result, text }) => searchItem({ - materialIconName: ' ', - name: `Math result`, - actionName: "Copy", - content: `${result}`, - onActivate: () => { - App.closeWindow('overview'); - execAsync(['wl-copy', `${result}`]).catch(print); - }, -}); - -export const DesktopEntryButton = (app) => { - const actionText = Widget.Revealer({ - revealChild: false, - transition: "crossfade", - transitionDuration: userOptions.animations.durationLarge, - child: Widget.Label({ - className: 'overview-search-results-txt txt txt-small txt-action', - label: 'Launch', - }) - }); - const actionTextRevealer = Widget.Revealer({ - revealChild: false, - transition: "slide_left", - transitionDuration: userOptions.animations.durationSmall, - child: actionText, - }); - return Widget.Button({ - className: 'overview-search-result-btn', - onClicked: () => { - App.closeWindow('overview'); - app.launch(); - }, - child: Widget.Box({ - children: [ - Widget.Box({ - vertical: false, - children: [ - Widget.Box({ - className: 'overview-search-results-icon', - homogeneous: true, - child: Widget.Icon({ - icon: app.iconName, - }), - }), - Widget.Label({ - className: 'overview-search-results-txt txt txt-norm', - label: app.name, - }), - Widget.Box({ hexpand: true }), - actionTextRevealer, - ] - }) - ] - }), - setup: (self) => self - .on('focus-in-event', (button) => { - actionText.revealChild = true; - actionTextRevealer.revealChild = true; - }) - .on('focus-out-event', (button) => { - actionText.revealChild = false; - actionTextRevealer.revealChild = false; - }) - , - }) -} - -export const ExecuteCommandButton = ({ command, terminal = false }) => searchItem({ - materialIconName: `${terminal ? 'terminal' : ' '}`, - name: `Run command`, - actionName: `Execute ${terminal ? 'in terminal' : ''}`, - content: `${command}`, - onActivate: () => execAndClose(command, terminal), - extraClassName: 'techfont', -}) - -export const CustomCommandButton = ({ text = '' }) => searchItem({ - materialIconName: ' ', - name: 'Action', - actionName: 'Run', - content: `${text}`, - onActivate: () => { - App.closeWindow('overview'); - launchCustomCommand(text); - }, -}); - -export const SearchButton = ({ text = '' }) => searchItem({ - materialIconName: ' ', - name: 'Search the web', - actionName: 'Go', - content: `${text}`, - onActivate: () => { - App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open '${userOptions.search.engineBaseUrl}${text} ${['', ...userOptions.search.excludedSites].join(' -site:')}' &`]).catch(print); - }, -});
\ No newline at end of file diff --git a/config/ags/modules/overview/searchitem.js b/config/ags/modules/overview/searchitem.js deleted file mode 100644 index 2a3303a4..00000000 --- a/config/ags/modules/overview/searchitem.js +++ /dev/null @@ -1,65 +0,0 @@ -import Widget from 'resource:///com/github/Aylur/ags/widget.js'; - -export const searchItem = ({ materialIconName, name, actionName, content, onActivate, extraClassName = '', ...rest }) => { - const actionText = Widget.Revealer({ - revealChild: false, - transition: "crossfade", - transitionDuration: userOptions.animations.durationLarge, - child: Widget.Label({ - className: 'overview-search-results-txt txt txt-small txt-action', - label: `${actionName}`, - }) - }); - const actionTextRevealer = Widget.Revealer({ - revealChild: false, - transition: "slide_left", - transitionDuration: userOptions.animations.durationSmall, - child: actionText, - }) - return Widget.Button({ - className: `overview-search-result-btn txt ${extraClassName}`, - onClicked: onActivate, - child: Widget.Box({ - children: [ - Widget.Box({ - vertical: false, - children: [ - Widget.Label({ - className: `icon-material overview-search-results-icon`, - label: `${materialIconName}`, - }), - Widget.Box({ - vertical: true, - children: [ - Widget.Label({ - hpack: 'start', - className: 'overview-search-results-txt txt-smallie txt-subtext', - label: `${name}`, - truncate: "end", - }), - Widget.Label({ - hpack: 'start', - className: 'overview-search-results-txt txt-norm', - label: `${content}`, - truncate: "end", - }), - ] - }), - Widget.Box({ hexpand: true }), - actionTextRevealer, - ], - }) - ] - }), - setup: (self) => self - .on('focus-in-event', (button) => { - actionText.revealChild = true; - actionTextRevealer.revealChild = true; - }) - .on('focus-out-event', (button) => { - actionText.revealChild = false; - actionTextRevealer.revealChild = false; - }) - , - }); -} diff --git a/config/ags/modules/overview/windowcontent.js b/config/ags/modules/overview/windowcontent.js deleted file mode 100644 index 7a19dd3c..00000000 --- a/config/ags/modules/overview/windowcontent.js +++ /dev/null @@ -1,262 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import App from 'resource:///com/github/Aylur/ags/app.js'; -import Widget from 'resource:///com/github/Aylur/ags/widget.js'; -import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; - -import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; -const { execAsync, exec } = Utils; -import { execAndClose, expandTilde, hasUnterminatedBackslash, couldBeMath, launchCustomCommand, ls } from './miscfunctions.js'; -import { - CalculationResultButton, CustomCommandButton, DirectoryButton, - DesktopEntryButton, ExecuteCommandButton, SearchButton -} from './searchbuttons.js'; -import { checkKeybind } from '../.widgetutils/keybind.js'; - -// Add math funcs -const { abs, sin, cos, tan, cot, asin, acos, atan, acot } = Math; -const pi = Math.PI; -// trigonometric funcs for deg -const sind = x => sin(x * pi / 180); -const cosd = x => cos(x * pi / 180); -const tand = x => tan(x * pi / 180); -const cotd = x => cot(x * pi / 180); -const asind = x => asin(x) * 180 / pi; -const acosd = x => acos(x) * 180 / pi; -const atand = x => atan(x) * 180 / pi; -const acotd = x => acot(x) * 180 / pi; - -const MAX_RESULTS = 10; -const OVERVIEW_SCALE = 0.18; // = overview workspace box / screen size -const OVERVIEW_WS_NUM_SCALE = 0.0; -const OVERVIEW_WS_NUM_MARGIN_SCALE = 0.07; -const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; - -function iconExists(iconName) { - let iconTheme = Gtk.IconTheme.get_default(); - return iconTheme.has_icon(iconName); -} - -const OptionalOverview = async () => { - try { - return (await import('./overview_hyprland.js')).default(); - } catch { - return Widget.Box({}); - // return (await import('./overview_hyprland.js')).default(); - } -}; - -const overviewContent = await OptionalOverview(); - -export const SearchAndWindows = () => { - var _appSearchResults = []; - - const ClickToClose = ({ ...props }) => Widget.EventBox({ - ...props, - onPrimaryClick: () => App.closeWindow('overview'), - onSecondaryClick: () => App.closeWindow('overview'), - onMiddleClick: () => App.closeWindow('overview'), - }); - const resultsBox = Widget.Box({ - className: 'overview-search-results', - vertical: true, - vexpand: true, - }); - const resultsRevealer = Widget.Revealer({ - transitionDuration: userOptions.animations.durationLarge, - revealChild: false, - transition: 'slide_down', - // duration: 200, - hpack: 'center', - child: resultsBox, - }); - const entryPromptRevealer = Widget.Revealer({ - transition: 'crossfade', - transitionDuration: userOptions.animations.durationLarge, - revealChild: true, - hpack: 'center', - child: Widget.Label({ - className: 'overview-search-prompt txt-small txt', - label: 'Type to search' - }), - }); - - const entryIconRevealer = Widget.Revealer({ - transition: 'crossfade', - transitionDuration: userOptions.animations.durationLarge, - revealChild: false, - hpack: 'end', - child: Widget.Label({ - className: 'txt txt-large icon-material overview-search-icon', - label: ' ', - }), - }); - - const entryIcon = Widget.Box({ - className: 'overview-search-prompt-box', - setup: box => box.pack_start(entryIconRevealer, true, true, 0), - }); - - const entry = Widget.Entry({ - className: 'overview-search-box txt-small txt', - hpack: 'center', - onAccept: (self) => { // This is when you hit Enter - const text = self.text; - if (text.length == 0) return; - const isAction = text.startsWith('>'); - const isDir = (['/', '~'].includes(entry.text[0])); - - if (couldBeMath(text)) { // Eval on typing is dangerous, this is a workaround - try { - const fullResult = eval(text.replace(/\^/g, "**")); - // copy - execAsync(['wl-copy', `${fullResult}`]).catch(print); - App.closeWindow('overview'); - return; - } catch (e) { - // console.log(e); - } - } - if (isDir) { - App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open "${expandTilde(text)}"`, `&`]).catch(print); - return; - } - if (_appSearchResults.length > 0) { - App.closeWindow('overview'); - _appSearchResults[0].launch(); - return; - } - else if (text[0] == '>') { // Custom commands - App.closeWindow('overview'); - launchCustomCommand(text); - return; - } - // Fallback: Execute command - if (!isAction && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { - if (text.startsWith('sudo')) - execAndClose(text, true); - else - execAndClose(text, false); - } - - else { - App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open '${userOptions.search.engineBaseUrl}${text} ${['', ...userOptions.search.excludedSites].join(' -site:')}' &`]).catch(print); - } - }, - onChange: (entry) => { // this is when you type - const isAction = entry.text[0] == '>'; - const isDir = (['/', '~'].includes(entry.text[0])); - resultsBox.get_children().forEach(ch => ch.destroy()); - - // check empty if so then dont do stuff - if (entry.text == '') { - resultsRevealer.revealChild = false; - overviewContent.revealChild = true; - entryPromptRevealer.revealChild = true; - entryIconRevealer.revealChild = false; - entry.toggleClassName('overview-search-box-extended', false); - return; - } - const text = entry.text; - resultsRevealer.revealChild = true; - overviewContent.revealChild = false; - entryPromptRevealer.revealChild = false; - entryIconRevealer.revealChild = true; - entry.toggleClassName('overview-search-box-extended', true); - _appSearchResults = Applications.query(text); - - // Calculate - if (couldBeMath(text)) { // Eval on typing is dangerous; this is a small workaround. - try { - const fullResult = eval(text.replace(/\^/g, "**")); - resultsBox.add(CalculationResultButton({ result: fullResult, text: text })); - } catch (e) { - // console.log(e); - } - } - if (isDir) { - var contents = []; - contents = ls({ path: text, silent: true }); - contents.forEach((item) => { - resultsBox.add(DirectoryButton(item)); - }) - } - if (isAction) { // Eval on typing is dangerous, this is a workaround. - resultsBox.add(CustomCommandButton({ text: entry.text })); - } - // Add application entries - let appsToAdd = MAX_RESULTS; - _appSearchResults.forEach(app => { - if (appsToAdd == 0) return; - resultsBox.add(DesktopEntryButton(app)); - appsToAdd--; - }); - - // Fallbacks - // if the first word is an actual command - if (!isAction && !hasUnterminatedBackslash(text) && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { - resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') })); - } - - // Add fallback: search - resultsBox.add(SearchButton({ text: entry.text })); - resultsBox.show_all(); - }, - }); - return Widget.Box({ - vertical: true, - children: [ - ClickToClose({ // Top margin. Also works as a click-outside-to-close thing - child: Widget.Box({ - className: 'bar-height', - }) - }), - Widget.Box({ - hpack: 'center', - children: [ - entry, - Widget.Box({ - className: 'overview-search-icon-box', - setup: (box) => { - box.pack_start(entryPromptRevealer, true, true, 0) - }, - }), - entryIcon, - ] - }), - overviewContent, - resultsRevealer, - ], - setup: (self) => self - .hook(App, (_b, name, visible) => { - if (name == 'overview' && !visible) { - resultsBox.children = []; - entry.set_text(''); - } - }) - .on('key-press-event', (widget, event) => { // Typing - const keyval = event.get_keyval()[1]; - const modstate = event.get_state()[1]; - if (checkKeybind(event, userOptions.keybinds.overview.altMoveLeft)) - entry.set_position(Math.max(entry.get_position() - 1, 0)); - else if (checkKeybind(event, userOptions.keybinds.overview.altMoveRight)) - entry.set_position(Math.min(entry.get_position() + 1, entry.get_text().length)); - else if (checkKeybind(event, userOptions.keybinds.overview.deleteToEnd)) { - const text = entry.get_text(); - const pos = entry.get_position(); - const newText = text.slice(0, pos); - entry.set_text(newText); - entry.set_position(newText.length); - } - else if (!(modstate & Gdk.ModifierType.CONTROL_MASK)) { // Ctrl not held - if (keyval >= 32 && keyval <= 126 && widget != entry) { - Utils.timeout(1, () => entry.grab_focus()); - entry.set_text(entry.text + String.fromCharCode(keyval)); - entry.set_position(-1); - } - } - }) - , - }); -}; |
