Bağlı ekranlar hakkında bilgi edinme ve pencereleri bu ekranlara göre konumlandırma
Yayınlanma tarihi: 14 Eylül 2020
Window Management API
Pencere Yönetimi API'si, makinenize bağlı ekranları listelemenize ve pencereleri belirli ekranlara yerleştirmenize olanak tanır.
Önerilen kullanım alanları
Bu API'yi kullanabilecek sitelere örnek olarak şunlar verilebilir:
- Gimp gibi çok pencereli grafik düzenleyiciler, çeşitli düzenleme araçlarını doğru konumlandırılmış pencerelere yerleştirebilir.
- Sanal ticaret masaları, piyasa trendlerini birden fazla pencerede gösterebilir. Bu pencerelerin herhangi biri tam ekran modunda görüntülenebilir.
- Slayt gösterisi uygulamaları, konuşmacı notlarını dahili birincil ekranda, sunuyu ise harici bir projektörde gösterebilir.
Window Management API'yi kullanma
Pencereleri kontrol etmek için uzun süredir kullanılan yaklaşım Window.open() maalesef ek ekranlardan haberdar değil. Bu API'nin bazı yönleri (ör. windowFeatures
DOMString parametresi) biraz eski görünse de yıllardır bize iyi hizmet vermiştir. Bir pencerenin konumunu belirtmek için koordinatları left ve top (veya sırasıyla screenX ve screenY) olarak, istenen boyutu ise width ve height (veya sırasıyla innerWidth ve innerHeight) olarak iletebilirsiniz. Örneğin, soldan 50 piksel ve üstten 50 piksel uzaklıkta 400×300 boyutlarında bir pencere açmak için kullanabileceğiniz kod şudur:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
window.screen özelliğine bakarak geçerli ekran hakkında bilgi edinebilirsiniz. Bu özellik, Screen nesnesi döndürür. MacBook Pro 13" cihazımdaki çıkış:
window.screen;
/* Output from my MacBook Pro 13″:
availHeight: 969
availLeft: 0
availTop: 25
availWidth: 1680
colorDepth: 30
height: 1050
isExtended: true
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 30
width: 1680
*/
Teknoloji sektöründe çalışan çoğu kişi gibi ben de 2020'deki çalışma koşullarına uyum sağlamak ve evimde kişisel ofisimi kurmak zorunda kaldım. Benimki fotoğraftaki gibi görünüyor. (İlgileniyorsanız kurulumumla ilgili tüm ayrıntıları okuyabilirsiniz.) MacBook'umun yanındaki iPad, Sidecar ile dizüstü bilgisayara bağlı. Bu sayede, gerektiğinde iPad'i hızlıca ikinci bir ekrana dönüştürebiliyorum.
Daha büyük ekrandan yararlanmak istiyorsam kod örneğindeki pop-up'ı ikinci ekrana yerleştirebilirim. Ben şöyle yapıyorum:
popup.moveTo(2500, 50);
İkinci ekranın boyutlarını bilmenin bir yolu olmadığından bu, kabaca bir tahmindir. window.screen cihazındaki bilgiler yalnızca yerleşik ekranı kapsar, iPad ekranını kapsamaz. Yerleşik ekranın bildirilen width değeri 1680 pikseldi. Bu nedenle, pencereyi iPad'e taşımak için 2500 piksele geçmek işe yarayabilir. Çünkü ben, iPad'in MacBook'umun sağ tarafında bulunduğunu biliyorum. How
can I do this in the general case? Tahmin etmek yerine daha iyi bir yol var. Bu yöntem, Pencere Yönetimi API'sidir.
Özellik algılama
Window Management API'nin desteklenip desteklenmediğini kontrol etmek için şunu kullanın:
if ('getScreenDetails' in window) {
// The Window Management API is supported.
}
window-management izni
Pencere Yönetimi API'sini kullanmadan önce kullanıcıdan izin istemem gerekiyor.
window-management izni, Permissions API ile şu şekilde sorgulanabilir:
let granted = false;
try {
const { state } = await navigator.permissions.query({ name: 'window-management' });
granted = state === 'granted';
} catch {
// Nothing.
}
Eski ve yeni izin adını içeren tarayıcılar kullanılırken izin isterken örnekteki gibi savunma amaçlı kod kullandığınızdan emin olun.
async function getWindowManagementPermissionState() {
let state;
// The new permission name.
try {
({ state } = await navigator.permissions.query({
name: "window-management",
}));
} catch (err) {
return `${err.name}: ${err.message}`;
}
return state;
}
document.querySelector("button").addEventListener>("click", async () = {
const state = await getWindowManagementPermissionState();
document.querySelector("pre").textContent = state;
});
Tarayıcı, yeni API'nin yöntemlerinden herhangi birini kullanma girişiminde izin istemini dinamik olarak göstermeyi seçebilir. Daha fazla bilgi edinmek için okumaya devam edin.
window.screen.isExtended özelliği
Cihazıma birden fazla ekranın bağlanıp bağlanmadığını öğrenmek için window.screen.isExtended özelliğine erişiyorum. true veya false değerini döndürür. Kurulumum için true değerini döndürüyor.
window.screen.isExtended;
// Returns `true` or `false`.
getScreenDetails() yöntemi
Mevcut kurulumun çok ekranlı olduğunu öğrendiğime göre, Window.getScreenDetails() kullanarak ikinci ekran hakkında daha fazla bilgi edinebilirim. Bu işlevi çağırdığımda, site ekranımda pencereler açıp yerleştirebilir mi diye soran bir izin istemi gösteriliyor. İşlev, ScreenDetailed nesnesiyle çözümlenen bir söz döndürür. Bağlı bir iPad'in bulunduğu MacBook Pro 13'ümde,
bu, iki ScreenDetailed nesnesi içeren bir screens alanı içerir:
await window.getScreenDetails();
/* Output from my MacBook Pro 13″ with the iPad attached:
{
currentScreen: ScreenDetailed {left: 0, top: 0, isPrimary: true, isInternal: true, devicePixelRatio: 2, …}
oncurrentscreenchange: null
onscreenschange: null
screens: [{
// The MacBook Pro
availHeight: 969
availLeft: 0
availTop: 25
availWidth: 1680
colorDepth: 30
devicePixelRatio: 2
height: 1050
isExtended: true
isInternal: true
isPrimary: true
label: "Built-in Retina Display"
left: 0
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 30
top: 0
width: 1680
},
{
// The iPad
availHeight: 999
availLeft: 1680
availTop: 25
availWidth: 1366
colorDepth: 24
devicePixelRatio: 2
height: 1024
isExtended: true
isInternal: false
isPrimary: false
label: "Sidecar Display (AirPlay)"
left: 1680
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 24
top: 0
width: 1366
}]
}
*/
Bağlı ekranlarla ilgili bilgiler screens dizisinde yer alır. iPad için left değerinin 1680 ile başladığını unutmayın. Bu değer, yerleşik ekranın width değeridir. Bu sayede, ekranların mantıksal olarak nasıl düzenlendiğini (yan yana, üst üste vb.) tam olarak belirleyebilirim. Ayrıca, her ekranın isInternal veya isPrimary olup olmadığını gösteren veriler de mevcuttur. Yerleşik ekranın birincil ekran olması gerekmediğini unutmayın.
currentScreen alanı, mevcut window.screen ile eşleşen canlı bir nesnedir. Nesne, ekranlar arası pencere yerleşimlerinde veya cihaz değişikliklerinde güncellenir.
screenschange etkinliği
Şu anda eksik olan tek şey, ekran kurulumumun değiştiğini algılamanın bir yoludur. Yeni bir etkinlik olan
screenschange, tam olarak bunu yapar: Ekran takımyıldızı her değiştirildiğinde tetiklenir. ("Ekranlar"ın etkinlik adında çoğul olduğuna dikkat edin.) Bu, yeni bir ekran veya mevcut bir ekran (Sidecar durumunda fiziksel ya da sanal olarak) takıldığında veya çıkarıldığında etkinliğin tetiklendiği anlamına gelir.
Yeni ekran ayrıntılarını eşzamansız olarak aramanız gerekir. screenschange etkinliği bu verileri sağlamaz. Ekran ayrıntılarını aramak için önbelleğe alınmış bir Screens arayüzünden canlı nesneyi kullanın.
const screenDetails = await window.getScreenDetails();
let cachedScreensLength = screenDetails.screens.length;
screenDetails.addEventListener('screenschange', (>event) = {
if (screenDetails.screens.length !== cachedScreensLength) {
console.log(
`The screen count changed from ${cachedScreensLength} to ${screenDetails.screens.length}`,
);
cachedScreensLength = screenDetails.screens.length;
}
});
currentscreenchange etkinliği
Yalnızca mevcut ekrandaki değişikliklerle (yani canlı nesnenin değeri currentScreen) ilgileniyorsam currentscreenchange etkinliğini dinleyebilirim.
const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (>event) = {
const details = screenDetails.currentScreen;
console.log('The current screen has changed.', event, details);
});
change etkinliği
Son olarak, yalnızca belirli bir ekrandaki değişikliklerle ilgileniyorsam o ekranın change etkinliğini dinleyebilirim.
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (>event) = {
console.log('The first screen has changed.', event, firstScreen);
});
Yeni tam ekran seçenekleri
Şimdiye kadar, uygun şekilde adlandırılmış
requestFullScreen()
yöntemiyle öğelerin tam ekran modunda gösterilmesini isteyebiliyordunuz. Yöntem, options parametresini alır. Bu parametreye FullscreenOptions değerini iletebilirsiniz. Şu ana kadar tek özelliği navigationUI oldu.
Window Management API, tam ekran görünümünün hangi ekranda başlatılacağını belirlemenize olanak tanıyan yeni bir screen özelliği ekler. Örneğin, birincil ekranı tam ekran yapmak istiyorsanız:
try {
const primaryScreen = (await getScreenDetails()).screens.filter((screen) => screen.isPrimary)[0];
await document.body.requestFullscreen({ screen: primaryScreen });
} catch (err) {
console.error(err.name, err.message);
}
Polyfill
Window Management API'yi polyfill yapmak mümkün değildir ancak şeklini shim yaparak yalnızca yeni API'ye karşı kod yazabilirsiniz:
if (!('getScreenDetails' in window)) {
// Returning a one-element array with the current screen,
// noting that there might be more.
window.getScreenDetails = as>ync () = [window.screen];
// Set to `false`, noting that this might be a lie.
window.screen.isExtended = false;
}
API'nin diğer yönleri (yani çeşitli ekran değişikliği etkinlikleri ve FullscreenOptions öğesinin screen özelliği) hiçbir zaman tetiklenmez veya desteklemeyen tarayıcılar tarafından sessizce yoksayılır.
Demo
Çeşitli kripto para birimlerinin gelişimini yakından takip ederseniz uygulamamdaki tek ekran kurulumuyla piyasaları yatağınızın rahatlığında izleyebilirsiniz. (Bu gezegeni çok sevdiğim için bu durumdan hiç hoşlanmıyorum ancak bu makalenin konusu gereği, bu durumdan hoşlandığımı varsayalım.)
Kripto para piyasalarıyla ilgili bu durum, piyasaların herhangi bir zamanda karışık hale gelmesine neden olabilir. Bu durumda, çoklu ekran kurulumumun olduğu masama hızlıca geçebilirim. Herhangi bir para biriminin penceresini tıklayarak tam ekran görünümünde tüm ayrıntıları hızlıca görebiliyorum. YCY kan banyosu sırasında çekilen son fotoğrafımı paylaşıyorum. Bu durum beni tamamen hazırlıksız yakaladı ve ellerimle yüzümü kapatmama neden oldu.
Demoyu inceleyin veya GitHub'daki kaynak kodunu görüntüleyin.
Güvenlik ve izinler
Chrome Ekibi, Window Management API'yi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme'de tanımlanan temel ilkeleri (kullanıcı kontrolü, şeffaflık ve ergonomi dahil) kullanarak tasarlayıp uygulamıştır. Pencere Yönetimi API'si, bir cihaza bağlı ekranlarla ilgili yeni bilgiler sunarak kullanıcıların parmak izi yüzeyini artırır. Bu durum, özellikle cihazlarına sürekli olarak birden fazla ekran bağlayan kullanıcılar için geçerlidir. Bu gizlilik endişesini gidermek için, gösterilen ekran özellikleri yaygın yerleşim kullanım alanları için gereken minimum düzeyle sınırlıdır.
Sitelerin çoklu ekran bilgisi alması ve pencereleri diğer ekranlara yerleştirmesi için kullanıcı izni gerekir. Chromium, ayrıntılı ekran etiketleri döndürürken tarayıcılar daha az açıklayıcı (hatta boş etiketler) döndürmekte serbesttir.
Kullanıcı denetimi
Kullanıcı, kurulumunun görünürlüğü üzerinde tam denetime sahiptir. Kullanıcılar izin istemini kabul edebilir veya reddedebilir ve daha önce verilen bir izni tarayıcıdaki site bilgileri özelliği aracılığıyla iptal edebilir.
Kurumsal kontrol
Chrome Enterprise kullanıcıları, Atomic Policy Groups ayarlarının ilgili bölümünde belirtildiği gibi Pencere Yönetimi API'sinin çeşitli yönlerini kontrol edebilir.
Şeffaflık
Pencere Yönetimi API'sini kullanma izninin verilip verilmediği, tarayıcının site bilgilerinde gösterilir ve Permissions API ile de sorgulanabilir.
İzin kalıcılığı
Tarayıcı, izinleri kalıcı olarak saklar. İzin, tarayıcının site bilgileri bölümünden iptal edilebilir.
Geri bildirim
API'nin beklendiğiniz gibi çalışmayan bir yönü var mı? Yoksa fikrinizi uygulamak için eksik yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var?
- İlgili GitHub deposunda bir spesifikasyon sorunu bildirin veya düşüncelerinizi mevcut bir soruna ekleyin.
- Chrome'un uygulamasıyla ilgili bir hata bildirin. Mümkün olduğunca fazla ayrıntı eklediğinizden, yeniden üretme talimatlarını verdiğinizden ve Bileşenler kutusuna
Blink>Screen>MultiScreengirdiğinizden emin olun.
API'ye desteğinizi gösterme
Pencere Yönetimi API'sini kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı satıcılarına bu özelliklerin desteklenmesinin ne kadar önemli olduğunu gösterir.
- Bu özelliği nasıl kullanmayı planladığınızı WICG Discourse iş parçacığında paylaşın.
#WindowManagementhashtag'ini kullanarak @ChromiumDev hesabına tweet gönderin ve nerede, nasıl kullandığınızı bize bildirin.- Diğer tarayıcı sağlayıcılarından API'yi uygulamalarını isteyin.
Kaynaklar
- Spec draft
- Herkese açık açıklayıcı
- Window Management API demosu | Window Management API demosu kaynağı
- Chromium izleme hatası
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>Screen>MultiScreen - TAG Review
- Deneme Yapma Amacı
Teşekkür
Window Management API spesifikasyonu Victor Costan, Joshua Bell ve Mike Wasserman tarafından düzenlendi. API, Mike Wasserman ve Adrienne Walker tarafından uygulandı. Bu makale Joe Medley, François Beaufort ve Kayce Basques tarafından incelenmiştir. Fotoğraflar için Laura Torrent Puig'e teşekkür ederiz.