Gerenciamento de janelas lado a lado para Windows.
komorebi é um gerenciador de janelas lado a lado que funciona como uma extensão do Desktop Window Manager da Microsoft no Windows 10 e superior.
komorebi permite controlar janelas de aplicativos, espaços de trabalho virtuais e monitores de exibição com uma CLI que pode ser usada com software de terceiros, como whkd
e AutoHotKey, para definir atalhos de teclado definidos pelo usuário.
komorebi pretende fazer o mínimo de modificações possível no sistema operacional e no ambiente de desktop por padrão. Os usuários são livres para fazer tais modificações em seus próprios arquivos de configuração do komorebi , mas eles permanecerão ativados e desativados por padrão no futuro próximo.
Consulte a documentação para obter instruções sobre como instalar e configurar komorebi , fluxos de trabalho comuns, uma referência completa do esquema de configuração e uma referência CLI completa.
Há um servidor Discord disponível para discussões relacionadas ao komorebi , ajuda, solução de problemas, etc. Se você tiver alguma solicitação de recurso específico ou bug para relatar, crie um problema neste repositório.
Existe um canal no YouTube onde posto vídeos de desenvolvimento do komorebi . Se você quiser ser avisado sobre os próximos vídeos, inscreva-se e ative as notificações.
Existe uma lista incrível que mostra os muitos projetos incríveis que existem no ecossistema komorebi .
komorebi é um projeto gratuito e disponível em fontes, que incentiva você a fazer doações de caridade se achar que o software é útil e tiver meios financeiros.
Encorajo você a fazer uma doação de caridade ao Fundo de Ajuda às Crianças da Palestina antes de considerar me patrocinar no GitHub.
GitHub Sponsors está habilitado para este projeto. Infelizmente não tenho nada específico para oferecer além da minha gratidão e agradecimentos no final dos vídeos e tutoriais de desenvolvimento ao vivo do komorebi .
Se você gostaria de dar gorjetas ou patrocinar o projeto, mas não consegue usar os patrocinadores do GitHub, você também pode patrocinar através do Ko-fi.
Está disponível um guia detalhado de instalação e início rápido que mostra como começar a usar scoop
, winget
ou a construção a partir do código-fonte.
O membro da comunidade Olge criou um excelente vídeo que compara os recursos padrão de gerenciamento de janelas do Windows 11, Fancy Zones e komorebi.
Se você não está familiarizado com gerenciadores de janelas lado a lado ou se está olhando para komorebi e se perguntando "como isso é diferente do Fancy Zones??", este pequeno vídeo responderá à maioria das suas perguntas.
@amnweb mostrando o komorebi v0.1.28
em execução no Windows 11 com bordas de janela, transparência de janela sem foco e animações habilitadas, usando uma barra de status personalizada integrada usando as assinaturas de eventos do gerenciador de janelas do komorebi .
@haxibami mostrando komorebi rodando no Windows 11 com um emulador de terminal, um navegador da web e um editor de código. O vídeo original pode ser visto aqui.
@aik2mlj mostrando o komorebi em execução no Windows 11 com vários espaços de trabalho, emuladores de terminal, um navegador da web e a barra de status do yasb com o widget do espaço de trabalho komorebi ativado. O vídeo original pode ser visto aqui.
Se você gostaria de contribuir para komorebi
reserve um tempo para ler atentamente as diretrizes abaixo.
use
cargo +stable clippy
e certifique-se de que todos os problemas e sugestões foram abordados antes de confirmarcargo +nightly fmt --all
para garantir uma formatação consistente antes de confirmargit cz
com a CLI do Commitizen para preparar mensagens de commitÉ muito difícil revisar solicitações pull que afetam vários recursos e partes não relacionadas da base de código.
Por favor, não envie solicitações pull como esta; você será solicitado a separá-los em PRs menores que tratam apenas de um recurso ou correção de bug por vez.
Se você estiver trabalhando em vários recursos e correções de bugs, sugiro que você corte uma ramificação chamada local-trunk
do master
, que você mantém atualizado, e rebase as várias ramificações independentes nas quais você está trabalhando nessa ramificação, se quiser testá-las. juntos ou crie uma construção com tudo integrado.
komorebi
é uma base de código madura com consistência e estrutura interna que se desenvolveu organicamente ao longo de quase meia década.
Há inúmeras horas de vídeos de codificação ao vivo demonstrando o trabalho neste projeto e mostrando aos novos colaboradores como fazer tudo, desde tarefas básicas, como implementar novos comandos komorebic
, até distinguir monitores por identificadores de hardware do fabricante e portas de placa de vídeo.
Refatorar a estrutura da base de código não é considerado levianamente e requer discussão e aprovação prévias.
Por favor, não comece a refatorar a base de código com a expectativa de ter suas alterações integradas até receber uma aprovação explícita ou uma solicitação para fazê-lo.
Da mesma forma, ao implementar recursos e correções de bugs, siga a estrutura da base de código tanto quanto possível e não aproveite isso como uma oportunidade para fazer alguma "refatoração ao longo do caminho".
É extremamente difícil revisar PRs em busca de recursos e correções de bugs se eles forem perdidos em mudanças radicais na estrutura da base de código.
Isso inclui, mas não está limitado a:
komorebic
komorebi.json
komorebi-application-specific-configuration
Nenhum usuário deve descobrir que seu arquivo de configuração parou de funcionar após atualizar para uma nova versão do komorebi
.
Na maioria das vezes, existem maneiras de reformular mudanças que inicialmente podem parecer exigir a divisão das interfaces voltadas ao usuário em mudanças aditivas.
Para se inspirar, dê uma olhada neste commit que adicionou a capacidade dos usuários de especificar cores em komorebi.json
no formato Hex junto com RGB.
Também existe um processo em vigor para descontinuação elegante e ininterrupta de opções de configuração que não são mais necessárias.
komorebi
é licenciado sob a licença Komorebi 1.0.0, que é uma bifurcação da licença PolyForm Strict 1.0.0. Em um nível elevado, isso significa que você é livre para fazer o que quiser com komorebi
para uso pessoal, exceto redistribuição ou distribuição de novos trabalhos (ou seja, hard-forks) baseados no software.
Qualquer um é livre para criar seu próprio fork do komorebi
com alterações destinadas ao uso pessoal ou à integração de volta ao upstream por meio de solicitações pull.
A Licença Komorebi 1.0.0 não permite qualquer tipo de uso comercial.
Uma licença dedicada e um EULA serão introduzidos em 2025 para organizações comerciais e não comerciais.
Consulte CONTRIBUTING.md para obter mais informações sobre como as contribuições de código para komorebi
são licenciadas.
Se você usar o IntelliJ, deverá habilitar as seguintes configurações para garantir que o código gerado pelas macros seja reconhecido pelo IDE para conclusões e navegação:
Expand declarative macros
para Use new engine
em "Configurações > Idiomas e Estruturas > Rust"org.rust.cargo.evaluate.build.scripts
org.rust.macros.proc
Os logs de komorebi
serão anexados a %LOCALAPPDATA%/komorebi/komorebi.log
; esse arquivo nunca é girado ou substituído, portanto continuará crescendo até ser excluído pelo usuário.
Sempre que executar o comando komorebic stop
ou enviar um sinal Ctrl-C diretamente para komorebi
, o processo komorebi
garante que todas as janelas ocultas sejam restauradas antes do encerramento.
Se, no entanto, você acabar com janelas ocultas e que não podem ser restauradas, uma lista de identificadores de janelas conhecidos por komorebi
será armazenada e atualizada continuamente em %LOCALAPPDATA%/komorebi//komorebi.hwnd.json
.
A execução komorebic restore-windows
lerá a lista de identificadores de janela e os restaurará à força, independentemente de o processo principal komorebi
estar em execução.
Se komorebi
parar de responder, provavelmente será devido a um pânico ou a um impasse. Em caso de pânico, isso será informado no log. No caso de um impasse, não haverá erros no log, mas o processo e o log aparecerão congelados.
Se você acredita ter encontrado um impasse, você pode compilar komorebi
com --features deadlock_detection
e tentar reproduzir o impasse novamente. Isso verificará a existência de deadlocks a cada 5 segundos em segundo plano e, se um deadlock for encontrado, informações sobre ele aparecerão no log que pode ser compartilhado ao abrir um problema.
O estado atual do gerenciador de janelas pode ser consultado usando o comando komorebic state
, que retorna uma representação JSON da estrutura State
.
Isso também pode ser pesquisado para construir integrações e widgets adicionais.
É possível assinar notificações de cada WindowManagerEvent
e SocketMessage
manipulado por komorebi
usando Named Pipes.
Primeiro, seu aplicativo deve criar um pipe nomeado. Depois que o pipe nomeado for criado, execute o seguinte comando:
komorebic.exe subscribe - pipe < your pipe name >
Observe que você não precisa incluir o caminho completo do pipe nomeado, apenas o nome.
Se o pipe nomeado existir, komorebi
começará a enviar dados JSON de eventos e mensagens manipulados com sucesso:
{ "event" :{ "type" : " AddSubscriber " , "content" : " yasb " }, "state" :{}}
{ "event" :{ "type" : " FocusWindow " , "content" : " Left " }, "state" :{}}
{ "event" :{ "type" : " FocusChange " , "content" :[ " SystemForeground " ,{ "hwnd" : 131444 , "title" : " komorebi – README.md " , "exe" : " idea64.exe " , "class" : " SunAwtFrame " , "rect" :{ "left" : 13 , "top" : 60 , "right" : 1520 , "bottom" : 1655 }}]}, "state" :{}}
{ "event" :{ "type" : " MonitorPoll " , "content" :[ " ObjectCreate " ,{ "hwnd" : 5572450 , "title" : " OLEChannelWnd " , "exe" : " explorer.exe " , "class" : " OleMainThreadWndClass " , "rect" :{ "left" : 0 , "top" : 0 , "right" : 0 , "bottom" : 0 }}]}, "state" :{}}
{ "event" :{ "type" : " FocusWindow " , "content" : " Right " }, "state" :{}}
{ "event" :{ "type" : " FocusChange " , "content" :[ " SystemForeground " ,{ "hwnd" : 132968 , "title" : " Windows PowerShell " , "exe" : " WindowsTerminal.exe " , "class" : " CASCADIA_HOSTING_WINDOW_CLASS " , "rect" :{ "left" : 1539 , "top" : 60 , "right" : 1520 , "bottom" : 821 }}]}, "state" :{}}
{ "event" :{ "type" : " FocusWindow " , "content" : " Down " }, "state" :{}}
{ "event" :{ "type" : " FocusChange " , "content" :[ " SystemForeground " ,{ "hwnd" : 329264 , "title" : " den — Mozilla Firefox " , "exe" : " firefox.exe " , "class" : " MozillaWindowClass " , "rect" :{ "left" : 1539 , "top" : 894 , "right" : 1520 , "bottom" : 821 }}]}, "state" :{}}
{ "event" :{ "type" : " FocusWindow " , "content" : " Up " }, "state" :{}}
{ "event" :{ "type" : " FocusChange " , "content" :[ " SystemForeground " ,{ "hwnd" : 132968 , "title" : " Windows PowerShell " , "exe" : " WindowsTerminal.exe " , "class" : " CASCADIA_HOSTING_WINDOW_CLASS " , "rect" :{ "left" : 1539 , "top" : 60 , "right" : 1520 , "bottom" : 821 }}]}, "state" :{}}
Você pode então filtrar a chave type
para ouvir os eventos de seu interesse. Para obter uma lista completa de possíveis tipos de notificação, consulte as variantes enum de WindowManagerEvent
em komorebi
e SocketMessage
em komorebi::core
.
Abaixo está um exemplo de como você pode assinar e filtrar eventos usando um pipe nomeado em nodejs
.
const { exec } = require ( "child_process" ) ;
const net = require ( "net" ) ;
const pipeName = "\\.\pipe\komorebi-js" ;
const server = net . createServer ( ( stream ) => {
console . log ( "Client connected" ) ;
// Every time there is a workspace-related event, let's log the names of all
// workspaces on the currently focused monitor, and then log the name of the
// currently focused workspace on that monitor
stream . on ( "data" , ( data ) => {
let json = JSON . parse ( data . toString ( ) ) ;
let event = json . event ;
if ( event . type . includes ( "Workspace" ) ) {
let monitors = json . state . monitors ;
let current_monitor = monitors . elements [ monitors . focused ] ;
let workspaces = monitors . elements [ monitors . focused ] . workspaces ;
let current_workspace = workspaces . elements [ workspaces . focused ] ;
console . log (
workspaces . elements
. map ( ( workspace ) => workspace . name )
. filter ( ( name ) => name !== null )
) ;
console . log ( current_workspace . name ) ;
}
} ) ;
stream . on ( "end" , ( ) => {
console . log ( "Client disconnected" ) ;
} ) ;
} ) ;
server . listen ( pipeName , ( ) => {
console . log ( "Named pipe server listening" ) ;
} ) ;
const command = "komorebic subscribe-pipe komorebi-js" ;
exec ( command , ( error , stdout , stderr ) => {
if ( error ) {
console . error ( `Error executing command: ${ error } ` ) ;
return ;
}
} ) ;
É possível assinar notificações de cada WindowManagerEvent
e SocketMessage
manipulado por komorebi
usando Unix Domain Sockets.
UDS também são o único modo de comunicação entre komorebi
e komorebic
.
Primeiro, seu aplicativo deve criar um soquete em $ENV:LocalAppDatakomorebi
. Depois que o soquete for criado, execute o seguinte comando:
komorebic.exe subscribe - socket < your socket name >
Se o soquete existir, komorebi começará a enviar dados JSON de eventos e mensagens manipulados com sucesso, como no exemplo acima na seção Named Pipes.
A partir da v0.1.22
é possível usar a caixa komorebi-client
para assinar notificações de cada WindowManagerEvent
e SocketMessage
manipulado por komorebi
em uma base de código Rust.
Abaixo está um exemplo simples de como usar komorebi-client
em um aplicativo Rust básico.
// komorebi-client = { git = "https://github.com/LGUG2Z/komorebi", tag = "v0.1.30"}
use anyhow :: Result ;
use komorebi_client :: Notification ;
use komorebi_client :: NotificationEvent ;
use komorebi_client :: UnixListener ;
use komorebi_client :: WindowManagerEvent ;
use std :: io :: BufRead ;
use std :: io :: BufReader ;
use std :: io :: Read ;
pub fn main ( ) -> anyhow :: Result < ( ) > {
let socket = komorebi_client :: subscribe ( NAME ) ? ;
for incoming in socket . incoming ( ) {
match incoming {
Ok ( data ) => {
let reader = BufReader :: new ( data . try_clone ( ) ? ) ;
for line in reader . lines ( ) . flatten ( ) {
let notification : Notification = match serde_json :: from_str ( & line ) {
Ok ( notification ) => notification ,
Err ( error ) => {
log :: debug! ( "discarding malformed komorebi notification: {error}" ) ;
continue ;
}
} ;
// match and filter on desired notifications
}
}
Err ( error ) => {
log :: debug! ( "{error}" ) ;
}
}
}
}
Um exemplo de mundo lido pode ser encontrado em komokana.
Um esquema JSON das notificações de eventos emitidas para assinantes pode ser gerado com o comando komorebic notification-schema
. A saída deste comando pode ser redirecionada para a área de transferência ou para um arquivo, que pode ser usado com serviços como Quicktype para gerar definições de tipo em diferentes linguagens de programação.
Um ouvinte TCP pode opcionalmente ser exposto em uma porta de sua escolha com o sinalizador --tcp-port=N
. Se este sinalizador não for fornecido para komorebi
ou komorebic start
, nenhum ouvinte TCP será criado.
Uma vez criado, seu cliente pode enviar qualquer SocketMessage para komorebi
da mesma forma que komorebic
faria.
Isso pode ser usado se você quiser criar sua própria alternativa ao komorebic
, que incorpora scripts e várias camadas de middleware, e da mesma forma, pode ser usado se você quiser integrar komorebi
com um manipulador de entrada personalizado.
Se um cliente enviar uma mensagem não reconhecida, ele será desconectado e deverá se reconectar antes de tentar se comunicar novamente.
Um esquema JSON de mensagens de soquete usadas para enviar instruções para komorebi
pode ser gerado com o comando komorebic socket-schema
. A saída deste comando pode ser redirecionada para a área de transferência ou para um arquivo, que pode ser usado com serviços como Quicktype para gerar definições de tipo em diferentes linguagens de programação.
Em primeiro lugar, obrigado à minha esposa, tanto por dar nome a este projeto como pela sua paciência ao longo do seu desenvolvimento sem fim.
Obrigado ao @sitiom por ser um líder exemplar da comunidade de código aberto
Obrigado aos desenvolvedores do nog que vieram antes de mim e cujo trabalho me ensinou mais do que posso esperar retribuir
Obrigado aos desenvolvedores do GlazeWM por ultrapassarem os limites do gerenciamento de janelas lado a lado no Windows comigo e por terem um excelente espírito de colaboração
Obrigado a @Ciantic por me ajudar a trazer a função oculta de camuflagem de desktops virtuais para komorebi