مدیریت چندین نمایشگر با Window Management API، مدیریت چندین نمایشگر با Window Management API

اطلاعاتی در مورد نمایشگرهای متصل و موقعیت پنجره ها نسبت به آن نمایشگرها دریافت کنید.

API مدیریت پنجره

Window Management API به شما این امکان را می دهد که نمایشگرهای متصل به دستگاه خود را برشمارید و پنجره ها را روی صفحه های خاص قرار دهید.

موارد استفاده پیشنهادی

نمونه هایی از سایت هایی که ممکن است از این API استفاده کنند عبارتند از:

  • ویرایشگرهای گرافیکی چند پنجره ای à la Gimp می توانند ابزارهای ویرایشی مختلف را در پنجره هایی با موقعیت دقیق قرار دهند.
  • میزهای معاملات مجازی می توانند روندهای بازار را در چندین پنجره نشان دهند که هر یک از آنها در حالت تمام صفحه قابل مشاهده است.
  • برنامه‌های نمایش اسلاید می‌توانند یادداشت‌های بلندگو را در صفحه اصلی داخلی و ارائه را در یک پروژکتور خارجی نشان دهند.

نحوه استفاده از Window Management API

مشکل

متأسفانه روش آزمایش شده برای کنترل ویندوز، Window.open() از صفحات اضافی بی اطلاع است. در حالی که برخی از جنبه‌های این API کمی قدیمی به نظر می‌رسند، مانند پارامتر windowFeatures DOMString ، با این وجود در طول سال‌ها به خوبی به ما خدمت کرده است. برای تعیین موقعیت یک پنجره، می توانید مختصات را به صورت left و top (یا screenX و screenY به ترتیب) منتقل کنید و اندازه دلخواه را به عنوان width و height (یا innerWidth و innerHeight به ترتیب) ارسال کنید. به عنوان مثال، برای باز کردن یک پنجره 400×300 در 50 پیکسل از سمت چپ و 50 پیکسل از بالا، این کدی است که می توانید استفاده کنید:

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

می توانید با مشاهده ویژگی window.screen که یک شی Screen را برمی گرداند، اطلاعاتی در مورد صفحه فعلی دریافت کنید. این خروجی در MacBook Pro 13 اینچی من است:

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
*/

مانند بسیاری از افرادی که در فناوری کار می کنند، من مجبور شدم خودم را با واقعیت کار جدید وفق دهم و دفتر خانه شخصی ام را راه اندازی کنم. مال من مانند عکس زیر است (اگر علاقه مند هستید، می توانید جزئیات کامل در مورد تنظیمات من را بخوانید). آی‌پد کنار مک‌بوک من از طریق Sidecar به لپ‌تاپ متصل می‌شود، بنابراین هر زمان که نیاز داشته باشم، می‌توانم به سرعت آی‌پد را به صفحه دوم تبدیل کنم.

نیمکت مدرسه روی دو صندلی. بالای نیمکت مدرسه جعبه‌های کفشی قرار دارد که از یک لپ‌تاپ پشتیبانی می‌کند و دو آی‌پد در اطراف آن قرار دارند.
تنظیم چند صفحه

اگر بخواهم از مزایای صفحه نمایش بزرگتر استفاده کنم، می توانم پنجره بازشو از نمونه کد بالا را در صفحه دوم قرار دهم. من این کار را به این صورت انجام می دهم:

popup.moveTo(2500, 50);

این یک حدس تقریبی است، زیرا هیچ راهی برای دانستن ابعاد صفحه دوم وجود ندارد. اطلاعات window.screen فقط صفحه داخلی را پوشش می دهد، اما صفحه iPad را پوشش نمی دهد. width صفحه نمایش داخلی گزارش شده 1680 پیکسل بود، بنابراین حرکت به 2500 پیکسل ممکن است برای انتقال پنجره به iPad کار کند، زیرا اتفاقاً می دانم که در سمت راست مک بوک من قرار دارد. چگونه می توانم این کار را در حالت کلی انجام دهم؟ به نظر می رسد، راهی بهتر از حدس زدن وجود دارد. به این ترتیب API مدیریت پنجره است.

