WinUI ile Windows Terminali Oluşturma

  • History |
  • |
  • 0 Yorum

WinUI ve Windows Terminal, Windows Terminal'in kökenine kadar uzanan güçlü bir ilişkiye sahiptir. Bu blog yazısı, bu iki teknolojinin nasıl bir araya geldiğinin tarihine ve mimarisine giriyor.

Tarih

WinUI  ve Windows Terminal'in geçmişi  Aralık 2017'ye kadar uzanıyor. Bu, Windows Terminal olacak uygulamanın ilk prototipinin başladığı zamandı. Windows Terminal ekibi  olarak, konsol ve bir terminal uygulaması arasında bir çeviri katmanı olarak faydalı olacak kadar iyi bir yere konpty almaya yeni başlamıştık  Windows'ta komut satırı için yeni bir kullanıcı deneyimi oluşturmamıza olanak tanıyan yeni bir terminal uygulamasına güç sağlayabilecek bir yapıya sahip olmak istediğimizi biliyorduk.
Terminal için ilk planlama aşamalarındayken, Windows platformunun sunduğu en iyi özellikleri kullanan modern bir uygulama geliştirmek istediğimizi hemen biliyorduk. Diğer gelen kutusu uygulamalarıyla görsel olarak tutarlı olduğundan emin olmak istedik ve Akıcı Tasarım ilkelerini izledik.
UWP uygulaması olarak Windows Terminali oluşturmayı seçtik. Bu, bize hemen UWP XAML'ye ve özellikle Windows uygulamaları için oluşturulmuş yerel denetimler, stiller ve yetenekler içeren WinUI 2 kitaplığının tamamına erişim sağlar  O zamanlar, "UWP uygulamaları", işletim sistemi tarafından kendilerine özel kısıtlamalar getirmişti. Bu güvenlik özellikleri, Microsoft Store tarafından sağlanan UWP uygulamalarının işletim sistemi içindeki kısıtlı konumlara erişememesini veya kaldırma işlemini basitleştirmek için disk üzerinde yapıtlar bırakmamasını sağladı. Bu UWP uygulamalarının tümü, "düşük bütünlüklü uygulama kapsayıcı" içinde başlatılır; bu, temelde  hiçbir işletim sisteminde izinler. Çalışma dizinlerini değiştirmelerine bile izin verilmiyor. Harici işlemleri başlatmalarına izin verilir, ancak bu harici işlemler ayrıca uygulamanın bağlı olduğu aynı kısıtlamalara tabidir.
Bu nedenle, 2018'de Terminal'i bir UWP uygulaması olarak kurmak isteseydik, oluşturacağımız herhangi bir kabuk (cmd.exe, powershell.exe veya bash gibi) sisteme hiçbir şey yapamazdı. Dizinleri değiştirmeden, dosya içeriğini okumadan veya etkileşime girebileceğiniz diğer işlemleri başlatmadan kabuğunuzu kullanmayı hayal edebiliyor musunuz? Açıkçası, bu bizim için bir başlangıç ??değildi.
O yılın büyük bir bölümünü seçeneklerimizi Windows organizasyonundaki bir dizi ekiple tartışarak geçirdik. Bir UWP'den tam güvenilir süreçleri başlatmak için özel bir kısıtlı yetenek gibi seçenekleri düşündük. UWP uygulamalarının uygulama kapsayıcısının dışında çalışmasına izin vermeye çalıştık. Bununla birlikte, takip ettiğimiz yolların çoğu ya açık bir güvenlik açığı ya da kuruluş genelinde yıllarca çaba gerektiren bir şey olarak sonuçlandı. (Aslında, bu tartışmaların çoğu, şimdi “ Proje Birleşimi ” olarak bilinen çabanın yanı sıra   modern UI çerçevesini Masaüstü uygulamalarına genişleten WinUI 3 çabasına yol açtı).

XAML Adaları

