การจัดการหน้าต่างการปูกระเบื้องสำหรับ Windows
komorebi เป็นตัวจัดการหน้าต่างแบบเรียงต่อกันที่ทำงานเป็นส่วนเสริมของ Desktop Window Manager ของ Microsoft ใน Windows 10 ขึ้นไป
komorebi ช่วยให้คุณควบคุมหน้าต่างแอปพลิเคชัน พื้นที่ทำงานเสมือน และจอภาพด้วย CLI ซึ่งสามารถใช้กับซอฟต์แวร์บุคคลที่สาม เช่น whkd
และ AutoHotKey เพื่อตั้งค่าแป้นพิมพ์ลัดที่ผู้ใช้กำหนด
komorebi มีเป้าหมายที่จะทำการ ปรับเปลี่ยนระบบปฏิบัติการและสภาพแวดล้อมเดสก์ท็อปให้น้อยที่สุดเท่าที่จะเป็นไปได้ ตามค่าเริ่มต้น ผู้ใช้มีอิสระที่จะทำการแก้ไขดังกล่าวในไฟล์การกำหนดค่าของตนเองสำหรับ komorebi แต่สิ่งเหล่านี้จะยังคงเลือกรับและปิดโดยค่าเริ่มต้นในอนาคตอันใกล้
โปรดดูเอกสารประกอบสำหรับคำแนะนำเกี่ยวกับวิธีการติดตั้งและกำหนดค่า komorebi เวิร์กโฟลว์ทั่วไป การอ้างอิงสกีมาการกำหนดค่าที่สมบูรณ์ และการอ้างอิง CLI ที่สมบูรณ์
มีเซิร์ฟเวอร์ Discord สำหรับการสนทนาที่เกี่ยวข้องกับ komorebi ความช่วยเหลือ การแก้ไขปัญหา ฯลฯ หากคุณมีคำขอคุณลักษณะเฉพาะหรือข้อบกพร่องที่จะรายงาน โปรดสร้างปัญหาในพื้นที่เก็บข้อมูลนี้
มีช่อง YouTube ที่ผมลงวีดีโอการพัฒนา komorebi หากคุณต้องการรับการแจ้งเตือนเกี่ยวกับวิดีโอที่กำลังจะมาถึง โปรดติดตามและเปิดการแจ้งเตือน
มีรายการที่ยอดเยี่ยมซึ่งนำเสนอโครงการที่ยอดเยี่ยมมากมายที่มีอยู่ในระบบนิเวศ ของโคโมเรบี
komorebi เป็นโครงการฟรีที่มีแหล่งที่มา และเป็นโครงการที่สนับสนุนให้คุณบริจาคเงินเพื่อการกุศลหากคุณพบว่าซอฟต์แวร์มีประโยชน์และมีฐานะทางการเงิน
ฉันขอแนะนำให้คุณบริจาคเงินเพื่อการกุศลให้กับ Palestine Children's Relief Fund ก่อนที่จะพิจารณาสนับสนุนฉันบน GitHub
เปิดใช้งานผู้สนับสนุน GitHub สำหรับโปรเจ็กต์นี้แล้ว น่าเสียดายที่ฉันไม่มีอะไรพิเศษที่จะนำเสนอนอกจากความกตัญญูและการกล่าวถึงในตอนท้ายของวิดีโอและบทช่วยสอนการพัฒนาสด ของ komorebi
หากคุณต้องการให้ทิปหรือสนับสนุนโครงการ แต่ไม่สามารถใช้ผู้สนับสนุน GitHub ได้ คุณสามารถสนับสนุนผ่าน Ko-fi ได้เช่นกัน
มีคู่มือการติดตั้งโดยละเอียดและคู่มือการเริ่มต้นฉบับย่อซึ่งแสดงวิธีเริ่มต้นใช้งาน scoop
, winget
หรือการสร้างจากแหล่งที่มา
Olge สมาชิกชุมชนได้สร้างวิดีโอที่ยอดเยี่ยมซึ่งเปรียบเทียบคุณสมบัติการจัดการหน้าต่างเริ่มต้นของ Windows 11, Fancy Zones และ komorebi
หากคุณไม่คุ้นเคยกับตัวจัดการหน้าต่างแบบเรียงต่อกัน หรือหากคุณกำลังมองหา komorebi และสงสัยว่า "สิ่งนี้แตกต่างจาก Fancy Zones อย่างไร ?" วิดีโอสั้น ๆ นี้จะตอบคำถามส่วนใหญ่ของคุณ
@amnweb แสดง komorebi v0.1.28
ที่ทำงานบน Windows 11 พร้อมขอบหน้าต่าง ความโปร่งใสของหน้าต่างที่ไม่ได้โฟกัส และเปิดใช้งานภาพเคลื่อนไหว โดยใช้แถบสถานะที่กำหนดเองซึ่งรวมเข้ากับการสมัครสมาชิกกิจกรรม Window Manager ของ komorebi
@haxibami แสดง komorebi ที่ทำงานบน Windows 11 พร้อมด้วยเทอร์มินัลอีมูเลเตอร์ เว็บเบราว์เซอร์ และโปรแกรมแก้ไขโค้ด สามารถดูวิดีโอต้นฉบับได้ที่นี่
@aik2mlj แสดง komorebi ที่ทำงานบน Windows 11 พร้อมพื้นที่ทำงานหลายพื้นที่ โปรแกรมจำลองเทอร์มินัล เว็บเบราว์เซอร์ และแถบสถานะ yasb พร้อมเปิดใช้งานวิดเจ็ตพื้นที่ทำงาน komorebi สามารถดูวิดีโอต้นฉบับได้ที่นี่
หากคุณต้องการสนับสนุน komorebi
โปรดสละเวลาอ่านหลักเกณฑ์ด้านล่างอย่างละเอียด
use
ทั้งหมดcargo +stable clippy
และตรวจสอบให้แน่ใจว่า Linint และข้อเสนอแนะทั้งหมดได้รับการแก้ไขก่อนดำเนินการcargo +nightly fmt --all
เพื่อให้แน่ใจว่ามีการจัดรูปแบบที่สอดคล้องกันก่อนดำเนินการgit cz
กับ Commitizen CLI เพื่อเตรียมข้อความคอมมิตเป็นเรื่องยากมากที่จะตรวจสอบคำขอดึงซึ่งสัมผัสคุณสมบัติที่ไม่เกี่ยวข้องหลายอย่างและบางส่วนของโค้ดเบส
กรุณาอย่าส่งคำขอดึงเช่นนี้ คุณจะถูกขอให้แยกพวกเขาออกเป็น PR ขนาดเล็กที่จัดการเฉพาะกับฟีเจอร์เดียวหรือการแก้ไขข้อบกพร่องในแต่ละครั้ง
หากคุณกำลังทำงานกับคุณสมบัติหลายอย่างและการแก้ไขข้อบกพร่อง ฉันขอแนะนำให้คุณตัดสาขาที่เรียกว่า local-trunk
จาก master
ที่คุณคอยอัปเดตอยู่เสมอ และรีบูตสาขาอิสระต่างๆ ที่คุณกำลังดำเนินการไปยังสาขานั้นหากคุณต้องการทดสอบ ร่วมกันหรือสร้างงานสร้างโดยรวมทุกอย่างเข้าด้วยกัน
komorebi
เป็น codebase ที่เติบโตเต็มที่โดยมีความสอดคล้องภายในและโครงสร้างที่พัฒนาขึ้นแบบออร์แกนิกมาเกือบครึ่งทศวรรษ
มีวิดีโอการเขียนโค้ดสดจำนวนนับไม่ถ้วนที่สาธิตการทำงานในโครงการนี้ และแสดงให้ผู้ร่วมให้ข้อมูลรายใหม่ทราบถึงวิธีทำทุกอย่างตั้งแต่งานพื้นฐาน เช่น การใช้คำสั่ง komorebic
ใหม่ ไปจนถึงการแยกจอภาพตามตัวระบุฮาร์ดแวร์ของผู้ผลิตและพอร์ตการ์ดแสดงผล
การรีแฟกเตอร์ให้กับโครงสร้างของโค้ดเบสนั้นไม่ได้ดำเนินการอย่างง่ายๆ และต้องมีการหารือและการอนุมัติล่วงหน้า
โปรดอย่าเริ่มปรับโครงสร้างโค้ดเบสใหม่โดยคาดหวังว่าจะรวมการเปลี่ยนแปลงของคุณเข้าด้วยกันจนกว่าคุณจะได้รับการอนุมัติอย่างชัดเจนหรือได้รับคำขอให้ดำเนินการดังกล่าว
ในทำนองเดียวกัน เมื่อใช้ฟีเจอร์และการแก้ไขข้อบกพร่อง โปรดยึดโครงสร้างของโค้ดเบสให้มากที่สุดเท่าที่จะเป็นไปได้ และอย่าใช้สิ่งนี้เป็นโอกาสในการ "ปรับโครงสร้างใหม่ไปพร้อมกัน"
เป็นเรื่องยากมากที่จะตรวจสอบ PR สำหรับฟีเจอร์และการแก้ไขข้อบกพร่อง หากหายไปจากการเปลี่ยนแปลงโครงสร้างของโค้ดเบสอย่างกว้างขวาง
ซึ่งรวมถึงแต่ไม่จำกัดเฉพาะ:
komorebic
ทั้งหมดkomorebi.json
komorebi-application-specific-configuration
ผู้ใช้ไม่ควรพบว่าไฟล์การกำหนดค่าของตนหยุดทำงานหลังจากอัปเกรดเป็น komorebi
เวอร์ชันใหม่
บ่อยครั้งมีวิธีจัดรูปแบบการเปลี่ยนแปลงที่อาจดูเหมือนต้องแยกส่วนต่อประสานกับผู้ใช้ออกเป็นการเปลี่ยนแปลงเพิ่มเติม
สำหรับแรงบันดาลใจ โปรดดูที่คอมมิตนี้ซึ่งเพิ่มความสามารถสำหรับผู้ใช้ในการระบุสีใน komorebi.json
ในรูปแบบ Hex ควบคู่ไปกับ RGB
นอกจากนี้ยังมีกระบวนการสำหรับการเลิกใช้ตัวเลือกการกำหนดค่าที่สง่างาม ไม่เสียหาย และไม่จำเป็นอีกต่อไป
komorebi
ได้รับอนุญาตภายใต้ใบอนุญาต Komorebi 1.0.0 ซึ่งเป็นทางแยกของใบอนุญาต PolyForm Strict 1.0.0 ในระดับสูง นี่หมายความว่าคุณมีอิสระที่จะทำสิ่งที่คุณต้องการด้วย komorebi
เพื่อการใช้งานส่วนตัว นอกเหนือจากการแจกจ่ายซ้ำ หรือการแจกจ่ายผลงานใหม่ (เช่น ฮาร์ดฟอร์ก) โดยใช้ซอฟต์แวร์
ทุกคนมีอิสระที่จะสร้างส้อม komorebi
ของตนเองโดยมีการเปลี่ยนแปลงที่มีจุดประสงค์เพื่อใช้ส่วนตัวหรือเพื่อบูรณาการกลับต้นน้ำผ่านการร้องขอแบบดึง
ใบอนุญาต Komorebi 1.0.0 ไม่อนุญาตให้นำไปใช้ในเชิงพาณิชย์ทุกประเภท
ใบอนุญาตเฉพาะและ EULA จะเปิดตัวในปี 2568 สำหรับทั้งองค์กรเชิงพาณิชย์และไม่ใช่เชิงพาณิชย์
โปรดดูที่ CONTRIBUTING.md สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการอนุญาตให้ใช้สิทธิ์ในการเขียนโค้ดให้กับ komorebi
หากคุณใช้ IntelliJ คุณควรเปิดใช้งานการตั้งค่าต่อไปนี้เพื่อให้แน่ใจว่าโค้ดที่สร้างโดยมาโครได้รับการยอมรับโดย IDE เพื่อความสมบูรณ์และการนำทาง:
Expand declarative macros
เพื่อ Use new engine
ภายใต้ "การตั้งค่า > ภาษาและกรอบงาน > สนิม"org.rust.cargo.evaluate.build.scripts
org.rust.macros.proc
บันทึกจาก komorebi
จะถูกผนวกเข้ากับ %LOCALAPPDATA%/komorebi/komorebi.log
; ไฟล์นี้จะไม่ถูกหมุนหรือเขียนทับ ดังนั้นไฟล์จะขยายใหญ่ขึ้นเรื่อยๆ จนกว่าผู้ใช้จะถูกลบออก
เมื่อใดก็ตามที่รันคำสั่ง komorebic stop
หรือส่งสัญญาณ Ctrl-C ไปยัง komorebi
โดยตรง กระบวนการ komorebi
จะทำให้แน่ใจว่าหน้าต่างที่ซ่อนไว้ทั้งหมดจะถูกกู้คืนก่อนที่จะยุติ
อย่างไรก็ตาม หากคุณพบว่าหน้าต่างถูกซ่อนไว้และไม่สามารถกู้คืนได้ รายการตัวจัดการหน้าต่างที่ komorebi
รู้จักจะถูกจัดเก็บและอัปเดตอย่างต่อเนื่องใน %LOCALAPPDATA%/komorebi//komorebi.hwnd.json
การเรียกใช้ komorebic restore-windows
จะอ่านรายการตัวจัดการหน้าต่างและบังคับให้กู้คืนหน้าต่างเหล่านั้น โดยไม่คำนึงว่ากระบวนการหลัก komorebi
กำลังทำงานอยู่หรือไม่
หาก komorebi
หยุดตอบสนอง อาจเป็นเพราะความตื่นตระหนกหรือการชะงักงัน ในกรณีที่เกิดความตื่นตระหนก สิ่งนี้จะถูกรายงานในบันทึก ในกรณีที่เกิดการชะงักงัน จะไม่มีข้อผิดพลาดใดๆ ในบันทึก แต่กระบวนการและบันทึกจะปรากฏค้าง
หากคุณเชื่อว่าคุณประสบปัญหาการหยุดชะงัก คุณสามารถคอมไพล์ komorebi
ด้วย --features deadlock_detection
และลองสร้างการหยุดชะงักอีกครั้ง วิธีนี้จะตรวจสอบการหยุดชะงักทุกๆ 5 วินาทีในเบื้องหลัง และหากพบการหยุดชะงัก ข้อมูลเกี่ยวกับการหยุดชะงักดังกล่าวจะปรากฏในบันทึกซึ่งสามารถแชร์ได้เมื่อเปิดปัญหา
สามารถสอบถามสถานะปัจจุบันของตัวจัดการหน้าต่างได้โดยใช้คำสั่ง komorebic state
ซึ่งจะส่งคืนการแสดง JSON ของโครงสร้าง State
สิ่งนี้อาจถูกสำรวจเพื่อสร้างการผสานรวมและวิดเจ็ตเพิ่มเติมเพิ่มเติม
เป็นไปได้ที่จะสมัครรับการแจ้งเตือนของทุก WindowManagerEvent
และ SocketMessage
ที่จัดการโดย komorebi
โดยใช้ Named Pipes
ขั้นแรก แอปพลิเคชันของคุณต้องสร้างไปป์ที่มีชื่อ เมื่อสร้างไปป์ที่มีชื่อแล้ว ให้รันคำสั่งต่อไปนี้:
komorebic.exe subscribe - pipe < your pipe name >
โปรดทราบว่าคุณไม่จำเป็นต้องรวมเส้นทางแบบเต็มของไปป์ที่มีชื่อ เพียงชื่อเท่านั้น
หากมีไปป์ที่มีชื่ออยู่แล้ว komorebi
จะเริ่มส่งข้อมูล JSON ของเหตุการณ์และข้อความที่จัดการได้สำเร็จ:
{ "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" :{}}
จากนั้นคุณอาจกรองคีย์ type
เพื่อฟังเหตุการณ์ที่คุณสนใจ สำหรับรายการประเภทการแจ้งเตือนที่เป็นไปได้ทั้งหมด โปรดดูตัวแปร enum ของ WindowManagerEvent
ใน komorebi
และ SocketMessage
ใน komorebi::core
ด้านล่างนี้เป็นตัวอย่างของวิธีที่คุณสามารถสมัครสมาชิกและกรองเหตุการณ์โดยใช้ไปป์ที่มีชื่อใน 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 ;
}
} ) ;
เป็นไปได้ที่จะสมัครรับการแจ้งเตือนของ WindowManagerEvent
และ SocketMessage
ทั้งหมดที่จัดการโดย komorebi
โดยใช้ Unix Domain Sockets
UDS ยังเป็นโหมดการสื่อสารเดียวระหว่าง komorebi
และ komorebic
ขั้นแรก แอปพลิเคชันของคุณจะต้องสร้างซ็อกเก็ตใน $ENV:LocalAppDatakomorebi
เมื่อสร้างซ็อกเก็ตแล้ว ให้รันคำสั่งต่อไปนี้:
komorebic.exe subscribe - socket < your socket name >
หากมีซ็อกเก็ตอยู่ komorebi จะเริ่มส่งข้อมูล JSON ของเหตุการณ์และข้อความที่จัดการได้สำเร็จดังตัวอย่างด้านบนในส่วน Named Pipes
ตั้งแต่ v0.1.22
เป็นต้นไป คุณสามารถใช้ komorebi-client
crate เพื่อสมัครรับการแจ้งเตือนของ WindowManagerEvent
และ SocketMessage
ทั้งหมดที่จัดการโดย komorebi
ในโค้ดเบสของ Rust
ด้านล่างนี้เป็นตัวอย่างง่ายๆ ของวิธีใช้ komorebi-client
ในแอปพลิเคชัน Rust พื้นฐาน
// 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}" ) ;
}
}
}
}
ตัวอย่างโลกการอ่านสามารถพบได้ใน komokana
JSON Schema ของการแจ้งเตือนเหตุการณ์ที่ส่งไปยังสมาชิกสามารถสร้างได้ด้วยคำสั่ง komorebic notification-schema
ผลลัพธ์ของคำสั่งนี้สามารถเปลี่ยนเส้นทางไปยังคลิปบอร์ดหรือไฟล์ได้ ซึ่งสามารถใช้กับบริการต่างๆ เช่น Quicktype เพื่อสร้างคำจำกัดความประเภทในภาษาการเขียนโปรแกรมต่างๆ
คุณสามารถเลือกที่จะเปิดเผย TCP Listener บนพอร์ตที่คุณเลือกได้ด้วยแฟล็ก --tcp-port=N
หากไม่ได้ระบุแฟล็กนี้ให้กับ komorebi
หรือ komorebic start
จะไม่มีการสร้าง TCP Listener
เมื่อสร้างแล้ว ไคลเอนต์ของคุณอาจส่ง SocketMessage ใด ๆ ไปยัง komorebi
ในลักษณะเดียวกับที่ komorebic
ส่ง
สามารถใช้สิ่งนี้ได้หากคุณต้องการสร้างทางเลือกของคุณเองแทน komorebic
ซึ่งรวมเอาการเขียนสคริปต์และเลเยอร์มิดเดิลแวร์ต่าง ๆ ไว้ และในทำนองเดียวกันก็สามารถใช้ได้หากคุณต้องการรวม komorebi
เข้ากับตัวจัดการอินพุตแบบกำหนดเอง
หากไคลเอนต์ส่งข้อความที่ไม่รู้จัก ข้อความนั้นจะถูกตัดการเชื่อมต่อและต้องเชื่อมต่อใหม่ก่อนที่จะพยายามสื่อสารอีกครั้ง
JSON Schema ของข้อความซ็อกเก็ตที่ใช้ในการส่งคำสั่งไปยัง komorebi
สามารถสร้างขึ้นได้ด้วยคำสั่ง komorebic socket-schema
ผลลัพธ์ของคำสั่งนี้สามารถเปลี่ยนเส้นทางไปยังคลิปบอร์ดหรือไฟล์ได้ ซึ่งสามารถใช้กับบริการต่างๆ เช่น Quicktype เพื่อสร้างคำจำกัดความประเภทในภาษาการเขียนโปรแกรมต่างๆ
ก่อนอื่นขอขอบคุณภรรยาของผมทั้งสำหรับการตั้งชื่อโครงการนี้และสำหรับความอดทนของเธอตลอดการพัฒนาที่ไม่มีที่สิ้นสุด
ขอขอบคุณ @sitiom สำหรับการเป็นผู้นำชุมชนโอเพ่นซอร์สที่เป็นแบบอย่าง
ขอขอบคุณนักพัฒนาของ nog ที่มาก่อนฉันและงานของเขาสอนฉันมากกว่าที่ฉันจะหวังว่าจะได้ตอบแทน
ขอขอบคุณนักพัฒนา GlazeWM ที่ขยายขอบเขตการจัดการหน้าต่างแบบเรียงต่อกันบน Windows กับฉันและมีจิตวิญญาณแห่งการทำงานร่วมกันที่ยอดเยี่ยม
ขอบคุณ @Ciantic ที่ช่วยฉันนำฟังก์ชันการปิดบัง Virtual Desktops ที่ซ่อนอยู่มาสู่ komorebi