تشخیص ویژگی

برای بررسی اینکه آیا API مدیریت پنجره پشتیبانی می‌شود، از موارد زیر استفاده کنید:

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

مجوز window-management

قبل از اینکه بتوانم از API مدیریت پنجره استفاده کنم، باید از کاربر اجازه این کار را بخواهم. مجوز window-management می توان با مجوزهای API به این صورت جستجو کرد:

let granted = false;
try {
  const { state } = await navigator.permissions.query({ name: 'window-management' });
  granted = state === 'granted';
} catch {
  // Nothing.
}

در حالی که مرورگرهایی با نام مجوز قدیمی و جدید در حال استفاده هستند، هنگام درخواست مجوز حتما از کد دفاعی استفاده کنید، مانند مثال زیر.

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;
});

مرورگر می‌تواند در اولین تلاش برای استفاده از هر یک از روش‌های API جدید، درخواست مجوز را به صورت پویا نشان دهد. برای کسب اطلاعات بیشتر به ادامه مطلب مراجعه کنید.

ویژگی window.screen.isExtended

برای اینکه بفهمم بیش از یک صفحه به دستگاه من متصل است یا نه، به ویژگی window.screen.isExtended دسترسی پیدا می کنم. true یا false را برمی گرداند. برای راه‌اندازی من، true برمی‌گردد.

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

getScreenDetails()

اکنون که می‌دانم تنظیمات فعلی چند صفحه‌ای است، می‌توانم اطلاعات بیشتری درباره صفحه دوم با استفاده از Window.getScreenDetails() بدست بیاورم. با فراخوانی این تابع، یک درخواست مجوز نشان داده می‌شود که از من می‌پرسد آیا سایت ممکن است باز شود و پنجره‌ها را روی صفحه من قرار دهد یا خیر. تابع وعده ای را برمی گرداند که با یک شی ScreenDetailed حل می شود. در MacBook Pro 13 من با یک iPad متصل، این شامل یک قسمت screens با دو شی ScreenDetailed است:

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
  }]
}
*/

اطلاعات مربوط به صفحه های متصل در آرایه screens موجود است. توجه داشته باشید که چگونه مقدار left برای iPad از 1680 شروع می شود، که دقیقاً width صفحه نمایش داخلی است. این به من امکان می دهد دقیقاً نحوه چیدمان منطقی صفحه نمایش ها (در کنار یکدیگر، روی هم و غیره) را تعیین کنم. هم‌اکنون داده‌هایی برای هر صفحه وجود دارد که نشان می‌دهد آیا صفحه isInternal است یا isPrimary است یا خیر. توجه داشته باشید که صفحه نمایش داخلی لزوماً صفحه اصلی نیست .

فیلد currentScreen یک شی زنده مربوط به window.screen فعلی است. شی در محل قرارگیری پنجره های متقاطع صفحه یا تغییرات دستگاه به روز می شود.

رویداد screenschange

تنها چیزی که در حال حاضر وجود ندارد، راهی برای تشخیص زمان تغییر تنظیمات صفحه نمایش من است. یک رویداد جدید، screenschange ، دقیقاً این کار را انجام می دهد: هر زمان که صورت فلکی صفحه تغییر می کند، فعال می شود. (توجه داشته باشید که "صفحه نمایش" در نام رویداد جمع است.) این به این معنی است که هر زمان که یک صفحه جدید یا صفحه موجود (از لحاظ فیزیکی یا مجازی در مورد Sidecar) به برق وصل یا قطع شود، رویداد فعال می شود.

توجه داشته باشید که باید جزئیات صفحه جدید را به صورت ناهمزمان جستجو کنید، خود رویداد screenschange این داده ها را ارائه نمی دهد. برای جستجوی جزئیات صفحه، از شی زنده از یک رابط Screens در حافظه پنهان استفاده کنید.

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

