diff --git a/panel/io/browser.py b/panel/io/browser.py index 2f22bed1d4..66fad402aa 100644 --- a/panel/io/browser.py +++ b/panel/io/browser.py @@ -46,6 +46,9 @@ class BrowserInfo(Syncable): webdriver = param.Boolean(default=None, doc=""" Indicates whether the user agent is controlled by automation.""") + webgl = param.Boolean(default=None, doc=""" + Indicates whether the browser has WebGL support.""") + # Mapping from parameter name to bokeh model property name _rename: ClassVar[Mapping[str, str | None]] = {"name": None} diff --git a/panel/models/browser.py b/panel/models/browser.py index 2709ab283c..c4f970e858 100644 --- a/panel/models/browser.py +++ b/panel/models/browser.py @@ -24,3 +24,5 @@ class BrowserInfo(Model): timezone_offset = Nullable(Float()) webdriver = Nullable(Bool()) + + webgl = Nullable(Bool()) diff --git a/panel/models/browser.ts b/panel/models/browser.ts index 311830c5d7..8aa69ccb81 100644 --- a/panel/models/browser.ts +++ b/panel/models/browser.ts @@ -24,6 +24,15 @@ export class BrowserInfoView extends View { if (timezone_offset != null) { this.model.timezone_offset = timezone_offset } + try { + const canvas = document.createElement("canvas") + this.model.webgl = !!( + window.WebGLRenderingContext && + (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")) + ) + } catch (e) { + this.model.webgl = false + } this._has_finished = true this.notify_finished() } @@ -38,6 +47,7 @@ export namespace BrowserInfo { timezone: p.Property timezone_offset: p.Property webdriver: p.Property + webgl: p.Property } } @@ -56,12 +66,13 @@ export class BrowserInfo extends Model { this.prototype.default_view = BrowserInfoView this.define(({Bool, Nullable, Float, Str}) => ({ - dark_mode: [ Nullable(Bool), null ], - device_pixel_ratio: [ Nullable(Float), null ], - language: [ Nullable(Str), null ], - timezone: [ Nullable(Str), null ], - timezone_offset: [ Nullable(Float), null ], - webdriver: [ Nullable(Bool), null ], + dark_mode: [ Nullable(Bool), null ], + device_pixel_ratio: [ Nullable(Float), null ], + language: [ Nullable(Str), null ], + timezone: [ Nullable(Str), null ], + timezone_offset: [ Nullable(Float), null ], + webdriver: [ Nullable(Bool), null ], + webgl: [ Nullable(Bool), null ], })) } }