mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-24 17:26:06 +08:00
202 lines
6.7 KiB
CoffeeScript
202 lines
6.7 KiB
CoffeeScript
|
path = require 'path'
|
||
|
{$} = require './space-pen-extensions'
|
||
|
_ = require 'underscore-plus'
|
||
|
{Disposable} = require 'event-kit'
|
||
|
ipc = require 'ipc'
|
||
|
shell = require 'shell'
|
||
|
{Subscriber} = require 'emissary'
|
||
|
fs = require 'fs-plus'
|
||
|
url = require 'url'
|
||
|
|
||
|
# Handles low-level events related to the window.
|
||
|
module.exports =
|
||
|
class WindowEventHandler
|
||
|
Subscriber.includeInto(this)
|
||
|
|
||
|
constructor: ->
|
||
|
@reloadRequested = false
|
||
|
|
||
|
@subscribe ipc, 'message', (message, detail) ->
|
||
|
switch message
|
||
|
when 'open-path'
|
||
|
{pathToOpen, initialLine, initialColumn} = detail
|
||
|
|
||
|
unless atom.project?.getPaths().length
|
||
|
if fs.existsSync(pathToOpen) or fs.existsSync(path.dirname(pathToOpen))
|
||
|
atom.project?.setPaths([pathToOpen])
|
||
|
|
||
|
unless fs.isDirectorySync(pathToOpen)
|
||
|
atom.workspace?.open(pathToOpen, {initialLine, initialColumn})
|
||
|
|
||
|
when 'update-available'
|
||
|
atom.updateAvailable(detail)
|
||
|
|
||
|
# FIXME: Remove this when deprecations are removed
|
||
|
{releaseVersion, releaseNotes} = detail
|
||
|
detail = [releaseVersion, releaseNotes]
|
||
|
if workspaceElement = atom.views.getView(atom.workspace)
|
||
|
atom.commands.dispatch workspaceElement, "window:update-available", detail
|
||
|
|
||
|
@subscribe ipc, 'command', (command, args...) ->
|
||
|
activeElement = document.activeElement
|
||
|
# Use the workspace element view if body has focus
|
||
|
if activeElement is document.body and workspaceElement = atom.views.getView(atom.workspace)
|
||
|
activeElement = workspaceElement
|
||
|
atom.commands.dispatch(activeElement, command, args[0])
|
||
|
|
||
|
@subscribe ipc, 'context-command', (command, args...) ->
|
||
|
$(atom.contextMenu.activeElement).trigger(command, args...)
|
||
|
|
||
|
@subscribe $(window), 'focus', -> document.body.classList.remove('is-blurred')
|
||
|
|
||
|
@subscribe $(window), 'blur', -> document.body.classList.add('is-blurred')
|
||
|
|
||
|
@subscribe $(window), 'beforeunload', =>
|
||
|
confirmed = atom.workspace?.confirmClose()
|
||
|
atom.hide() if confirmed and not @reloadRequested and atom.getCurrentWindow().isWebViewFocused()
|
||
|
@reloadRequested = false
|
||
|
|
||
|
atom.storeDefaultWindowDimensions()
|
||
|
atom.storeWindowDimensions()
|
||
|
atom.unloadEditorWindow() if confirmed
|
||
|
|
||
|
confirmed
|
||
|
|
||
|
@subscribe $(window), 'blur', -> atom.storeDefaultWindowDimensions()
|
||
|
|
||
|
@subscribe $(window), 'unload', -> atom.removeEditorWindow()
|
||
|
|
||
|
@subscribeToCommand $(window), 'window:toggle-full-screen', -> atom.toggleFullScreen()
|
||
|
|
||
|
@subscribeToCommand $(window), 'window:close', -> atom.close()
|
||
|
|
||
|
@subscribeToCommand $(window), 'window:reload', =>
|
||
|
@reloadRequested = true
|
||
|
atom.reload()
|
||
|
|
||
|
@subscribeToCommand $(window), 'window:toggle-dev-tools', -> atom.toggleDevTools()
|
||
|
|
||
|
if process.platform in ['win32', 'linux']
|
||
|
@subscribeToCommand $(window), 'window:toggle-menu-bar', ->
|
||
|
atom.config.set('core.autoHideMenuBar', !atom.config.get('core.autoHideMenuBar'))
|
||
|
|
||
|
@subscribeToCommand $(document), 'core:focus-next', @focusNext
|
||
|
|
||
|
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
|
||
|
|
||
|
document.addEventListener 'keydown', @onKeydown
|
||
|
|
||
|
document.addEventListener 'drop', @onDrop
|
||
|
@subscribe new Disposable =>
|
||
|
document.removeEventListener('drop', @onDrop)
|
||
|
|
||
|
document.addEventListener 'dragover', @onDragOver
|
||
|
@subscribe new Disposable =>
|
||
|
document.removeEventListener('dragover', @onDragOver)
|
||
|
|
||
|
@subscribe $(document), 'click', 'a', @openLink
|
||
|
|
||
|
# Prevent form submits from changing the current window's URL
|
||
|
@subscribe $(document), 'submit', 'form', (e) -> e.preventDefault()
|
||
|
|
||
|
@subscribe $(document), 'contextmenu', (e) ->
|
||
|
e.preventDefault()
|
||
|
atom.contextMenu.showForEvent(e)
|
||
|
|
||
|
@handleNativeKeybindings()
|
||
|
|
||
|
# Wire commands that should be handled by the native menu
|
||
|
# for elements with the `.native-key-bindings` class.
|
||
|
handleNativeKeybindings: ->
|
||
|
menu = null
|
||
|
bindCommandToAction = (command, action) =>
|
||
|
@subscribe $(document), command, (event) ->
|
||
|
if event.target.webkitMatchesSelector('.native-key-bindings, input')
|
||
|
menu ?= require('remote').require('menu')
|
||
|
menu.sendActionToFirstResponder(action)
|
||
|
true
|
||
|
|
||
|
bindCommandToAction('core:copy', 'copy:')
|
||
|
bindCommandToAction('core:cut', 'cut:')
|
||
|
bindCommandToAction('core:paste', 'paste:')
|
||
|
bindCommandToAction('core:undo', 'undo:')
|
||
|
bindCommandToAction('core:redo', 'redo:')
|
||
|
bindCommandToAction('core:select-all', 'selectAll:')
|
||
|
|
||
|
onKeydown: (event) ->
|
||
|
atom.keymaps.handleKeyboardEvent(event)
|
||
|
event.stopImmediatePropagation()
|
||
|
|
||
|
onDrop: (event) ->
|
||
|
event.preventDefault()
|
||
|
event.stopPropagation()
|
||
|
pathsToOpen = _.pluck(event.dataTransfer.files, 'path')
|
||
|
atom.open({pathsToOpen}) if pathsToOpen.length > 0
|
||
|
|
||
|
onDragOver: (event) ->
|
||
|
event.preventDefault()
|
||
|
event.stopPropagation()
|
||
|
|
||
|
openLink: ({target, currentTarget}) ->
|
||
|
location = target?.getAttribute('href') or currentTarget?.getAttribute('href')
|
||
|
if location?
|
||
|
schema = url.parse(location).protocol
|
||
|
# special handling for mailto
|
||
|
if schema? and schema in ['http:', 'https:', 'mailto:', 'tel:']
|
||
|
# should add test coverage to this, need to discuss which
|
||
|
# protocols are allowable, add map(s) eventually...
|
||
|
shell.openExternal(location)
|
||
|
false
|
||
|
|
||
|
eachTabIndexedElement: (callback) ->
|
||
|
for element in $('[tabindex]')
|
||
|
element = $(element)
|
||
|
continue if element.isDisabled()
|
||
|
|
||
|
tabIndex = parseInt(element.attr('tabindex'))
|
||
|
continue unless tabIndex >= 0
|
||
|
|
||
|
callback(element, tabIndex)
|
||
|
|
||
|
focusNext: =>
|
||
|
focusedTabIndex = parseInt($(':focus').attr('tabindex')) or -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()
|
||
|
|
||
|
focusPrevious: =>
|
||
|
focusedTabIndex = parseInt($(':focus').attr('tabindex')) or 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()
|