اگر من فقط به تغییرات در صفحه فعلی علاقه مند هستم (یعنی مقدار جسم زنده currentScreen )، می توانم به رویداد currentscreenchange گوش دهم.

const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (event) => {
  const details = screenDetails.currentScreen;
  console.log('The current screen has changed.', event, details);
});

رویداد change

در نهایت، اگر من فقط به تغییرات در یک صفحه بتونی علاقه مند باشم، می توانم به رویداد change آن صفحه گوش دهم.

const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
  console.log('The first screen has changed.', event, firstScreen);
});

گزینه های تمام صفحه جدید

تا به حال، می‌توانید درخواست کنید که عناصر در حالت تمام‌صفحه از طریق متد requestFullScreen() با نام مناسب نمایش داده شوند. این روش یک پارامتر options را می گیرد که در آن می توانید FullscreenOptions ارسال کنید. تاکنون تنها ویژگی آن navigationUI بوده است. Window Management API یک ویژگی screen جدید اضافه می کند که به شما امکان می دهد تعیین کنید که نمای تمام صفحه را در کدام صفحه شروع کنید. به عنوان مثال، اگر می خواهید صفحه اصلی را تمام صفحه کنید:

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);
}

پلی پر

نمی‌توان API Window Management را چند بار پر کرد، اما می‌توانید شکل آن را تغییر دهید تا بتوانید منحصراً در برابر API جدید کدنویسی کنید:

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، یعنی رویدادهای مختلف تغییر صفحه نمایش و ویژگی screen FullscreenOptions ، به سادگی توسط مرورگرهایی که پشتیبانی نمی کنند هرگز فعال نمی شوند یا بی سر و صدا نادیده گرفته می شوند.

نسخه ی نمایشی

اگر شما هم مانند من هستید، توسعه ارزهای دیجیتال مختلف را زیر نظر داشته باشید. (در واقع من خیلی دوست ندارم این سیاره را دوست دارم، اما به خاطر این مقاله، فقط فرض کنید که این سیاره را دوست دارم.) برای پیگیری ارزهای دیجیتالی که مالک آنها هستم، یک برنامه وب ایجاد کرده ام که به من امکان می دهد تماشا کنم. بازارها در همه موقعیت‌های زندگی، مانند راحتی تختم، جایی که من یک صفحه نمایش خوب و مناسب دارم.

صفحه تلویزیون عظیم در انتهای تخت با پاهای نویسنده تا حدی قابل مشاهده است. روی صفحه، یک میز معاملات ارزهای دیجیتال جعلی.
استراحت و تماشای بازارها.

این در مورد کریپتو است، بازارها می توانند در هر زمان هولناک شوند. اگر این اتفاق بیفتد، می‌توانم به سرعت به سمت میز کارم حرکت کنم، جایی که تنظیمات چند صفحه‌ای را دارم. من می توانم روی پنجره هر ارز کلیک کنم و به سرعت جزئیات کامل را در یک نمای تمام صفحه در صفحه مقابل ببینم. در زیر یک عکس اخیر از من است که در آخرین حمام خون YCY گرفته شده است. من را کاملاً غافلگیر کرد و دستانم را روی صورتم گذاشت.

نویسنده با دستانش روی صورت وحشت زده اش که به میز معاملات ارزهای دیجیتال جعلی خیره شده است.
وحشت زده، شاهد حمام خون YCY.

می‌توانید با نسخه‌ی نمایشی تعبیه‌شده در زیر بازی کنید یا کد منبع آن را در نقص مشاهده کنید.

امنیت و مجوزها