Neyse ki bizim için çözüm aslında düşündüğümüzden daha yakındı. Koridorun hemen aşağısında WinUI ekibi vardı ve çok az şey biliyorduk  , önceki yılın daha iyi bir kısmı için XAML Adaları inşa ediyorlardı  XAML Adaları, geleneksel Win32 tarzı bir uygulamanın, bir UWP uygulamasının geleneksel kısıtlamaları olmadan UWP XAML içeriğini kendi penceresinde barındırmasına olanak tanır. Görünüşe göre, bu tam  olarak  ihtiyacımız olan şeydi.
Sonunda inşa ettiğimiz şey, iki bölümden oluşan bir uygulamaydı:
  • Çoğunlukla ekrana bir pencere çizmekten ve XAML Barındırma altyapısını başlatmaktan sorumlu olan ince bir Win32 penceresi
  • Uygulamanın büyük kısmı WinUI 2 kullanan bir UWP XAML Uygulaması olarak oluşturulmuştur. Bu katman, bir Win32 penceresi tarafından barındırıldığını bile bilmez. Tek bildiği, bu sadece normal bir C++/WinRT UWP uygulamasıdır.
Bu model, Terminal'in her iki dünyanın da en iyisini elde etmesini sağlar. Bir Win32 uygulaması olarak, bir terminal uygulamasının işlemleri başlatmak ve dosya sistemini sorgulamak için ihtiyaç duyabileceği tüm eski Win32 API'lerini kullanabiliriz. Ayrıca UWP XAML ve WinUI 2'nin gücünü, Terminal'in kullanıcı arayüzünü hızlı ve güzel bir şekilde oluşturmaya yardımcı olmak için kullanabildik.

Mimari

Windows Terminal mimarisinin daha ayrıntılı bir dökümü için aşağıdaki şemaya bakalım:
Bu şekilde, en üstteki turuncu kutu bizim Win32 katmanımızdır. Bu katman, son yürütülebilir dosyamızı oluşturur ve Win32 penceremizi manipüle etmek ve XAML içeriğimiz için bir XAML adası barındırmak için tüm mantığı içerir.
Alttaki iki mavi kutunun her ikisi de Windows Terminal uygulamasındaki bileşenlerdir. Bu iki bileşenin her ikisi de esasen yalnızca geleneksel bir UWP uygulamasında barındırılabilen UWP XAML bileşenleridir. Onlar sadece bu yüzden  gerçekleşmesi  , Windows Terminal için bir Win32 uygulamasında barındırılması, ama saf UWP bağlamında bunların yeniden durdurma şey yok. Aslında, Terminal deposu  , bunu yapmanın mümkün olduğunu kanıtlamak için TerminalApp'i barındıran saf bir UWP uygulaması bile oluşturur  .
TerminalApp projesi, uygulamanın kendisi için tüm mantığı temsil eder – sekmeler, bölmeler, ayarlar, UI öğelerimizin çoğu gibi şeyler; hepsi TerminalApp projesinin bir parçası. Terminal uygulamasının bir parçası olarak, diğer sekmelerde veya hatta yan yana (bölmelerde) birden fazla terminal örneğini aynı anda barındırabilir. Çözümü mantıklı bir şekilde parçalamamıza yardımcı olmak için, TerminalControl kendi projesidir: TerminalControl projesi. Bir gün, sadece TerminalControl için bir nuget paketi çıkarmayı umuyoruz, böylece diğer uygulama geliştiriciler de bunu kendi uygulamalarında kullanabilirler.
Windows'ta mümkün olan en hızlı terminali oluşturmak istediğimizi biliyorduk. XAML metin öğeleri hızlı ve kullanışlıdır, ancak WinUI ekibi, metin arabelleğimizi özel bir DirectX  metin oluşturucuyla işleyerek daha da hızlı performans elde edebileceğimize dikkat çekti  , bu yüzden bu yola gittik.
Neyse ki, eski konsol için GDI oluşturucunun yerini alacak bir DirectX oluşturucu üzerinde çalışmaya başlamıştık. Zaten sahip olduğumuz oluşturucuyu XAML'nin SwapChainPanel sınıfına bağlayabilmek nispeten önemsizdi  Bu, yalnızca GPU'da inanılmaz hızlı bir şekilde metin oluşturmamıza değil, aynı zamanda konsol kod tabanının büyük bir bölümünü yeni Terminal'de yeniden kullanmamıza izin verdi. Bu, Terminal'deki iyileştirmelerin gelen kutusu  konsolunu da iyileştirdiği anlamına gelir  .

uyarılar

