desktop-capturer.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. 'use strict'
  2. const ipcMain = require('@electron/internal/browser/ipc-main-internal')
  3. const { desktopCapturer } = process.atomBinding('desktop_capturer')
  4. const deepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b)
  5. // A queue for holding all requests from renderer process.
  6. let requestsQueue = []
  7. const electronSources = 'ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES'
  8. const capturerResult = (id) => `ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_${id}`
  9. ipcMain.on(electronSources, (event, captureWindow, captureScreen, thumbnailSize, id) => {
  10. const request = {
  11. id,
  12. options: {
  13. captureWindow,
  14. captureScreen,
  15. thumbnailSize
  16. },
  17. webContents: event.sender
  18. }
  19. requestsQueue.push(request)
  20. if (requestsQueue.length === 1) {
  21. desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
  22. }
  23. // If the WebContents is destroyed before receiving result, just remove the
  24. // reference from requestsQueue to make the module not send the result to it.
  25. event.sender.once('destroyed', () => {
  26. request.webContents = null
  27. })
  28. })
  29. desktopCapturer.emit = (event, name, sources) => {
  30. // Receiving sources result from main process, now send them back to renderer.
  31. const handledRequest = requestsQueue.shift()
  32. const handledWebContents = handledRequest.webContents
  33. const unhandledRequestsQueue = []
  34. const result = sources.map(source => {
  35. return {
  36. id: source.id,
  37. name: source.name,
  38. thumbnail: source.thumbnail.toDataURL(),
  39. display_id: source.display_id
  40. }
  41. })
  42. if (handledWebContents) {
  43. handledWebContents._sendInternal(capturerResult(handledRequest.id), result)
  44. }
  45. // Check the queue to see whether there is another identical request & handle
  46. requestsQueue.forEach(request => {
  47. const webContents = request.webContents
  48. if (deepEqual(handledRequest.options, request.options)) {
  49. if (webContents) {
  50. webContents._sendInternal(capturerResult(request.id), result)
  51. }
  52. } else {
  53. unhandledRequestsQueue.push(request)
  54. }
  55. })
  56. requestsQueue = unhandledRequestsQueue
  57. // If the requestsQueue is not empty, start a new request handling.
  58. if (requestsQueue.length > 0) {
  59. const { captureWindow, captureScreen, thumbnailSize } = requestsQueue[0].options
  60. return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
  61. }
  62. }