Skip to content

Commit

Permalink
feat: implement transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-berger committed Feb 28, 2024
1 parent 9fd6fe2 commit 6258131
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { createProviderListener } from '../create-provider-listener';
import { getMonitors } from '~/desktop';
import { getCoordinateDistance } from '~/utils';

interface KomorebiResponse {
allMonitors: KomorebiMonitor[];
focusedMonitorIndex: number;
}

export interface KomorebiProvider {
/**
* Workspace displayed on the current monitor.
Expand All @@ -30,7 +35,7 @@ export interface KomorebiProvider {
/**
* All monitors.
*/
monitors: KomorebiMonitor[];
allMonitors: KomorebiMonitor[];

/**
* Monitor that currently has focus.
Expand All @@ -45,26 +50,27 @@ export interface KomorebiProvider {

export interface KomorebiMonitor {
id: number;
name: string;
deviceId: string;
focusedWorkspaceIndex: number;
name: string;
size: KomorebiRect;
workAreaOffset: number | null;
workAreaSize: KomorebiRect;
workspaces: KomorebiWorkspace[];
}

export interface KomorebiWorkspace {
containerPadding: number;
containerPadding: number | null;
floatingWindows: KomorebiWindow[];
focusedContainerIndex: number;
latestLayout: KomorebiRect[];
layout: KomorebiLayout;
layoutFlip: KomorebiLayoutFlip | null;
name: string;
maximizedWindow: KomorebiWindow | null;
monocleContainer: KomorebiContainer | null;
name: string | null;
tilingContainers: KomorebiContainer[];
workspacePadding: number;
workspacePadding: number | null;
}

export interface KomorebiContainer {
Expand All @@ -73,11 +79,10 @@ export interface KomorebiContainer {
}

export interface KomorebiWindow {
class: string;
exe: string;
class: string | null;
exe: string | null;
hwnd: number;
size: KomorebiRect;
title: string;
title: string | null;
}

export interface KomorebiRect {
Expand All @@ -92,9 +97,14 @@ export type KomorebiLayout =
| 'vertical_stack'
| 'horizontal_stack'
| 'ultrawide_vertical_stack'
| 'rows';
| 'rows'
| 'grid'
| 'custom';

export type KomorebiLayoutFlip = 'horizontal' | 'vertical';
export type KomorebiLayoutFlip =
| 'horizontal'
| 'vertical'
| 'horizontal_and_vertical';

export async function createKomorebiProvider(
config: KomorebiProviderConfig,
Expand All @@ -104,7 +114,7 @@ export async function createKomorebiProvider(

const providerListener = await createProviderListener<
KomorebiProviderConfig,
KomorebiProvider
KomorebiResponse
>(config, owner);

const [komorebiVariables, setKomorebiVariables] = createStore(
Expand All @@ -118,7 +128,7 @@ export async function createKomorebiProvider(
const currentPosition = { x: currentMonitor!.x, y: currentMonitor!.y };

// Get Komorebi monitor that corresponds to the window's monitor.
const currentKomorebiMonitor = state.monitors.reduce((a, b) =>
const currentKomorebiMonitor = state.allMonitors.reduce((a, b) =>
getCoordinateDistance(currentPosition, {
x: a.workAreaSize.left,
y: a.workAreaSize.top,
Expand All @@ -136,14 +146,22 @@ export async function createKomorebiProvider(
currentKomorebiMonitor.focusedWorkspaceIndex
]!;

const allWorkspaces = state.allMonitors.flatMap(
monitor => monitor.workspaces,
);

const focusedMonitor = state.allMonitors[state.focusedMonitorIndex]!;
const focusedWorkspace =
focusedMonitor.workspaces[focusedMonitor.focusedWorkspaceIndex]!;

return {
displayedWorkspace,
focusedWorkspace: state.focusedWorkspace,
focusedWorkspace,
currentWorkspaces: currentKomorebiMonitor.workspaces,
allWorkspaces: state.allWorkspaces,
monitors: state.monitors,
focusedMonitor: state.focusedMonitor,
allWorkspaces,
focusedMonitor,
currentMonitor: currentKomorebiMonitor,
allMonitors: state.allMonitors,
};
}

Expand All @@ -160,8 +178,8 @@ export async function createKomorebiProvider(
get allWorkspaces() {
return komorebiVariables.allWorkspaces;
},
get monitors() {
return komorebiVariables.monitors;
get allMonitors() {
return komorebiVariables.allMonitors;
},
get focusedMonitor() {
return komorebiVariables.focusedMonitor;
Expand Down
103 changes: 81 additions & 22 deletions packages/desktop/src/providers/komorebi/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use async_trait::async_trait;
use komorebi_client::Monitor;
use komorebi_client::{Container, Monitor, Window, Workspace};
use tokio::{
sync::mpsc::Sender,
task::{self, AbortHandle},
Expand All @@ -18,7 +18,10 @@ use crate::providers::{
variables::ProviderVariables,
};

use super::{KomorebiMonitor, KomorebiProviderConfig};
use super::{
KomorebiContainer, KomorebiLayout, KomorebiLayoutFlip, KomorebiMonitor,
KomorebiProviderConfig, KomorebiWindow, KomorebiWorkspace,
};

const SOCKET_NAME: &str = "zebar.sock";

Expand All @@ -38,28 +41,83 @@ impl KomorebiProvider {
fn transform_response(
state: komorebi_client::State,
) -> KomorebiVariables {
let monitors = state
let all_monitors = state
.monitors
.elements()
.into_iter()
.map(|&monitor| KomorebiMonitor {
id: monitor.id(),
name: monitor.name().to_string(),
device_id: monitor.device_id().clone(),
size: monitor.size(),
work_area_size: KomorebiRect {
left: size.left,
top: size.top,
right: size.right,
bottom: size.bottom,
},
work_area_offset: monitor.work_area_offset(),
work_area_size: monitor.work_area_size(),
workspaces: monitor.workspaces(),
})
.map(Self::transform_monitor)
.collect();

KomorebiVariables { monitors }
KomorebiVariables {
all_monitors,
focused_monitor_index: state.monitors.focused_idx(),
}
}

fn transform_monitor(monitor: &Monitor) -> KomorebiMonitor {
KomorebiMonitor {
id: monitor.id(),
name: monitor.name().to_string(),
device_id: monitor.device_id().clone(),
focused_workspace_index: monitor.focused_workspace_idx(),
size: *monitor.size(),
work_area_size: *monitor.work_area_size(),
work_area_offset: monitor.work_area_offset(),
workspaces: monitor
.workspaces()
.into_iter()
.map(Self::transform_workspace)
.collect(),
}
}

fn transform_workspace(workspace: &Workspace) -> KomorebiWorkspace {
KomorebiWorkspace {
container_padding: workspace.container_padding(),
floating_windows: workspace
.floating_windows()
.into_iter()
.map(Self::transform_window)
.collect(),
focused_container_index: workspace.focused_container_idx(),
latest_layout: (*workspace.latest_layout()).clone(),
layout: KomorebiLayout::from((*workspace.layout()).clone()),
layout_flip: workspace.layout_flip().map(KomorebiLayoutFlip::from),
name: workspace.name().clone(),
maximized_window: workspace
.maximized_window()
.map(|w| Self::transform_window(&w)),
monocle_container: workspace
.monocle_container()
.as_ref()
.map(|c| Self::transform_container(&c)),
tiling_containers: workspace
.containers()
.into_iter()
.map(Self::transform_container)
.collect(),
workspace_padding: workspace.workspace_padding(),
}
}

fn transform_container(container: &Container) -> KomorebiContainer {
KomorebiContainer {
id: container.id().to_string(),
windows: container
.windows()
.iter()
.map(Self::transform_window)
.collect(),
}
}

fn transform_window(window: &Window) -> KomorebiWindow {
KomorebiWindow {
class: window.class().ok(),
exe: window.exe().ok(),
hwnd: window.hwnd().0 as u64,
title: window.title().ok(),
}
}
}

Expand All @@ -85,13 +143,14 @@ impl Provider for KomorebiProvider {
let notification: komorebi_client::Notification =
serde_json::from_str(&line).unwrap();

// Transform and emit the incoming Komorebi state.
_ = emit_output_tx
.send(ProviderOutput {
config_hash: config_hash.clone(),
variables: VariablesResult::Data(
ProviderVariables::Komorebi(KomorebiVariables {
monitors: notification.state.monitors,
}),
ProviderVariables::Komorebi(Self::transform_response(
notification.state,
)),
),
})
.await;
Expand Down
Loading

0 comments on commit 6258131

Please sign in to comment.