From 7ceacec28ef4fff812e4bf47b9d39ef48425d379 Mon Sep 17 00:00:00 2001 From: Will Scullin Date: Sat, 25 Dec 2021 07:24:59 -0800 Subject: [PATCH] Full page improvements (#96) * Full page improvements * Update fullscreen api calls, save fullpage state --- apple2js.html | 2 +- apple2jse.html | 2 +- css/apple2.css | 11 ++++++--- js/prefs.ts | 9 ++++++++ js/ui/apple2.ts | 15 +++++++++--- js/ui/options_modal.ts | 2 +- js/ui/screen.ts | 52 ++++++++++++++++++++++++------------------ 7 files changed, 62 insertions(+), 31 deletions(-) diff --git a/apple2js.html b/apple2js.html index 8726d31..aa73bd2 100644 --- a/apple2js.html +++ b/apple2js.html @@ -96,7 +96,7 @@ - diff --git a/apple2jse.html b/apple2jse.html index 77dbd39..3004f76 100644 --- a/apple2jse.html +++ b/apple2jse.html @@ -97,7 +97,7 @@ - diff --git a/css/apple2.css b/css/apple2.css index 3534bec..90184b5 100644 --- a/css/apple2.css +++ b/css/apple2.css @@ -184,6 +184,7 @@ th { canvas { display: block; float: left; + image-rendering: pixelated; } .mono { @@ -192,7 +193,7 @@ canvas { .scanlines:after { display: block; - background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 1px, #000 1px, #000 2px); + background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 1px, rgba(0,0,0,0.5) 1px, rgba(0,0,0,0.5) 2px); content: ''; position: absolute; top: 0; @@ -201,6 +202,10 @@ canvas { right: 0; } +.full-page .scanlines:after { + background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 0.25vh, rgba(0,0,0,0.5) 0.25vh, rgba(0,0,0,0.5) 0.5vh); +} + #screen { cursor: crosshair; -moz-image-rendering: -moz-crisp-edges; @@ -214,8 +219,8 @@ canvas { background-color: black; top: 0; left: 0; - width: 100%; - height: 100%; + width: 100vw; + height: 100vh; } #about { diff --git a/js/prefs.ts b/js/prefs.ts index 596e55f..24d8a88 100644 --- a/js/prefs.ts +++ b/js/prefs.ts @@ -1,6 +1,11 @@ const havePrefs = typeof window.localStorage !== 'undefined'; export default class Prefs { + params: URLSearchParams + + constructor() { + this.params = new URLSearchParams(window.location.search); + } havePrefs() { return havePrefs; @@ -9,6 +14,10 @@ export default class Prefs { readPref(name: string): string | null readPref(name: string, defaultValue: string): string readPref(name: string, defaultValue: string | null = null) { + if (this.params.has(name)) { + return this.params.get(name); + } + if (havePrefs) { return window.localStorage.getItem(name) ?? defaultValue; } diff --git a/js/ui/apple2.ts b/js/ui/apple2.ts index 900c17b..8d44a12 100644 --- a/js/ui/apple2.ts +++ b/js/ui/apple2.ts @@ -25,11 +25,10 @@ import DiskII from '../cards/disk2'; import CPU6502 from '../cpu6502'; import { VideoModes } from '../videomodes'; import Apple2IO from '../apple2io'; -import { } from '../formats/format_utils'; import Printer from './printer'; import { OptionsModal } from './options_modal'; -import { Screen } from './screen'; +import { Screen, SCREEN_FULL_PAGE } from './screen'; import { JoyStick } from './joystick'; import { System } from './system'; @@ -886,8 +885,18 @@ function onLoaded(apple2: Apple2, disk2: DiskII, massStorage: MassStorage, print keyboard = new KeyBoard(cpu, io, e); keyboard.create('#keyboard'); keyboard.setFunction('F1', () => cpu.reset()); - keyboard.setFunction('F2', screen.enterFullScreen); + keyboard.setFunction('F2', (event) => { + if (event.shiftKey) { // Full window, but not full screen + optionsModal.setOption( + SCREEN_FULL_PAGE, + !optionsModal.getOption(SCREEN_FULL_PAGE) + ); + } else { + screen.enterFullScreen(); + } + }); keyboard.setFunction('F3', () => io.keyDown(0x1b)); // Escape + keyboard.setFunction('F4', optionsModal.openModal); keyboard.setFunction('F6', () => { window.localStorage.state = base64_json_stringify(_apple2.getState()); }); diff --git a/js/ui/options_modal.ts b/js/ui/options_modal.ts index c91f32f..bced211 100644 --- a/js/ui/options_modal.ts +++ b/js/ui/options_modal.ts @@ -85,7 +85,7 @@ export class OptionsModal { } } - openModal() { + openModal = () => { const content = document.querySelector('#options-modal-content'); if (content) { content.innerHTML = ''; diff --git a/js/ui/screen.ts b/js/ui/screen.ts index d38800e..fc1e678 100644 --- a/js/ui/screen.ts +++ b/js/ui/screen.ts @@ -1,45 +1,36 @@ import { VideoModes } from '../videomodes'; import { BOOLEAN_OPTION, OptionHandler } from './options_modal'; -const SCREEN_MONO = 'mono_screen'; -const SCREEN_SCANLINE = 'show_scanlines'; -const SCREEN_GL = 'gl_canvas'; +export const SCREEN_MONO = 'mono_screen'; +export const SCREEN_FULL_PAGE = 'full_page'; +export const SCREEN_SCANLINE = 'show_scanlines'; +export const SCREEN_GL = 'gl_canvas'; declare global { interface Document { webkitCancelFullScreen: () => void; webkitIsFullScreen: boolean; - mozCancelFullScreen: () => void; - mozIsFullScreen: boolean; } interface Element { webkitRequestFullScreen: (options?: any) => void; - mozRequestFullScreen: () => void; } } export class Screen implements OptionHandler { constructor(private vm: VideoModes) {} - enterFullScreen = (evt: KeyboardEvent) => { + enterFullScreen = () => { const elem = document.getElementById('screen')!; - if (evt.shiftKey) { // Full window, but not full screen - document.body.classList.toggle('full-page'); - } else if (document.webkitCancelFullScreen) { + if (document.fullscreenEnabled) { + if (document.fullscreenElement) { + void document.exitFullscreen(); + } else { + void elem.requestFullscreen(); + } + } else if (elem.webkitRequestFullScreen) { if (document.webkitIsFullScreen) { document.webkitCancelFullScreen(); } else { - const allowKeyboardInput = (Element as any).ALLOW_KEYBOARD_INPUT; - if (allowKeyboardInput) { - elem.webkitRequestFullScreen(allowKeyboardInput); - } else { - elem.webkitRequestFullScreen(); - } - } - } else if (document.mozCancelFullScreen) { - if (document.mozIsFullScreen) { - document.mozCancelFullScreen(); - } else { - elem.mozRequestFullScreen(); + elem.webkitRequestFullScreen(); } } }; @@ -61,6 +52,12 @@ export class Screen implements OptionHandler { type: BOOLEAN_OPTION, defaultVal: false, }, + { + name: SCREEN_FULL_PAGE, + label: 'Full Page', + type: BOOLEAN_OPTION, + defaultVal: false, + }, { name: SCREEN_GL, label: 'GL Renderer *', @@ -77,9 +74,20 @@ export class Screen implements OptionHandler { case SCREEN_MONO: this.vm.mono(value); break; + case SCREEN_FULL_PAGE: + this.setFullPage(value); + break; case SCREEN_SCANLINE: this.vm.scanlines(value); break; } } + + private setFullPage(on: boolean) { + if (on) { + document.body.classList.add('full-page'); + } else { + document.body.classList.remove('full-page'); + } + } }