mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Decaffeinate src/window-event-handler.coffee
This commit is contained in:
@@ -1,189 +0,0 @@
|
||||
{Disposable, CompositeDisposable} = require 'event-kit'
|
||||
listen = require './delegated-listener'
|
||||
|
||||
# Handles low-level events related to the @window.
|
||||
module.exports =
|
||||
class WindowEventHandler
|
||||
constructor: ({@atomEnvironment, @applicationDelegate}) ->
|
||||
@reloadRequested = false
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
@handleNativeKeybindings()
|
||||
|
||||
initialize: (@window, @document) ->
|
||||
@subscriptions.add @atomEnvironment.commands.add @window,
|
||||
'window:toggle-full-screen': @handleWindowToggleFullScreen
|
||||
'window:close': @handleWindowClose
|
||||
'window:reload': @handleWindowReload
|
||||
'window:toggle-dev-tools': @handleWindowToggleDevTools
|
||||
|
||||
if process.platform in ['win32', 'linux']
|
||||
@subscriptions.add @atomEnvironment.commands.add @window,
|
||||
'window:toggle-menu-bar': @handleWindowToggleMenuBar
|
||||
|
||||
@subscriptions.add @atomEnvironment.commands.add @document,
|
||||
'core:focus-next': @handleFocusNext
|
||||
'core:focus-previous': @handleFocusPrevious
|
||||
|
||||
@addEventListener(@window, 'beforeunload', @handleWindowBeforeunload)
|
||||
@addEventListener(@window, 'focus', @handleWindowFocus)
|
||||
@addEventListener(@window, 'blur', @handleWindowBlur)
|
||||
|
||||
@addEventListener(@document, 'keyup', @handleDocumentKeyEvent)
|
||||
@addEventListener(@document, 'keydown', @handleDocumentKeyEvent)
|
||||
@addEventListener(@document, 'drop', @handleDocumentDrop)
|
||||
@addEventListener(@document, 'dragover', @handleDocumentDragover)
|
||||
@addEventListener(@document, 'contextmenu', @handleDocumentContextmenu)
|
||||
@subscriptions.add listen(@document, 'click', 'a', @handleLinkClick)
|
||||
@subscriptions.add listen(@document, 'submit', 'form', @handleFormSubmit)
|
||||
|
||||
@subscriptions.add(@applicationDelegate.onDidEnterFullScreen(@handleEnterFullScreen))
|
||||
@subscriptions.add(@applicationDelegate.onDidLeaveFullScreen(@handleLeaveFullScreen))
|
||||
|
||||
# Wire commands that should be handled by Chromium for elements with the
|
||||
# `.native-key-bindings` class.
|
||||
handleNativeKeybindings: ->
|
||||
bindCommandToAction = (command, action) =>
|
||||
@subscriptions.add @atomEnvironment.commands.add(
|
||||
'.native-key-bindings',
|
||||
command,
|
||||
((event) => @applicationDelegate.getCurrentWindow().webContents[action]()),
|
||||
false
|
||||
)
|
||||
|
||||
bindCommandToAction('core:copy', 'copy')
|
||||
bindCommandToAction('core:paste', 'paste')
|
||||
bindCommandToAction('core:undo', 'undo')
|
||||
bindCommandToAction('core:redo', 'redo')
|
||||
bindCommandToAction('core:select-all', 'selectAll')
|
||||
bindCommandToAction('core:cut', 'cut')
|
||||
|
||||
unsubscribe: ->
|
||||
@subscriptions.dispose()
|
||||
|
||||
on: (target, eventName, handler) ->
|
||||
target.on(eventName, handler)
|
||||
@subscriptions.add(new Disposable ->
|
||||
target.removeListener(eventName, handler)
|
||||
)
|
||||
|
||||
addEventListener: (target, eventName, handler) ->
|
||||
target.addEventListener(eventName, handler)
|
||||
@subscriptions.add(new Disposable(-> target.removeEventListener(eventName, handler)))
|
||||
|
||||
handleDocumentKeyEvent: (event) =>
|
||||
@atomEnvironment.keymaps.handleKeyboardEvent(event)
|
||||
event.stopImmediatePropagation()
|
||||
|
||||
handleDrop: (event) ->
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
handleDragover: (event) ->
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
event.dataTransfer.dropEffect = 'none'
|
||||
|
||||
eachTabIndexedElement: (callback) ->
|
||||
for element in @document.querySelectorAll('[tabindex]')
|
||||
continue if element.disabled
|
||||
continue unless element.tabIndex >= 0
|
||||
callback(element, element.tabIndex)
|
||||
return
|
||||
|
||||
handleFocusNext: =>
|
||||
focusedTabIndex = @document.activeElement.tabIndex ? -Infinity
|
||||
|
||||
nextElement = null
|
||||
nextTabIndex = Infinity
|
||||
lowestElement = null
|
||||
lowestTabIndex = Infinity
|
||||
@eachTabIndexedElement (element, tabIndex) ->
|
||||
if tabIndex < lowestTabIndex
|
||||
lowestTabIndex = tabIndex
|
||||
lowestElement = element
|
||||
|
||||
if focusedTabIndex < tabIndex < nextTabIndex
|
||||
nextTabIndex = tabIndex
|
||||
nextElement = element
|
||||
|
||||
if nextElement?
|
||||
nextElement.focus()
|
||||
else if lowestElement?
|
||||
lowestElement.focus()
|
||||
|
||||
handleFocusPrevious: =>
|
||||
focusedTabIndex = @document.activeElement.tabIndex ? Infinity
|
||||
|
||||
previousElement = null
|
||||
previousTabIndex = -Infinity
|
||||
highestElement = null
|
||||
highestTabIndex = -Infinity
|
||||
@eachTabIndexedElement (element, tabIndex) ->
|
||||
if tabIndex > highestTabIndex
|
||||
highestTabIndex = tabIndex
|
||||
highestElement = element
|
||||
|
||||
if focusedTabIndex > tabIndex > previousTabIndex
|
||||
previousTabIndex = tabIndex
|
||||
previousElement = element
|
||||
|
||||
if previousElement?
|
||||
previousElement.focus()
|
||||
else if highestElement?
|
||||
highestElement.focus()
|
||||
|
||||
handleWindowFocus: ->
|
||||
@document.body.classList.remove('is-blurred')
|
||||
|
||||
handleWindowBlur: =>
|
||||
@document.body.classList.add('is-blurred')
|
||||
@atomEnvironment.storeWindowDimensions()
|
||||
|
||||
handleEnterFullScreen: =>
|
||||
@document.body.classList.add("fullscreen")
|
||||
|
||||
handleLeaveFullScreen: =>
|
||||
@document.body.classList.remove("fullscreen")
|
||||
|
||||
handleWindowBeforeunload: (event) =>
|
||||
if not @reloadRequested and not @atomEnvironment.inSpecMode() and @atomEnvironment.getCurrentWindow().isWebViewFocused()
|
||||
@atomEnvironment.hide()
|
||||
@reloadRequested = false
|
||||
@atomEnvironment.storeWindowDimensions()
|
||||
@atomEnvironment.unloadEditorWindow()
|
||||
@atomEnvironment.destroy()
|
||||
|
||||
handleWindowToggleFullScreen: =>
|
||||
@atomEnvironment.toggleFullScreen()
|
||||
|
||||
handleWindowClose: =>
|
||||
@atomEnvironment.close()
|
||||
|
||||
handleWindowReload: =>
|
||||
@reloadRequested = true
|
||||
@atomEnvironment.reload()
|
||||
|
||||
handleWindowToggleDevTools: =>
|
||||
@atomEnvironment.toggleDevTools()
|
||||
|
||||
handleWindowToggleMenuBar: =>
|
||||
@atomEnvironment.config.set('core.autoHideMenuBar', not @atomEnvironment.config.get('core.autoHideMenuBar'))
|
||||
|
||||
if @atomEnvironment.config.get('core.autoHideMenuBar')
|
||||
detail = "To toggle, press the Alt key or execute the window:toggle-menu-bar command"
|
||||
@atomEnvironment.notifications.addInfo('Menu bar hidden', {detail})
|
||||
|
||||
handleLinkClick: (event) =>
|
||||
event.preventDefault()
|
||||
uri = event.currentTarget?.getAttribute('href')
|
||||
if uri and uri[0] isnt '#' and /^https?:\/\//.test(uri)
|
||||
@applicationDelegate.openExternal(uri)
|
||||
|
||||
handleFormSubmit: (event) ->
|
||||
# Prevent form submits from changing the current window's URL
|
||||
event.preventDefault()
|
||||
|
||||
handleDocumentContextmenu: (event) =>
|
||||
event.preventDefault()
|
||||
@atomEnvironment.contextMenu.showForEvent(event)
|
||||
253
src/window-event-handler.js
Normal file
253
src/window-event-handler.js
Normal file
@@ -0,0 +1,253 @@
|
||||
const {Disposable, CompositeDisposable} = require('event-kit')
|
||||
const listen = require('./delegated-listener')
|
||||
|
||||
// Handles low-level events related to the `window`.
|
||||
module.exports =
|
||||
class WindowEventHandler {
|
||||
constructor ({atomEnvironment, applicationDelegate}) {
|
||||
this.handleDocumentKeyEvent = this.handleDocumentKeyEvent.bind(this)
|
||||
this.handleFocusNext = this.handleFocusNext.bind(this)
|
||||
this.handleFocusPrevious = this.handleFocusPrevious.bind(this)
|
||||
this.handleWindowBlur = this.handleWindowBlur.bind(this)
|
||||
this.handleEnterFullScreen = this.handleEnterFullScreen.bind(this)
|
||||
this.handleLeaveFullScreen = this.handleLeaveFullScreen.bind(this)
|
||||
this.handleWindowBeforeunload = this.handleWindowBeforeunload.bind(this)
|
||||
this.handleWindowToggleFullScreen = this.handleWindowToggleFullScreen.bind(this)
|
||||
this.handleWindowClose = this.handleWindowClose.bind(this)
|
||||
this.handleWindowReload = this.handleWindowReload.bind(this)
|
||||
this.handleWindowToggleDevTools = this.handleWindowToggleDevTools.bind(this)
|
||||
this.handleWindowToggleMenuBar = this.handleWindowToggleMenuBar.bind(this)
|
||||
this.handleLinkClick = this.handleLinkClick.bind(this)
|
||||
this.handleDocumentContextmenu = this.handleDocumentContextmenu.bind(this)
|
||||
this.atomEnvironment = atomEnvironment
|
||||
this.applicationDelegate = applicationDelegate
|
||||
this.reloadRequested = false
|
||||
this.subscriptions = new CompositeDisposable()
|
||||
|
||||
this.handleNativeKeybindings()
|
||||
}
|
||||
|
||||
initialize (window, document) {
|
||||
this.window = window
|
||||
this.document = document
|
||||
this.subscriptions.add(this.atomEnvironment.commands.add(this.window, {
|
||||
'window:toggle-full-screen': this.handleWindowToggleFullScreen,
|
||||
'window:close': this.handleWindowClose,
|
||||
'window:reload': this.handleWindowReload,
|
||||
'window:toggle-dev-tools': this.handleWindowToggleDevTools
|
||||
}))
|
||||
|
||||
if (['win32', 'linux'].includes(process.platform)) {
|
||||
this.subscriptions.add(this.atomEnvironment.commands.add(this.window,
|
||||
{'window:toggle-menu-bar': this.handleWindowToggleMenuBar})
|
||||
)
|
||||
}
|
||||
|
||||
this.subscriptions.add(this.atomEnvironment.commands.add(this.document, {
|
||||
'core:focus-next': this.handleFocusNext,
|
||||
'core:focus-previous': this.handleFocusPrevious
|
||||
}))
|
||||
|
||||
this.addEventListener(this.window, 'beforeunload', this.handleWindowBeforeunload)
|
||||
this.addEventListener(this.window, 'focus', this.handleWindowFocus)
|
||||
this.addEventListener(this.window, 'blur', this.handleWindowBlur)
|
||||
|
||||
this.addEventListener(this.document, 'keyup', this.handleDocumentKeyEvent)
|
||||
this.addEventListener(this.document, 'keydown', this.handleDocumentKeyEvent)
|
||||
this.addEventListener(this.document, 'drop', this.handleDocumentDrop)
|
||||
this.addEventListener(this.document, 'dragover', this.handleDocumentDragover)
|
||||
this.addEventListener(this.document, 'contextmenu', this.handleDocumentContextmenu)
|
||||
this.subscriptions.add(listen(this.document, 'click', 'a', this.handleLinkClick))
|
||||
this.subscriptions.add(listen(this.document, 'submit', 'form', this.handleFormSubmit))
|
||||
|
||||
this.subscriptions.add(this.applicationDelegate.onDidEnterFullScreen(this.handleEnterFullScreen))
|
||||
this.subscriptions.add(this.applicationDelegate.onDidLeaveFullScreen(this.handleLeaveFullScreen))
|
||||
}
|
||||
|
||||
// Wire commands that should be handled by Chromium for elements with the
|
||||
// `.native-key-bindings` class.
|
||||
handleNativeKeybindings () {
|
||||
const bindCommandToAction = (command, action) => {
|
||||
this.subscriptions.add(
|
||||
this.atomEnvironment.commands.add(
|
||||
'.native-key-bindings',
|
||||
command,
|
||||
event => this.applicationDelegate.getCurrentWindow().webContents[action](),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
bindCommandToAction('core:copy', 'copy')
|
||||
bindCommandToAction('core:paste', 'paste')
|
||||
bindCommandToAction('core:undo', 'undo')
|
||||
bindCommandToAction('core:redo', 'redo')
|
||||
bindCommandToAction('core:select-all', 'selectAll')
|
||||
bindCommandToAction('core:cut', 'cut')
|
||||
}
|
||||
|
||||
unsubscribe () {
|
||||
this.subscriptions.dispose()
|
||||
}
|
||||
|
||||
on (target, eventName, handler) {
|
||||
target.on(eventName, handler)
|
||||
this.subscriptions.add(new Disposable(function () {
|
||||
target.removeListener(eventName, handler)
|
||||
}))
|
||||
}
|
||||
|
||||
addEventListener (target, eventName, handler) {
|
||||
target.addEventListener(eventName, handler)
|
||||
this.subscriptions.add(new Disposable(function () {
|
||||
target.removeEventListener(eventName, handler)
|
||||
}))
|
||||
}
|
||||
|
||||
handleDocumentKeyEvent (event) {
|
||||
this.atomEnvironment.keymaps.handleKeyboardEvent(event)
|
||||
event.stopImmediatePropagation()
|
||||
}
|
||||
|
||||
handleDrop (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
handleDragover (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
event.dataTransfer.dropEffect = 'none'
|
||||
}
|
||||
|
||||
eachTabIndexedElement (callback) {
|
||||
for (let element of this.document.querySelectorAll('[tabindex]')) {
|
||||
if (element.disabled) { continue }
|
||||
if (!(element.tabIndex >= 0)) { continue }
|
||||
callback(element, element.tabIndex)
|
||||
}
|
||||
}
|
||||
|
||||
handleFocusNext () {
|
||||
const focusedTabIndex = this.document.activeElement.tabIndex != null ? this.document.activeElement.tabIndex : -Infinity
|
||||
|
||||
let nextElement = null
|
||||
let nextTabIndex = Infinity
|
||||
let lowestElement = null
|
||||
let lowestTabIndex = Infinity
|
||||
this.eachTabIndexedElement(function (element, tabIndex) {
|
||||
if (tabIndex < lowestTabIndex) {
|
||||
lowestTabIndex = tabIndex
|
||||
lowestElement = element
|
||||
}
|
||||
|
||||
if (focusedTabIndex < tabIndex && tabIndex < nextTabIndex) {
|
||||
nextTabIndex = tabIndex
|
||||
nextElement = element
|
||||
}
|
||||
})
|
||||
|
||||
if (nextElement != null) {
|
||||
nextElement.focus()
|
||||
} else if (lowestElement != null) {
|
||||
lowestElement.focus()
|
||||
}
|
||||
}
|
||||
|
||||
handleFocusPrevious () {
|
||||
const focusedTabIndex = this.document.activeElement.tabIndex != null ? this.document.activeElement.tabIndex : Infinity
|
||||
|
||||
let previousElement = null
|
||||
let previousTabIndex = -Infinity
|
||||
let highestElement = null
|
||||
let highestTabIndex = -Infinity
|
||||
this.eachTabIndexedElement(function (element, tabIndex) {
|
||||
if (tabIndex > highestTabIndex) {
|
||||
highestTabIndex = tabIndex
|
||||
highestElement = element
|
||||
}
|
||||
|
||||
if (focusedTabIndex > tabIndex && tabIndex > previousTabIndex) {
|
||||
previousTabIndex = tabIndex
|
||||
previousElement = element
|
||||
}
|
||||
})
|
||||
|
||||
if (previousElement != null) {
|
||||
previousElement.focus()
|
||||
} else if (highestElement != null) {
|
||||
highestElement.focus()
|
||||
}
|
||||
}
|
||||
|
||||
handleWindowFocus () {
|
||||
this.document.body.classList.remove('is-blurred')
|
||||
}
|
||||
|
||||
handleWindowBlur () {
|
||||
this.document.body.classList.add('is-blurred')
|
||||
this.atomEnvironment.storeWindowDimensions()
|
||||
}
|
||||
|
||||
handleEnterFullScreen () {
|
||||
this.document.body.classList.add('fullscreen')
|
||||
}
|
||||
|
||||
handleLeaveFullScreen () {
|
||||
this.document.body.classList.remove('fullscreen')
|
||||
}
|
||||
|
||||
handleWindowBeforeunload (event) {
|
||||
if (!this.reloadRequested && !this.atomEnvironment.inSpecMode() && this.atomEnvironment.getCurrentWindow().isWebViewFocused()) {
|
||||
this.atomEnvironment.hide()
|
||||
}
|
||||
this.reloadRequested = false
|
||||
this.atomEnvironment.storeWindowDimensions()
|
||||
this.atomEnvironment.unloadEditorWindow()
|
||||
this.atomEnvironment.destroy()
|
||||
}
|
||||
|
||||
handleWindowToggleFullScreen () {
|
||||
this.atomEnvironment.toggleFullScreen()
|
||||
}
|
||||
|
||||
handleWindowClose () {
|
||||
this.atomEnvironment.close()
|
||||
}
|
||||
|
||||
handleWindowReload () {
|
||||
this.reloadRequested = true
|
||||
this.atomEnvironment.reload()
|
||||
}
|
||||
|
||||
handleWindowToggleDevTools () {
|
||||
this.atomEnvironment.toggleDevTools()
|
||||
}
|
||||
|
||||
handleWindowToggleMenuBar () {
|
||||
this.atomEnvironment.config.set('core.autoHideMenuBar', !this.atomEnvironment.config.get('core.autoHideMenuBar'))
|
||||
|
||||
if (this.atomEnvironment.config.get('core.autoHideMenuBar')) {
|
||||
const detail = 'To toggle, press the Alt key or execute the window:toggle-menu-bar command'
|
||||
this.atomEnvironment.notifications.addInfo('Menu bar hidden', {detail})
|
||||
}
|
||||
}
|
||||
|
||||
handleLinkClick (event) {
|
||||
event.preventDefault()
|
||||
const uri = event.currentTarget && event.currentTarget.getAttribute('href')
|
||||
if (uri && (uri[0] !== '#') && /^https?:\/\//.test(uri)) {
|
||||
this.applicationDelegate.openExternal(uri)
|
||||
}
|
||||
}
|
||||
|
||||
handleFormSubmit (event) {
|
||||
// Prevent form submits from changing the current window's URL
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
handleDocumentContextmenu (event) {
|
||||
event.preventDefault()
|
||||
this.atomEnvironment.contextMenu.showForEvent(event)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user