Window Management API ile birkaç ekranı yönetme

Bağlı ekranlar hakkında bilgi edinin ve pencereleri bu ekranlara göre konumlandırın.

Window Management API

Pencere Yönetimi API'si, makinenize bağlı ekranları saymanıza 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 işlem masaları, pazar trendlerini birden fazla pencerede gösterebilir. Bu pencerelerin her biri tam ekran modunda görüntülenebilir.
  • Slayt gösterisi uygulamaları, konuşmacı notlarını dahili birincil ekranda ve sunuyu harici bir projektörde gösterebilir.

Window Management API'yi kullanma

Sorun

Pencereleri kontrol etmek için zaman içinde kanıtlanmış bir yaklaşım olan Window.open(), maalesef ek ekranları hesaba katmaz. Bu API'nin bazı yönleri (ör. windowFeatures DOMString parametresi) biraz eski görünse de yıllar boyunca bize iyi hizmet etti. 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 mesafede 400x300 boyutunda bir pencere açmak için şu kodu kullanabilirsiniz:

const popup = window.open(
  'https://example.com/',
  'My Popup',
  'left=50,top=50,width=400,height=300',
);

Screen nesnesi döndüren window.screen mülküne bakarak geçerli ekran hakkında bilgi edinebilirsiniz. MacBook Pro 13 inç cihazımdaki çıkış şu şekildedir:

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 yeni çalışma koşullarına uyum sağlamak ve kişisel ev ofisimi kurmak zorunda kaldım. Benimki aşağıdaki fotoğraftaki gibi görünüyor (İsterseniz kurulumumla ilgili tüm ayrıntıları okuyabilirsiniz). MacBook'ımın yanındaki iPad, Sidecar aracılığıyla dizüstü bilgisayara bağlı. Böylece, gerektiğinde iPad'i hızlıca ikinci ekrana dönüştürebiliyorum.

İki sandalye üzerinde okul bankı. Okul bankının üzerinde, bir dizüstü bilgisayarı destekleyen ayakkabı kutuları ve etrafında iki iPad var.
Çok ekranlı kurulum.

Daha büyük ekrandan yararlanmak isterseniz yukarıdaki kod örneğindeki pop-up'ı ikinci ekrana yerleştirebilirsiniz. Bunu şu şekilde yapıyorum:

popup.moveTo(2500, 50);

İkinci ekranın boyutlarını bilmenin bir yolu olmadığından bu tahmin yaklaşıktır. window.screen'ten alınan bilgiler yalnızca yerleşik ekranı kapsar, iPad ekranını kapsamaz. Yerleşik ekranın bildirilen width değeri 1680 piksel olduğundan, 2500 piksele geçmek pencereyi iPad'e taşımak için işe yarayabilir. Bunun MacBook'ımın sağ tarafında olduğunu biliyorum. Bunu genel olarak nasıl yapabilirim? Tahmin etmekten daha iyi bir yöntem olduğu ortaya çıktı. Bu yöntem, Window Management API'dir.

Özellik algılama

Window Management API'nin desteklenip desteklenmediğini kontrol etmek için:

if ('getScreenDetails' in window) {
  // The Window Management API is supported.
}

window-management izni

Window Management API'yi kullanabilmek için kullanıcıdan izin istemem gerekir. window-management izni, Permissions API ile aşağıdaki gibi 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ın kullanıldığı tarayıcılarda izin isterken aşağıdaki örnekte gösterildiği 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 kullanmaya ilk girişimde izin istemini dinamik olarak göstermeyi seçebilir. Daha fazla bilgi için okumaya devam edin.

window.screen.isExtended mülkü

Cihazıma birden fazla ekranın bağlı olup olmadığını öğrenmek için window.screen.isExtended mülküne erişiyorum. true veya false döndürür. Benim kurulumumda true döndürülüyor.

window.screen.isExtended;
// Returns `true` or `false`.

getScreenDetails() yöntemi