Bu, hibrit bir uygulama geliştirme yolculuğunun tamamen ağrısız olduğu anlamına gelmiyor. Terminal üzerinde çalışmaya başladığımızdan bu yana, bu sürece girmeyi beklemediğimiz birkaç önemli engelle karşılaştık:
  • Kullanıcı arabirimimizi başlık çubuğu alanına sokmanın oldukça zor olduğu kanıtlanmıştır. Terminal artık başlık çubuğunda ikonik olarak sekme şeridine sahip olsa da, bu aslında uygulamanın Win32 bölümünde iyi bir miktar ağır kaldırmaydı. Neyse ki, topluluk üyesi  @greg904'ün yardımını aldık . O olmasaydı, Terminal başlık çubuğu bugün olduğu kadar parlak olmazdı.
  • Hibrit bir uygulamanın paketlenmesi kendi zorluklarına sahiptir. Uygulama paketleme projesi, bağımlılıklarımızı projemiz içinde tam olarak doğru klasörlere yerleştirme konusunda titiz olduğunu kanıtladı, bu da manüel olarak çok sayıda msbuild hedefi yazmak zorunda kaldığımız anlamına geliyor. Bunun nedeni muhtemelen wapproj proje tipinin gerçekten bunlar için tasarlanmamasıdır.
  • Mevcut XAML öğelerini kullanmak yerine kendi TerminalControl'ümüzü oluşturarak, kontrol için kendimiz için UIA ve erişilebilirlik desteği oluşturmamız gerekti. Bu, tamamen önemsiz olmayan bir süreç oldu ve kesinlikle beklediğimizden daha fazla geliştirme saatine mal oldu. Ancak, tüm geliştiricilerin Terminal'i etkin bir şekilde kullanabilmesini sağlamak kesinlikle zorunluydu.

Sekme Görünümü

Terminal'in ihtiyaç duyduğu temel özelliklerden biri sekmelerdi - kullanıcılar paralel olarak çalışan görevler ile birden fazla terminalin açık olmasını bekler. Sadece bu değil, aynı tarayıcıdaki sekme deneyimi gibi, sekme denetiminin de iyi görünmesi ve iyi hissetmesi gerekiyordu. Bir sekme deneyimi oluşturmaya ilk başladığımızda, Windows Topluluk Araç Seti'nde bir ilk uygulama olmasına rağmen WinUI 2'de sekme denetimi yoktu. Bu ilk C# uygulaması, denetim için API yönünü belirlemeye yardımcı olurken, yalnızca WinUI'de bulunabilen yüksek performanslı, yüksek cilalı bir denetime ihtiyacımız vardı.  WinUI 2'de yerleşik TabView denetiminin görünümünü ve verdiği hissi tanımlamak için WinUI ekibiyle (sırasıyla WCT çalışanları ve Edge ekibi gibi Microsoft içindeki çeşitli ekiplerle yakın işbirliği içinde çalıştı) yakın bir şekilde çalıştık  .
Bizim açımızdan, bu ortaklık faydalı olmuştur çünkü TabView için sekmeleri yeniden sıralama ve kapatma gibi pek çok işlevsel gereksinim WinUI ekibi tarafından oluşturulmuştur – ve WinUI ekibinin bakış açısına göre bu ortaklık faydalı olmuştur çünkü Terminal diğer uygulamalarda kullanılabilecek genel amaçlı bir TabView gereksinimlerinin ve tasarımının şekillendirilmesine yardımcı oldu. Ayrıca, WinUI TabView esnektir - örneğin, Terminal, "stok" TabView'da bulunmayan ancak kontrol içinde iyi desteklenen özel bir açılır sekme düğmesi içerir.

Tasarım süreci

TabView'ın nasıl görüneceğini tanımlamak için WinUI ekibiyle ve birçok tasarımcıyla birlikte çalıştık. Temel eskizlerden, sırayla çalışan bir kontrol olarak geliştirilen yüksek kaliteli maketlere geçtik. Aşağıda, Terminal'in nasıl görünmesini istediğimizi tanımlarken oluşturduğumuz bir maket var.
Birden fazla tasarımcıyla çalıştıktan ve birçok maket üzerinde yinelendikten sonra, TabView bugünkü haline geldi ve Windows Terminal içinde temel bir özellik.

İleriye bakmak

Windows Terminali daha fazla özellik kazandıkça, bunlar kullanılabilir hale geldikçe daha fazla kontrol eklemek için sürekli olarak WinUI ile çalışabiliriz. Listedeki bir sonraki büyük öğe, bugün mevcut olan birçok WinUI 2 kontrolünü kullanacak olan ayarlar arayüzüdür. Bu ortaklık harika oldu ve yeni özellikler ve kontroller oluşturarak hem Windows Terminalini hem de WinUI'yi geliştirmeye devam etmek için sabırsızlanıyoruz.