تیم Chrome با استفاده از اصول اصلی تعریف شده در کنترل دسترسی به ویژگی‌های قدرتمند پلتفرم وب ، از جمله کنترل کاربر، شفافیت و ارگونومی، API مدیریت پنجره را طراحی و پیاده‌سازی کرده است. Window Management API اطلاعات جدیدی در مورد صفحه‌نمایش‌های متصل به یک دستگاه به نمایش می‌گذارد و سطح اثرانگشت کاربران را افزایش می‌دهد، به‌ویژه آنهایی که چندین صفحه به طور مداوم به دستگاه‌هایشان متصل هستند. به‌عنوان یکی از کاهش‌دهنده‌های این نگرانی حفظ حریم خصوصی، ویژگی‌های صفحه نمایش در معرض به حداقل مورد نیاز برای موارد استفاده معمول از مکان‌گذاری محدود شده است. اجازه کاربر برای سایت‌ها برای دریافت اطلاعات چند صفحه‌ای و قرار دادن پنجره‌ها بر روی صفحه‌های دیگر مورد نیاز است. در حالی که Chromium برچسب‌های دقیق صفحه نمایش را برمی‌گرداند، مرورگرها می‌توانند برچسب‌های کمتر توصیفی (یا حتی خالی) را برگردانند.

کنترل کاربر

کاربر کنترل کامل نوردهی تنظیمات خود را دارد. آنها می‌توانند درخواست مجوز را بپذیرند یا رد کنند، و مجوزی را که قبلاً اعطا شده بود از طریق ویژگی اطلاعات سایت در مرورگر لغو کنند.

کنترل سازمانی

کاربران Chrome Enterprise می‌توانند چندین جنبه از API مدیریت پنجره را همانطور که در بخش مربوطه تنظیمات گروه‌های خط‌مشی اتمی مشخص شده است، کنترل کنند.

شفافیت

این واقعیت که آیا مجوز استفاده از Window Management API اعطا شده است در اطلاعات سایت مرورگر آشکار است و همچنین از طریق Permissions API قابل استعلام است.

تداوم مجوز

مرورگر همچنان اجازه می دهد. مجوز را می توان از طریق اطلاعات سایت مرورگر لغو کرد.

بازخورد

تیم Chrome می‌خواهد درباره تجربیات شما با Window Management API بشنود.

در مورد طراحی API به ما بگویید

آیا چیزی در مورد API وجود دارد که آنطور که انتظار داشتید کار نمی کند؟ یا آیا روش ها یا ویژگی هایی وجود دارد که برای اجرای ایده خود به آنها نیاز دارید؟ سوال یا نظری در مورد مدل امنیتی دارید؟

  • یک مشکل مشخصات را در مخزن GitHub مربوطه ثبت کنید یا افکار خود را به یک مشکل موجود اضافه کنید.

گزارش مشکل در اجرا

آیا اشکالی در پیاده سازی کروم پیدا کردید؟ یا اجرا با مشخصات متفاوت است؟

  • یک اشکال را در new.crbug.com ثبت کنید. مطمئن شوید که تا جایی که می توانید جزئیات، دستورالعمل های ساده برای بازتولید را وارد کنید و Blink>Screen>MultiScreen در کادر Components وارد کنید. Glitch برای به اشتراک گذاری سریع و آسان تکرارها عالی عمل می کند.

پشتیبانی از API را نشان دهید

آیا قصد دارید از Windows Management API استفاده کنید؟ پشتیبانی عمومی شما به تیم Chrome کمک می‌کند ویژگی‌ها را اولویت‌بندی کند و به سایر فروشندگان مرورگر نشان می‌دهد که چقدر حمایت از آنها ضروری است.

  • نحوه استفاده از آن را در موضوع WICG Discourse به اشتراک بگذارید.
  • با استفاده از هشتگ #WindowManagement یک توییت به ChromiumDev@ ارسال کنید و به ما اطلاع دهید کجا و چگونه از آن استفاده می‌کنید.
  • از سایر فروشندگان مرورگر بخواهید که API را پیاده سازی کنند.

لینک های مفید

قدردانی

مشخصات API مدیریت پنجره توسط ویکتور کوستان ، جاشوا بل و مایک واسرمن ویرایش شده است. API توسط Mike Wasserman و Adrienne Walker پیاده سازی شد. این مقاله توسط Joe Medley , François Beaufort و Kayce Basques بررسی شده است . با تشکر از Laura Torrent Puig برای عکس ها.