Mevcut kurulumun çok ekranlı olduğunu bildiğim için Window.getScreenDetails() kullanarak ikinci ekran hakkında daha fazla bilgi edinebilirim. Bu işlevi çağırdığımda, sitenin ekranımda pencere açıp yerleştirip yerleştiremeyeceğini soran bir izin istemi gösterilir. İşlev, ScreenDetailed nesnesi ile çözülen bir promise döndürür. iPad'in bağlı olduğ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 bulunur. iPad için left değerinin 1680 ile başladığını, bunun da tam olarak yerleşik ekranın width değeri olduğunu unutmayın. Bu sayede ekranların mantıksal olarak nasıl düzenlendiğini (yan yana, üst üste vb.) tam olarak belirleyebilirim. Artık her ekran için isInternal ekranı mı yoksa isPrimary ekranı mı olduğunu gösteren veriler de mevcuttur. Yerleşik ekranın mutlaka birincil ekran olmayabileceğini unutmayın.

currentScreen alanı, mevcut window.screen'a karşılık gelen canlı bir nesnedir. Nesne, ekranlar arası pencere yerleşimlerinde veya cihaz değişikliklerinde güncellenir.

screenschange etkinliği

Ekran kurulumum değiştiğinde bunu algılamanın bir yolunu bulmak istiyorum. Yeni bir etkinlik olan screenschange tam da bunu yapar: Ekran takımyıldızı değiştirildiğinde tetiklenir. ("screens" ifadesinin etkinlik adında çoğul olduğunu unutmayın.) Bu, yeni bir ekran veya mevcut bir ekran (Sidecar'da fiziksel olarak ya da sanal olarak) her takıldığında ya da prizden çekildiğinde etkinliğin tetiklendiği anlamına gelir.

Yeni ekran ayrıntılarını eşzamansız olarak aramanız gerektiğini unutmayın. screenschange etkinliği bu verileri sağlamaz. Ekran ayrıntılarını görüntülemek için önbelleğe alınmış bir Screens arayüzündeki 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 geçerli ekrandaki değişikliklerle (yani canlı nesnenin currentScreen değeri) 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 söz konusu 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öntemi aracılığıyla öğelerin tam ekran modunda gösterilmesini isteyebilirdiniz. Yöntem, FullscreenOptions iletmenizi sağlayan bir options parametresi alır. Şimdiye kadar tek mülkü navigationUI olmuştur. Window Management API, tam ekran görünümün hangi ekranda başlatılacağını belirlemenize olanak tanıyan yeni bir screen mülkü 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);
}

Çoklu dolgu

Window Management API'yi polyfill olarak doldurmak mümkün değildir ancak yalnızca yeni API'ye göre kod yazabilmek için şeklini değiştirebilirsiniz:

if (!('getScreenDetails' in window)) {
  // Returning a one-element array with the current screen,
  // noting that there might be more.
  window.getScreenDetails = async () => [window.screen];
  // Set to `false`, noting that this might be a lie.
  window.screen.isExtended = false;
}

API'nin diğer yönleri (ör. çeşitli ekran değiştirme etkinlikleri ve FullscreenOptions nesnesinin screen mülkü) desteklenmeyen tarayıcılar tarafından hiçbir zaman tetiklenmez veya sessizce yoksayılır.

Demo

Benim gibiyseniz çeşitli kripto para birimlerinin gelişimini yakından takip edersiniz. (Aslında bu gezegeni sevdiğim için çok da istemiyorum ama bu makale için bunu yaptığımı varsayın.) Sahip olduğum kripto para birimlerini takip etmek için, piyasaları tüm yaşam durumlarımda (ör. iyi bir tek ekranlı kurulumun bulunduğu yatağımın rahatlığında) izlememe olanak tanıyan bir web uygulaması geliştirdim.

Yatağın ucundaki büyük TV ekranı ve yazarın kısmen görünen bacakları. Ekranda sahte bir kripto para alım satımı masası var.
Rahatlamak ve piyasaları izlemek.

Kripto para birimleri söz konusu olduğunda piyasalar her an hareketli olabilir. Böyle bir durumda, çok ekranlı kurulumun bulunduğu masama hızlıca geçebilirim. Herhangi bir para biriminin penceresini tıklayıp tam ekran görünümünde tüm ayrıntıları hızlıca görebilirim. Aşağıda, son YCY kan banyosu sırasında çekilmiş bir fotoğrafımı görebilirsiniz. Bu durum beni tamamen hazırlıksız yakaladı ve ellerimi yüzüme kapatmama neden oldu.

Elleri panik halindeki yüzünde olan yazar, sahte kripto para alım satımı masasına bakıyor.
YCY'deki kanlı katliama tanık olan panik halindeki bir kişi.

Aşağıya yerleştirilmiş demo ile oynayabilir veya glitch'te kaynak kodunu görebilirsiniz.

Güvenlik ve izinler

Chrome ekibi, Window Management API'yi tasarlarken ve uygularken kullanıcı kontrolü, şeffaflık ve ergonomi gibi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme başlıklı makalede belirtilen temel ilkeleri temel almıştır. Pencere Yönetimi API'si, bir cihaza bağlı ekranlarla ilgili yeni bilgiler sunarak kullanıcıların (özellikle de cihazlarına sürekli olarak bağlı birden fazla ekranı olan kullanıcıların) parmak izi yüzeyini artırır. Bu gizlilik endişesini azaltmak 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 bilgilerini alması ve diğer ekranlara pencere yerleştirmesi için kullanıcı izni gerekir. Chromium ayrıntılı ekran etiketleri döndürür ancak tarayıcıların daha az açıklayıcı (veya hatta boş etiketler) döndürmesi serbesttir.

Kullanıcı denetimi

Kullanıcı, kurulumunun pozlamasını tamamen kontrol eder. Kullanıcılar izin istemlerini kabul edebilir veya reddedebilir ve daha önce verilen izinleri tarayıcıdaki site bilgileri özelliği aracılığıyla iptal edebilir.

Kurumsal kontrol

Chrome Enterprise kullanıcıları, Atomik Politika Grupları ayarlarının ilgili bölümünde belirtildiği gibi Window Management API'nin çeşitli yönlerini kontrol edebilir.

Şeffaflık

Pencere Yönetimi API'sinin kullanım izninin verilip verilmediği, tarayıcının site bilgilerinde gösterilir ve ayrıca İzinler API'si aracılığıyla sorgulanabilir.

İzin kalıcılığı

Tarayıcı, izin verme işlemlerini devam ettirir. İzin, tarayıcının site bilgileri üzerinden iptal edilebilir.

Geri bildirim

Chrome ekibi, Window Management API ile ilgili deneyimlerinizi öğrenmek istiyor.

API tasarımı hakkında bilgi verin

API ile ilgili olarak beklediğiniz gibi çalışmayan bir şey var mı? Yoksa fikrinizi uygulamak için ihtiyaç duyduğunuz yöntemler veya özellikler eksik mi? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var?

  • İlgili GitHub deposunda özellik sorunu gönderin veya düşüncelerinizi mevcut bir soruna ekleyin.

Uygulamayla ilgili sorunları bildirme

Chrome'un uygulamasında bir hata mı buldunuz? Yoksa uygulama, spesifikasyondan farklı mı?

  • new.crbug.com adresinden hata kaydı oluşturun. Mümkün olduğunca fazla ayrıntı ekleyin, hatayı yeniden oluşturmayla ilgili basit talimatlar verin ve Bileşenler kutusuna Blink>Screen>MultiScreen yazın. Glitch, hızlı ve kolay yeniden oluşturma işlemlerini paylaşmak için idealdir.

API'yi destekleme

Window Management API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı tedarikçi firmalarına bu özellikleri desteklemenin ne kadar önemli olduğunu gösterir.

  • WICG Discourse mesaj dizisinde bu özelliği nasıl kullanmayı planladığınızı paylaşın.
  • #WindowManagement hashtag'ini kullanarak @ChromiumDev hesabına tweet gönderin ve bu özelliği nerede ve nasıl kullandığınızı bize bildirin.
  • Diğer tarayıcı tedarikçilerinden API'yi uygulamalarını isteyin.

Faydalı bağlantılar

Teşekkür ederiz

Window Management API spesifikasyonu Victor Costan, Joshua Bell ve Mike Wasserman tarafından düzenlenmiştir. API, Mike Wasserman ve Adrienne Walker tarafından uygulanmıştır. Bu makale; Joe Medley, François Beaufort ve Kayce Basques tarafından incelendi. Fotoğraflar için Laura Torrent Puig'e teşekkürler.