├── .github ├── FUNDING.yml └── workflows │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── screenshots ├── Final.png ├── S1.png ├── S2.png ├── S3.png ├── S5.png ├── S6.png └── S7.png ├── src-start ├── README.md ├── index.html ├── main.js ├── package-lock.json ├── package.json ├── renderer.js └── style.css └── src ├── README.md ├── icons ├── close-k-10.png ├── close-k-12.png ├── close-k-15.png ├── close-k-20.png ├── close-k-24.png ├── close-k-30.png ├── close-w-10.png ├── close-w-12.png ├── close-w-15.png ├── close-w-20.png ├── close-w-24.png ├── close-w-30.png ├── max-k-10.png ├── max-k-12.png ├── max-k-15.png ├── max-k-20.png ├── max-k-24.png ├── max-k-30.png ├── max-w-10.png ├── max-w-12.png ├── max-w-15.png ├── max-w-20.png ├── max-w-24.png ├── max-w-30.png ├── min-k-10.png ├── min-k-12.png ├── min-k-15.png ├── min-k-20.png ├── min-k-24.png ├── min-k-30.png ├── min-w-10.png ├── min-w-12.png ├── min-w-15.png ├── min-w-20.png ├── min-w-24.png ├── min-w-30.png ├── restore-k-10.png ├── restore-k-12.png ├── restore-k-15.png ├── restore-k-20.png ├── restore-k-24.png ├── restore-k-30.png ├── restore-w-10.png ├── restore-w-12.png ├── restore-w-15.png ├── restore-w-20.png ├── restore-w-24.png └── restore-w-30.png ├── index.html ├── main.js ├── package-lock.json ├── package.json ├── renderer.js └── style.css /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['paypal.me/RonnieDutta'] 2 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 2 13 | 14 | steps: 15 | - name: Checkout repo 16 | uses: actions/checkout@v2.1.0 17 | 18 | # - name: Setup Node.js environment 19 | # uses: actions/setup-node@v1.4.1 20 | # with: 21 | # node-version: '10.x' 22 | 23 | - name: Check /src & /src-start packages match 24 | run: | 25 | diff -Z src/package.json src-start/package.json 26 | diff -Z src/package-lock.json src-start/package-lock.json 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ronnie Dutta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Electron seamless titlebar tutorial (Windows 10 style) 2 | 3 | A guide to creating a seamless Windows 10 title bar in your Electron app. 4 | 5 | ![Final] 6 | 7 | I was inspired by the way [Hyper terminal](https://hyper.is/) achieved a native look, and a tutorial by [Shawn Rakowski](https://github.com/srakowski) (no longer available, it seems). 8 | 9 | I'm going to start with a version of the [Electron quick start app](https://github.com/electron/electron-quick-start) - see the [`src-start` directory](/src-start) of this repo for the starting point of the tutorial, including installation instructions. 10 | 11 | (The full final source code is located in the [`src` directory](/src).) 12 | 13 | ## 1. Add some styles 14 | 15 | ![S1] 16 | 17 | First, I'm just going to add some basic styles to the quick start app make it look a bit better than some sort of web 1.0 site. Open/create the empty `style.css` and add the following: 18 | 19 | ```css 20 | * {margin: 0; padding: 0; border: 0; vertical-align: baseline;} 21 | html {box-sizing: border-box;} 22 | *, *:before, *:after {box-sizing: inherit;} 23 | html, body {height: 100%; margin: 0;} 24 | 25 | body { 26 | font-family: "Segoe UI", sans-serif; 27 | background: #1A2933; 28 | color: #FFF; 29 | } 30 | h1 {margin: 0 0 10px 0; font-weight: 600; line-height: 1.2;} 31 | p {margin-top: 10px; color: rgba(255,255,255,0.4);} 32 | ``` 33 | 34 | If there isn't already a link to it in the `` element of `index.html`, add one. 35 | 36 | ## 2. Make the window frameless 37 | 38 | ![S2] 39 | 40 | We're going to remove the standard Windows title bar and border. In `main.js`, modify the `new BrowserWindow()` line so it includes `frame: false`: 41 | 42 | ```javascript 43 | mainWindow = new BrowserWindow({ 44 | width: 800, 45 | height: 600, 46 | frame: false, 47 | backgroundColor: '#FFF', 48 | webPreferences: { 49 | nodeIntegration: true 50 | } 51 | }); 52 | ``` 53 | 54 | N.B. we have included `backgroundColor: '#FFF'` so that subpixel anti-aliasing is enabled ([see here for details](https://github.com/electron/electron/issues/6344#issuecomment-420371918)). `nodeIntegration` is enabled for the window controls JavaScript to work (which we will get to later). 55 | 56 | Tip: uncomment `mainWindow.webContents.openDevTools()` to open developer tools every time the app is run. 57 | 58 | If you run the app now, you'll see the title bar is gone. See the [docs](https://electronjs.org/docs/api/frameless-window) for more info on frameless windows. 59 | 60 | ## 3. Create a replacement title bar 61 | 62 | We're going to create our own title bar using HTML and CSS. Let's also put the rest of the app content in its own div: 63 | 64 | ```html 65 | 66 | 67 |
68 | 69 |
70 |

Hello World!

71 |

Lorem ipsum dolor sit amet...

72 |
73 | 74 | 77 | 78 | ``` 79 | 80 | The default title bar height in Windows is 32px. We want the titlebar fixed at the top of the DOM. I'm giving it a background colour temporarily so we can see where it is. I've also added a subtle 1px border to the window. We need to add 32px top margin to `#main`, and change the `overflow-y` for `#main` and `body` (`#main` is now replacing `body` as the scrolling content). 81 | 82 | ```css 83 | body { 84 | border: 1px solid #48545c; 85 | overflow-y: hidden; 86 | } 87 | 88 | #titlebar { 89 | display: block; 90 | position: fixed; 91 | height: 32px; 92 | width: calc(100% - 2px); /*Compensate for body 1px border*/ 93 | background: #254053; 94 | } 95 | 96 | #main { 97 | height: calc(100% - 32px); 98 | margin-top: 32px; 99 | padding: 20px; 100 | overflow-y: auto; 101 | } 102 | ``` 103 | 104 | ![S3] 105 | 106 | Tip: you can do ctrl+R to reload the app. 107 | 108 | ## 4. Make the title bar draggable 109 | 110 | You might notice our new titlebar isn't actually draggable. To fix this, we add a div to `#titlebar`: 111 | 112 | ```html 113 |
114 |
115 |
116 | ``` 117 | 118 | We need to give it a style of `-webkit-app-region: drag`. The reason we don't just add this style to `#titlebar` is that we also want the cursor to change to resize when we hover near the edge of the window at the top. If the whole title bar was draggable, this wouldn't happen. So we also add some padding to the non-draggable `#titlebar` element. 119 | 120 | ```css 121 | #titlebar { 122 | padding: 4px; 123 | } 124 | 125 | #titlebar #drag-region { 126 | width: 100%; 127 | height: 100%; 128 | -webkit-app-region: drag; 129 | } 130 | ``` 131 | 132 | If you reload now, you will be able to drag the window around again, and the window can be resized at the top. 133 | 134 | ## 5. Add window control buttons 135 | 136 | It's time to add the minimise, maximise, restore and close buttons. To do this, we'll need the icons. [A previous version of this tutorial](https://github.com/binaryfunt/electron-seamless-titlebar-tutorial/tree/v1.0.0#5-add-window-control-buttons) used the [Segoe MDL2 Assets](https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font) font for the icons. However, these have some issues, such as [high DPI display scaling](https://github.com/binaryfunt/electron-seamless-titlebar-tutorial/issues/11) and [lack of cross-platform compatibility](https://github.com/binaryfunt/electron-seamless-titlebar-tutorial/issues/1). 137 | 138 | To overcome these issues, I recreated the icons as PNGs for crisp viewing at display scaling factors from 100-350% (but only the predefined Windows 10 scaling values; for custom scaling values you will probably see some anti-aliasing blur/pixelation and may be better off using the old method or the [SVG approach](https://github.com/binaryfunt/electron-seamless-titlebar-tutorial/pull/13)). The icons are located in [`src/icons`](src/icons). Making use of the [`srcset` attribute](https://bitsofco.de/the-srcset-and-sizes-attributes/#thesrcsetattribute) of the ``, we can load the correct resolution icons for the user's display scaling factor/device pixel ratio. 139 | 140 | We'll put the buttons inside the `#drag-region` div 141 | 142 | ```html 143 |
144 |
145 |
146 | 147 |
148 | 149 |
150 | 151 |
152 | 153 |
154 | 155 |
156 | 157 |
158 | 159 |
160 | 161 |
162 | 163 |
164 |
165 |
166 | ``` 167 | 168 | The buttons are 46px wide & 32px high. We'll use [CSS grid](https://css-tricks.com/snippets/css/complete-guide-grid/) to overlap the maximise/restore buttons, and later use JavaScript to alternate between them. 169 | 170 | ```css 171 | #titlebar { 172 | color: #FFF; 173 | } 174 | 175 | #window-controls { 176 | display: grid; 177 | grid-template-columns: repeat(3, 46px); 178 | position: absolute; 179 | top: 0; 180 | right: 0; 181 | height: 100%; 182 | } 183 | 184 | #window-controls .button { 185 | grid-row: 1 / span 1; 186 | display: flex; 187 | justify-content: center; 188 | align-items: center; 189 | width: 100%; 190 | height: 100%; 191 | } 192 | #min-button { 193 | grid-column: 1; 194 | } 195 | #max-button, #restore-button { 196 | grid-column: 2; 197 | } 198 | #close-button { 199 | grid-column: 3; 200 | } 201 | ``` 202 | 203 | ![S5] 204 | 205 | For some reason, the PNG icons are not rendered at the correct 10 device independent pixels width/height for the scaling factors 150%, 200% or 300%, so we need to target those using a [media query](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) and the [`-webkit-device-pixel-ratio` feature](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/-webkit-device-pixel-ratio). 206 | 207 | ```css 208 | @media (-webkit-device-pixel-ratio: 1.5), (device-pixel-ratio: 1.5), 209 | (-webkit-device-pixel-ratio: 2), (device-pixel-ratio: 2), 210 | (-webkit-device-pixel-ratio: 3), (device-pixel-ratio: 3) { 211 | #window-controls .icon { 212 | width: 10px; 213 | height: 10px; 214 | } 215 | } 216 | ``` 217 | 218 | The feature `device-pixel-ratio` without the webkit prefix does not exist yet, but no harm in future-proofing. The reason we don't just give the width/height rule for all device pixel ratios is that this leads to fuzzy anti-aliasing for some of them. 219 | 220 | ## 6. Style the window control buttons 221 | 222 | First of all, the buttons shouldn't be part of the window drag region, so we'll exclude them. Also, we don't want to be able to select the icon images. We also need to add hover effects. The default Windows close button hover colour is `#E81123`. When active, the button becomes `#F1707A` and the icon becomes black, which can be achieved using [the invert filter](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/invert). Lastly, we'll hide the restore button by default (again, we'll implement switching between the maximise/restore buttons later). 223 | 224 | ```css 225 | #window-controls { 226 | -webkit-app-region: no-drag; 227 | } 228 | 229 | #window-controls .button { 230 | user-select: none; 231 | } 232 | #window-controls .button:hover { 233 | background: rgba(255,255,255,0.1); 234 | } 235 | #window-controls .button:active { 236 | background: rgba(255,255,255,0.2); 237 | } 238 | 239 | #close-button:hover { 240 | background: #E81123 !important; 241 | } 242 | #close-button:active { 243 | background: #F1707A !important; 244 | } 245 | #close-button:active .icon { 246 | filter: invert(1); 247 | } 248 | 249 | #restore-button { 250 | display: none !important; 251 | } 252 | ``` 253 | 254 | ![S6] 255 | 256 | ## 7. Add the window title 257 | 258 | There are lots of ways you could do this, depending on whether you wanted to add any buttons or file menus to the titlebar, and whether you wanted the title centered or to the left. 259 | 260 | ![S7] 261 | 262 | My way is to put it the left. Add this inside the `#drag-region` div, above the window controls: 263 | 264 | ```html 265 |
266 | Electron quick start 267 |
268 | ``` 269 | 270 | I've gone with grid, as you can change the template columns to suit whatever you decide to do. Here we have an auto width column and a 138px column (3 * 46px = 138px). The default Windows window title font size is 12px. The default margin/padding on the left of the title is 10px, but 2px is already taken up by `#titlebar`'s padding, so 8px of margin/padding is needed on the left. I've taken the precaution of hiding any overflowing text if the title happens to be very long. 271 | 272 | ```css 273 | #titlebar #drag-region { 274 | display: grid; 275 | grid-template-columns: auto 138px; 276 | } 277 | 278 | #window-title { 279 | grid-column: 1; 280 | display: flex; 281 | align-items: center; 282 | margin-left: 8px; 283 | overflow: hidden; 284 | font-family: "Segoe UI", sans-serif; 285 | font-size: 12px; 286 | } 287 | 288 | #window-title span { 289 | overflow: hidden; 290 | text-overflow: ellipsis; 291 | white-space: nowrap; 292 | line-height: 1.5; 293 | } 294 | ``` 295 | 296 | At this point, you can remove the background colour from `#titlebar` and admire your handiwork. 297 | 298 | ![Final] 299 | 300 | ## 8. Implement window controls functionality 301 | 302 | Now, open `renderer.js`. We're going to code the windows controls, which is part of a single BrowserWindow instance and so should be in `renderer.js` as opposed to `main.js` (according to my interpretation of [the docs](https://electronjs.org/docs/tutorial/application-architecture)). The code isn't too complex so here it is in its entirety: 303 | 304 | ```javascript 305 | const remote = require('electron').remote; 306 | 307 | const win = remote.getCurrentWindow(); /* Note this is different to the 308 | html global `window` variable */ 309 | 310 | // When document has loaded, initialise 311 | document.onreadystatechange = (event) => { 312 | if (document.readyState == "complete") { 313 | handleWindowControls(); 314 | } 315 | }; 316 | 317 | window.onbeforeunload = (event) => { 318 | /* If window is reloaded, remove win event listeners 319 | (DOM element listeners get auto garbage collected but not 320 | Electron win listeners as the win is not dereferenced unless closed) */ 321 | win.removeAllListeners(); 322 | } 323 | 324 | function handleWindowControls() { 325 | // Make minimise/maximise/restore/close buttons work when they are clicked 326 | document.getElementById('min-button').addEventListener("click", event => { 327 | win.minimize(); 328 | }); 329 | 330 | document.getElementById('max-button').addEventListener("click", event => { 331 | win.maximize(); 332 | }); 333 | 334 | document.getElementById('restore-button').addEventListener("click", event => { 335 | win.unmaximize(); 336 | }); 337 | 338 | document.getElementById('close-button').addEventListener("click", event => { 339 | win.close(); 340 | }); 341 | 342 | // Toggle maximise/restore buttons when maximisation/unmaximisation occurs 343 | toggleMaxRestoreButtons(); 344 | win.on('maximize', toggleMaxRestoreButtons); 345 | win.on('unmaximize', toggleMaxRestoreButtons); 346 | 347 | function toggleMaxRestoreButtons() { 348 | if (win.isMaximized()) { 349 | document.body.classList.add('maximized'); 350 | } else { 351 | document.body.classList.remove('maximized'); 352 | } 353 | } 354 | } 355 | ``` 356 | 357 | Note: there is a bug with window maximization in some Electron versions on Windows (see [#6](https://github.com/binaryfunt/electron-seamless-titlebar-tutorial/issues/6)). It seems to have been fixed as of Electron 8.2.1+. 358 | 359 | ## 9. Adding styling for when the window is maximized 360 | 361 | Now all there is to do is to add some CSS for when the window is in the maximized state. When the window is maximized we should be able to drag from the very top down to restore it, so we should remove the drag region padding and set its width to 100%. We also need to swap between the maximize and restore buttons. 362 | 363 | ```css 364 | .maximized #titlebar { 365 | width: 100%; 366 | padding: 0; 367 | } 368 | 369 | .maximized #window-title { 370 | margin-left: 12px; 371 | } 372 | 373 | .maximized #restore-button { 374 | display: flex !important; 375 | } 376 | 377 | .maximized #max-button { 378 | display: none; 379 | } 380 | ``` 381 | 382 | 383 | [Final]: screenshots/Final.png 384 | [S1]: screenshots/S1.png 385 | [S2]: screenshots/S2.png 386 | [S3]: screenshots/S3.png 387 | [S5]: screenshots/S5.png 388 | [S6]: screenshots/S6.png 389 | [S7]: screenshots/S7.png 390 | -------------------------------------------------------------------------------- /screenshots/Final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/Final.png -------------------------------------------------------------------------------- /screenshots/S1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/S1.png -------------------------------------------------------------------------------- /screenshots/S2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/S2.png -------------------------------------------------------------------------------- /screenshots/S3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/S3.png -------------------------------------------------------------------------------- /screenshots/S5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/S5.png -------------------------------------------------------------------------------- /screenshots/S6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/S6.png -------------------------------------------------------------------------------- /screenshots/S7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/screenshots/S7.png -------------------------------------------------------------------------------- /src-start/README.md: -------------------------------------------------------------------------------- 1 | ## Installation of example app (at tutorial starting point) 2 | 3 | (For the full final app, see the [`src` directory](/src)) 4 | 5 | Assuming you have [Node](https://nodejs.org/en/) installed, clone this repo and run `npm install` in the `src-start` directory. 6 | 7 | #### Command line: 8 | 9 | ``` 10 | git clone https://github.com/binaryfunt/electron-seamless-titlebar-tutorial.git 11 | 12 | cd electron-seamless-titlebar-tutorial/src-start 13 | 14 | npm install 15 | 16 | npm start 17 | ``` 18 | -------------------------------------------------------------------------------- /src-start/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World! 6 | 7 | 8 | 9 | 10 | 11 |

Hello World!

12 |

13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit nulla ut libero varius sollicitudin. Morbi suscipit pretium velit id dictum. Curabitur congue faucibus lorem vel placerat. Morbi id sapien ut leo tincidunt consectetur quis eu odio. Quisque aliquet, nisl eget dictum sodales, mauris sapien fringilla nisl, eget aucto urna libero sit amet lectus. Nam et semper diam. Quisque augue velit, vulputate sit amet nisl vel, accumsan euismod mauris. Suspendisse erat lectus, semper vel pulvinar vitae, condimentum in urna. Pellentesque habitant morbi tristique senectus et netus malesuada fames ac turpis egestas. Suspendisse ullamcorper felis risus, sed porta ligula vulputate a. Maecenas sapien dolor, eleifend a rhoncus placerat, laoreet ut augue. Curabitur quis auctor est, ut congue neque. 14 |

15 |

16 | Donec lobortis pellentesque magna, at aliquam sapien et egestas vel. Aenean ac arcu vitae nisi luctus iaculis nec nec tortor. In nunc dolor, tincidunt in tincidunt et, scelerisque at velit. Nulla auctor vulputate ex, eget tempus mauris rhoncus in. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque lectus ex, pharetra ut ornare non, mattis quis nunc. Nulla porta, nisl et ullamcorper pretium, eros sem porttitor tellus, eu tincidunt turpis mauris sed turpis. Sed a nulla est in lacus consequat consectetur. In vitae cursus orci. Nulla vehicula posuere mollis. Fusce eu ipsum at velit tincidunt bibendum non eu lorem. Mauris id augue sapien. Vestibulum posuere elit sit amet iaculis dictum. Vivamus suscipit maximus risus, id egestas ligula venenatis quis. Pellentesque lobortis sapien vitae nisi venenatis rutrum. Aenean lacus libero, aliquam vitae nisl vitae, eleifend fermentum nisi. Nulla non ante nec tortor venenatis fermentum id at justo. Maecenas faucibus aliquam nibh non auctor. 17 |

18 |

19 | Morbi cursus augue quis nulla tincidunt, ut vulputate libero semper. Nunc suscipit a purus vel bibendum. Nunc rhoncus ante eget elementum finibus. Nulla facilisi. Praesent sed eros rhoncus, molestie eros et, mollis mauris. Fusce non placerat lacus. Sed in iaculis orci, ut congue odio. In nec lacus feugiat, rutrum purus ut, efficitur nunc. Etiam eget augue sed dui ultricies porttitor in nec leo. Quisque dui leo, sollicitudin blandit molestie, posuere eu augue. Phasellus eget risus lobortis, ornare ex nec viverra sapien. Aliquam mi ipsum, eleifend ac odio eleifend, tristique tempus odio. Sed ac id tortor laoreet elementum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit nulla ut libero varius sollicitudin. 20 |

21 |

22 | Morbi cursus augue quis nulla tincidunt, ut vulputate libero semper. Nunc suscipit a purus vel bibendum. Nunc rhoncus ante eget elementum finibus. Nulla facilisi. Praesent sed eros rhoncus, molestie eros et, mollis mauris. Fusce non placerat lacus. Sed in iaculis orci, ut congue odio. In nec lacus feugiat, rutrum purus ut, efficitur nunc. Etiam eget augue sed dui ultricies porttitor in nec leo. Quisque dui leo, sollicitudin blandit molestie, posuere eu augue. Phasellus eget risus lobortis, ornare ex nec viverra sapien. Aliquam mi ipsum, eleifend ac odio eleifend, tristique tempus odio. Sed ac id tortor laoreet elementum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit nulla ut libero varius sollicitudin. 23 |

24 | 25 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src-start/main.js: -------------------------------------------------------------------------------- 1 | // Modules to control application life and create native browser window 2 | const {app, BrowserWindow} = require('electron'); 3 | 4 | // Keep a global reference of the window object, if you don't, the window will 5 | // be closed automatically when the JavaScript object is garbage collected. 6 | let mainWindow; 7 | 8 | function createWindow () { 9 | // Create the browser window. 10 | mainWindow = new BrowserWindow({ 11 | width: 800, 12 | height: 600, 13 | backgroundColor: '#FFF', 14 | webPreferences: { 15 | nodeIntegration: true 16 | } 17 | }); 18 | 19 | // and load the index.html of the app. 20 | mainWindow.loadFile('index.html'); 21 | 22 | // Open the DevTools. 23 | // mainWindow.webContents.openDevTools(); 24 | 25 | // Emitted when the window is closed. 26 | mainWindow.on('closed', () => { 27 | // Dereference the window object, usually you would store windows 28 | // in an array if your app supports multi windows, this is the time 29 | // when you should delete the corresponding element. 30 | mainWindow = null; 31 | }); 32 | } 33 | 34 | // This method will be called when Electron has finished 35 | // initialization and is ready to create browser windows. 36 | // Some APIs can only be used after this event occurs. 37 | app.on('ready', createWindow); 38 | 39 | // Quit when all windows are closed. 40 | app.on('window-all-closed', function () { 41 | // On macOS it is common for applications and their menu bar 42 | // to stay active until the user quits explicitly with Cmd + Q 43 | if (process.platform !== 'darwin') { 44 | app.quit(); 45 | } 46 | }); 47 | 48 | app.on('activate', function () { 49 | // On macOS it's common to re-create a window in the app when the 50 | // dock icon is clicked and there are no other windows open. 51 | if (mainWindow === null) { 52 | createWindow(); 53 | } 54 | }); 55 | 56 | // In this file you can include the rest of your app's specific main process 57 | // code. You can also put them in separate files and require them here. 58 | -------------------------------------------------------------------------------- /src-start/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-seamless-titlebar-tutorial", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@electron/get": { 8 | "version": "1.12.3", 9 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.3.tgz", 10 | "integrity": "sha512-NFwSnVZQK7dhOYF1NQCt+HGqgL1aNdj0LUSx75uCqnZJqyiWCVdAMFV4b4/kC8HjUJAnsvdSEmjEt4G2qNQ9+Q==", 11 | "dev": true, 12 | "requires": { 13 | "debug": "^4.1.1", 14 | "env-paths": "^2.2.0", 15 | "filenamify": "^4.1.0", 16 | "fs-extra": "^8.1.0", 17 | "global-agent": "^2.0.2", 18 | "global-tunnel-ng": "^2.7.1", 19 | "got": "^9.6.0", 20 | "progress": "^2.0.3", 21 | "semver": "^6.2.0", 22 | "sumchecker": "^3.0.1" 23 | } 24 | }, 25 | "@sindresorhus/is": { 26 | "version": "0.14.0", 27 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 28 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 29 | "dev": true 30 | }, 31 | "@szmarczak/http-timer": { 32 | "version": "1.1.2", 33 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 34 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 35 | "dev": true, 36 | "requires": { 37 | "defer-to-connect": "^1.0.1" 38 | } 39 | }, 40 | "@types/node": { 41 | "version": "12.19.15", 42 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", 43 | "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==", 44 | "dev": true 45 | }, 46 | "boolean": { 47 | "version": "3.0.2", 48 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz", 49 | "integrity": "sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==", 50 | "dev": true, 51 | "optional": true 52 | }, 53 | "buffer-crc32": { 54 | "version": "0.2.13", 55 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 56 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 57 | "dev": true 58 | }, 59 | "buffer-from": { 60 | "version": "1.1.1", 61 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 62 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 63 | "dev": true 64 | }, 65 | "cacheable-request": { 66 | "version": "6.1.0", 67 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 68 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 69 | "dev": true, 70 | "requires": { 71 | "clone-response": "^1.0.2", 72 | "get-stream": "^5.1.0", 73 | "http-cache-semantics": "^4.0.0", 74 | "keyv": "^3.0.0", 75 | "lowercase-keys": "^2.0.0", 76 | "normalize-url": "^4.1.0", 77 | "responselike": "^1.0.2" 78 | }, 79 | "dependencies": { 80 | "get-stream": { 81 | "version": "5.2.0", 82 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 83 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 84 | "dev": true, 85 | "requires": { 86 | "pump": "^3.0.0" 87 | } 88 | }, 89 | "lowercase-keys": { 90 | "version": "2.0.0", 91 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 92 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 93 | "dev": true 94 | } 95 | } 96 | }, 97 | "clone-response": { 98 | "version": "1.0.2", 99 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 100 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 101 | "dev": true, 102 | "requires": { 103 | "mimic-response": "^1.0.0" 104 | } 105 | }, 106 | "concat-stream": { 107 | "version": "1.6.2", 108 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 109 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 110 | "dev": true, 111 | "requires": { 112 | "buffer-from": "^1.0.0", 113 | "inherits": "^2.0.3", 114 | "readable-stream": "^2.2.2", 115 | "typedarray": "^0.0.6" 116 | } 117 | }, 118 | "config-chain": { 119 | "version": "1.1.12", 120 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", 121 | "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", 122 | "dev": true, 123 | "optional": true, 124 | "requires": { 125 | "ini": "^1.3.4", 126 | "proto-list": "~1.2.1" 127 | } 128 | }, 129 | "core-js": { 130 | "version": "3.8.3", 131 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", 132 | "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==", 133 | "dev": true, 134 | "optional": true 135 | }, 136 | "core-util-is": { 137 | "version": "1.0.2", 138 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 139 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 140 | "dev": true 141 | }, 142 | "debug": { 143 | "version": "4.3.1", 144 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 145 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 146 | "dev": true, 147 | "requires": { 148 | "ms": "2.1.2" 149 | } 150 | }, 151 | "decompress-response": { 152 | "version": "3.3.0", 153 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 154 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 155 | "dev": true, 156 | "requires": { 157 | "mimic-response": "^1.0.0" 158 | } 159 | }, 160 | "defer-to-connect": { 161 | "version": "1.1.3", 162 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 163 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 164 | "dev": true 165 | }, 166 | "define-properties": { 167 | "version": "1.1.3", 168 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 169 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 170 | "dev": true, 171 | "optional": true, 172 | "requires": { 173 | "object-keys": "^1.0.12" 174 | } 175 | }, 176 | "detect-node": { 177 | "version": "2.0.4", 178 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", 179 | "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", 180 | "dev": true, 181 | "optional": true 182 | }, 183 | "duplexer3": { 184 | "version": "0.1.4", 185 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 186 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 187 | "dev": true 188 | }, 189 | "electron": { 190 | "version": "9.4.0", 191 | "resolved": "https://registry.npmjs.org/electron/-/electron-9.4.0.tgz", 192 | "integrity": "sha512-hOC4q0jkb+UDYZRy8vrZ1IANnq+jznZnbkD62OEo06nU+hIbp2IrwDRBNuSLmQ3cwZMVir0WSIA1qEVK0PkzGA==", 193 | "dev": true, 194 | "requires": { 195 | "@electron/get": "^1.0.1", 196 | "@types/node": "^12.0.12", 197 | "extract-zip": "^1.0.3" 198 | } 199 | }, 200 | "encodeurl": { 201 | "version": "1.0.2", 202 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 203 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 204 | "dev": true, 205 | "optional": true 206 | }, 207 | "end-of-stream": { 208 | "version": "1.4.4", 209 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 210 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 211 | "dev": true, 212 | "requires": { 213 | "once": "^1.4.0" 214 | } 215 | }, 216 | "env-paths": { 217 | "version": "2.2.0", 218 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", 219 | "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", 220 | "dev": true 221 | }, 222 | "es6-error": { 223 | "version": "4.1.1", 224 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 225 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 226 | "dev": true, 227 | "optional": true 228 | }, 229 | "escape-string-regexp": { 230 | "version": "1.0.5", 231 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 232 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 233 | "dev": true 234 | }, 235 | "extract-zip": { 236 | "version": "1.7.0", 237 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", 238 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", 239 | "dev": true, 240 | "requires": { 241 | "concat-stream": "^1.6.2", 242 | "debug": "^2.6.9", 243 | "mkdirp": "^0.5.4", 244 | "yauzl": "^2.10.0" 245 | }, 246 | "dependencies": { 247 | "debug": { 248 | "version": "2.6.9", 249 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 250 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 251 | "dev": true, 252 | "requires": { 253 | "ms": "2.0.0" 254 | } 255 | }, 256 | "ms": { 257 | "version": "2.0.0", 258 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 259 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 260 | "dev": true 261 | } 262 | } 263 | }, 264 | "fd-slicer": { 265 | "version": "1.1.0", 266 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 267 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 268 | "dev": true, 269 | "requires": { 270 | "pend": "~1.2.0" 271 | } 272 | }, 273 | "filename-reserved-regex": { 274 | "version": "2.0.0", 275 | "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", 276 | "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", 277 | "dev": true 278 | }, 279 | "filenamify": { 280 | "version": "4.2.0", 281 | "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.2.0.tgz", 282 | "integrity": "sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==", 283 | "dev": true, 284 | "requires": { 285 | "filename-reserved-regex": "^2.0.0", 286 | "strip-outer": "^1.0.1", 287 | "trim-repeated": "^1.0.0" 288 | } 289 | }, 290 | "fs-extra": { 291 | "version": "8.1.0", 292 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 293 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 294 | "dev": true, 295 | "requires": { 296 | "graceful-fs": "^4.2.0", 297 | "jsonfile": "^4.0.0", 298 | "universalify": "^0.1.0" 299 | } 300 | }, 301 | "get-stream": { 302 | "version": "4.1.0", 303 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 304 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 305 | "dev": true, 306 | "requires": { 307 | "pump": "^3.0.0" 308 | } 309 | }, 310 | "global-agent": { 311 | "version": "2.1.12", 312 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz", 313 | "integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==", 314 | "dev": true, 315 | "optional": true, 316 | "requires": { 317 | "boolean": "^3.0.1", 318 | "core-js": "^3.6.5", 319 | "es6-error": "^4.1.1", 320 | "matcher": "^3.0.0", 321 | "roarr": "^2.15.3", 322 | "semver": "^7.3.2", 323 | "serialize-error": "^7.0.1" 324 | }, 325 | "dependencies": { 326 | "semver": { 327 | "version": "7.3.4", 328 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 329 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 330 | "dev": true, 331 | "optional": true, 332 | "requires": { 333 | "lru-cache": "^6.0.0" 334 | } 335 | } 336 | } 337 | }, 338 | "global-tunnel-ng": { 339 | "version": "2.7.1", 340 | "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", 341 | "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", 342 | "dev": true, 343 | "optional": true, 344 | "requires": { 345 | "encodeurl": "^1.0.2", 346 | "lodash": "^4.17.10", 347 | "npm-conf": "^1.1.3", 348 | "tunnel": "^0.0.6" 349 | } 350 | }, 351 | "globalthis": { 352 | "version": "1.0.1", 353 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", 354 | "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", 355 | "dev": true, 356 | "optional": true, 357 | "requires": { 358 | "define-properties": "^1.1.3" 359 | } 360 | }, 361 | "got": { 362 | "version": "9.6.0", 363 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 364 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 365 | "dev": true, 366 | "requires": { 367 | "@sindresorhus/is": "^0.14.0", 368 | "@szmarczak/http-timer": "^1.1.2", 369 | "cacheable-request": "^6.0.0", 370 | "decompress-response": "^3.3.0", 371 | "duplexer3": "^0.1.4", 372 | "get-stream": "^4.1.0", 373 | "lowercase-keys": "^1.0.1", 374 | "mimic-response": "^1.0.1", 375 | "p-cancelable": "^1.0.0", 376 | "to-readable-stream": "^1.0.0", 377 | "url-parse-lax": "^3.0.0" 378 | } 379 | }, 380 | "graceful-fs": { 381 | "version": "4.2.4", 382 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 383 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 384 | "dev": true 385 | }, 386 | "http-cache-semantics": { 387 | "version": "4.1.0", 388 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 389 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 390 | "dev": true 391 | }, 392 | "inherits": { 393 | "version": "2.0.4", 394 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 395 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 396 | "dev": true 397 | }, 398 | "ini": { 399 | "version": "1.3.8", 400 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 401 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 402 | "dev": true, 403 | "optional": true 404 | }, 405 | "isarray": { 406 | "version": "1.0.0", 407 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 408 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 409 | "dev": true 410 | }, 411 | "json-buffer": { 412 | "version": "3.0.0", 413 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 414 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 415 | "dev": true 416 | }, 417 | "json-stringify-safe": { 418 | "version": "5.0.1", 419 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 420 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 421 | "dev": true, 422 | "optional": true 423 | }, 424 | "jsonfile": { 425 | "version": "4.0.0", 426 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 427 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 428 | "dev": true, 429 | "requires": { 430 | "graceful-fs": "^4.1.6" 431 | } 432 | }, 433 | "keyv": { 434 | "version": "3.1.0", 435 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 436 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 437 | "dev": true, 438 | "requires": { 439 | "json-buffer": "3.0.0" 440 | } 441 | }, 442 | "lodash": { 443 | "version": "4.17.21", 444 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 445 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 446 | "dev": true, 447 | "optional": true 448 | }, 449 | "lowercase-keys": { 450 | "version": "1.0.1", 451 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 452 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 453 | "dev": true 454 | }, 455 | "lru-cache": { 456 | "version": "6.0.0", 457 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 458 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 459 | "dev": true, 460 | "optional": true, 461 | "requires": { 462 | "yallist": "^4.0.0" 463 | } 464 | }, 465 | "matcher": { 466 | "version": "3.0.0", 467 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 468 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 469 | "dev": true, 470 | "optional": true, 471 | "requires": { 472 | "escape-string-regexp": "^4.0.0" 473 | }, 474 | "dependencies": { 475 | "escape-string-regexp": { 476 | "version": "4.0.0", 477 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 478 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 479 | "dev": true, 480 | "optional": true 481 | } 482 | } 483 | }, 484 | "mimic-response": { 485 | "version": "1.0.1", 486 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 487 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 488 | "dev": true 489 | }, 490 | "minimist": { 491 | "version": "1.2.5", 492 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 493 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 494 | "dev": true 495 | }, 496 | "mkdirp": { 497 | "version": "0.5.5", 498 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 499 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 500 | "dev": true, 501 | "requires": { 502 | "minimist": "^1.2.5" 503 | } 504 | }, 505 | "ms": { 506 | "version": "2.1.2", 507 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 508 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 509 | "dev": true 510 | }, 511 | "normalize-url": { 512 | "version": "4.5.1", 513 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", 514 | "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", 515 | "dev": true 516 | }, 517 | "npm-conf": { 518 | "version": "1.1.3", 519 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", 520 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", 521 | "dev": true, 522 | "optional": true, 523 | "requires": { 524 | "config-chain": "^1.1.11", 525 | "pify": "^3.0.0" 526 | } 527 | }, 528 | "object-keys": { 529 | "version": "1.1.1", 530 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 531 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 532 | "dev": true, 533 | "optional": true 534 | }, 535 | "once": { 536 | "version": "1.4.0", 537 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 538 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 539 | "dev": true, 540 | "requires": { 541 | "wrappy": "1" 542 | } 543 | }, 544 | "p-cancelable": { 545 | "version": "1.1.0", 546 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 547 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 548 | "dev": true 549 | }, 550 | "pend": { 551 | "version": "1.2.0", 552 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 553 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 554 | "dev": true 555 | }, 556 | "pify": { 557 | "version": "3.0.0", 558 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 559 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 560 | "dev": true, 561 | "optional": true 562 | }, 563 | "prepend-http": { 564 | "version": "2.0.0", 565 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 566 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 567 | "dev": true 568 | }, 569 | "process-nextick-args": { 570 | "version": "2.0.1", 571 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 572 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 573 | "dev": true 574 | }, 575 | "progress": { 576 | "version": "2.0.3", 577 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 578 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 579 | "dev": true 580 | }, 581 | "proto-list": { 582 | "version": "1.2.4", 583 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 584 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", 585 | "dev": true, 586 | "optional": true 587 | }, 588 | "pump": { 589 | "version": "3.0.0", 590 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 591 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 592 | "dev": true, 593 | "requires": { 594 | "end-of-stream": "^1.1.0", 595 | "once": "^1.3.1" 596 | } 597 | }, 598 | "readable-stream": { 599 | "version": "2.3.7", 600 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 601 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 602 | "dev": true, 603 | "requires": { 604 | "core-util-is": "~1.0.0", 605 | "inherits": "~2.0.3", 606 | "isarray": "~1.0.0", 607 | "process-nextick-args": "~2.0.0", 608 | "safe-buffer": "~5.1.1", 609 | "string_decoder": "~1.1.1", 610 | "util-deprecate": "~1.0.1" 611 | } 612 | }, 613 | "responselike": { 614 | "version": "1.0.2", 615 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 616 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 617 | "dev": true, 618 | "requires": { 619 | "lowercase-keys": "^1.0.0" 620 | } 621 | }, 622 | "roarr": { 623 | "version": "2.15.4", 624 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", 625 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", 626 | "dev": true, 627 | "optional": true, 628 | "requires": { 629 | "boolean": "^3.0.1", 630 | "detect-node": "^2.0.4", 631 | "globalthis": "^1.0.1", 632 | "json-stringify-safe": "^5.0.1", 633 | "semver-compare": "^1.0.0", 634 | "sprintf-js": "^1.1.2" 635 | } 636 | }, 637 | "safe-buffer": { 638 | "version": "5.1.2", 639 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 640 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 641 | "dev": true 642 | }, 643 | "semver": { 644 | "version": "6.3.0", 645 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 646 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 647 | "dev": true 648 | }, 649 | "semver-compare": { 650 | "version": "1.0.0", 651 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 652 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", 653 | "dev": true, 654 | "optional": true 655 | }, 656 | "serialize-error": { 657 | "version": "7.0.1", 658 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", 659 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", 660 | "dev": true, 661 | "optional": true, 662 | "requires": { 663 | "type-fest": "^0.13.1" 664 | } 665 | }, 666 | "sprintf-js": { 667 | "version": "1.1.2", 668 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 669 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", 670 | "dev": true, 671 | "optional": true 672 | }, 673 | "string_decoder": { 674 | "version": "1.1.1", 675 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 676 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 677 | "dev": true, 678 | "requires": { 679 | "safe-buffer": "~5.1.0" 680 | } 681 | }, 682 | "strip-outer": { 683 | "version": "1.0.1", 684 | "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", 685 | "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", 686 | "dev": true, 687 | "requires": { 688 | "escape-string-regexp": "^1.0.2" 689 | } 690 | }, 691 | "sumchecker": { 692 | "version": "3.0.1", 693 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", 694 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", 695 | "dev": true, 696 | "requires": { 697 | "debug": "^4.1.0" 698 | } 699 | }, 700 | "to-readable-stream": { 701 | "version": "1.0.0", 702 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 703 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 704 | "dev": true 705 | }, 706 | "trim-repeated": { 707 | "version": "1.0.0", 708 | "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", 709 | "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", 710 | "dev": true, 711 | "requires": { 712 | "escape-string-regexp": "^1.0.2" 713 | } 714 | }, 715 | "tunnel": { 716 | "version": "0.0.6", 717 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 718 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 719 | "dev": true, 720 | "optional": true 721 | }, 722 | "type-fest": { 723 | "version": "0.13.1", 724 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 725 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", 726 | "dev": true, 727 | "optional": true 728 | }, 729 | "typedarray": { 730 | "version": "0.0.6", 731 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 732 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 733 | "dev": true 734 | }, 735 | "universalify": { 736 | "version": "0.1.2", 737 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 738 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 739 | "dev": true 740 | }, 741 | "url-parse-lax": { 742 | "version": "3.0.0", 743 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 744 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 745 | "dev": true, 746 | "requires": { 747 | "prepend-http": "^2.0.0" 748 | } 749 | }, 750 | "util-deprecate": { 751 | "version": "1.0.2", 752 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 753 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 754 | "dev": true 755 | }, 756 | "wrappy": { 757 | "version": "1.0.2", 758 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 759 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 760 | "dev": true 761 | }, 762 | "yallist": { 763 | "version": "4.0.0", 764 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 765 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 766 | "dev": true, 767 | "optional": true 768 | }, 769 | "yauzl": { 770 | "version": "2.10.0", 771 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 772 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 773 | "dev": true, 774 | "requires": { 775 | "buffer-crc32": "~0.2.3", 776 | "fd-slicer": "~1.1.0" 777 | } 778 | } 779 | } 780 | } 781 | -------------------------------------------------------------------------------- /src-start/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-seamless-titlebar-tutorial", 3 | "version": "1.0.0", 4 | "description": "A minimal Electron application", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "electron ." 8 | }, 9 | "repository": "https://github.com/binaryfunt/electron-seamless-titlebar-tutorial", 10 | "author": "binaryfunt", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "electron": "^9.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src-start/renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // All of the Node.js APIs are available in this process. 4 | -------------------------------------------------------------------------------- /src-start/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src-start/style.css -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | ## Installation of complete example app 2 | 3 | (For the tutorial starting point app, see the [`src-start` directory](/src-start)) 4 | 5 | Assuming you have [Node](https://nodejs.org/en/) installed, clone this repo and run `npm install` in the `src` directory. 6 | 7 | #### Command line: 8 | 9 | ``` 10 | git clone https://github.com/binaryfunt/electron-seamless-titlebar-tutorial.git 11 | 12 | cd electron-seamless-titlebar-tutorial/src 13 | 14 | npm install 15 | 16 | npm start 17 | ``` 18 | -------------------------------------------------------------------------------- /src/icons/close-k-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-k-10.png -------------------------------------------------------------------------------- /src/icons/close-k-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-k-12.png -------------------------------------------------------------------------------- /src/icons/close-k-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-k-15.png -------------------------------------------------------------------------------- /src/icons/close-k-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-k-20.png -------------------------------------------------------------------------------- /src/icons/close-k-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-k-24.png -------------------------------------------------------------------------------- /src/icons/close-k-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-k-30.png -------------------------------------------------------------------------------- /src/icons/close-w-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-w-10.png -------------------------------------------------------------------------------- /src/icons/close-w-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-w-12.png -------------------------------------------------------------------------------- /src/icons/close-w-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-w-15.png -------------------------------------------------------------------------------- /src/icons/close-w-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-w-20.png -------------------------------------------------------------------------------- /src/icons/close-w-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-w-24.png -------------------------------------------------------------------------------- /src/icons/close-w-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/close-w-30.png -------------------------------------------------------------------------------- /src/icons/max-k-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-k-10.png -------------------------------------------------------------------------------- /src/icons/max-k-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-k-12.png -------------------------------------------------------------------------------- /src/icons/max-k-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-k-15.png -------------------------------------------------------------------------------- /src/icons/max-k-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-k-20.png -------------------------------------------------------------------------------- /src/icons/max-k-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-k-24.png -------------------------------------------------------------------------------- /src/icons/max-k-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-k-30.png -------------------------------------------------------------------------------- /src/icons/max-w-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-w-10.png -------------------------------------------------------------------------------- /src/icons/max-w-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-w-12.png -------------------------------------------------------------------------------- /src/icons/max-w-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-w-15.png -------------------------------------------------------------------------------- /src/icons/max-w-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-w-20.png -------------------------------------------------------------------------------- /src/icons/max-w-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-w-24.png -------------------------------------------------------------------------------- /src/icons/max-w-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/max-w-30.png -------------------------------------------------------------------------------- /src/icons/min-k-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-k-10.png -------------------------------------------------------------------------------- /src/icons/min-k-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-k-12.png -------------------------------------------------------------------------------- /src/icons/min-k-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-k-15.png -------------------------------------------------------------------------------- /src/icons/min-k-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-k-20.png -------------------------------------------------------------------------------- /src/icons/min-k-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-k-24.png -------------------------------------------------------------------------------- /src/icons/min-k-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-k-30.png -------------------------------------------------------------------------------- /src/icons/min-w-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-w-10.png -------------------------------------------------------------------------------- /src/icons/min-w-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-w-12.png -------------------------------------------------------------------------------- /src/icons/min-w-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-w-15.png -------------------------------------------------------------------------------- /src/icons/min-w-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-w-20.png -------------------------------------------------------------------------------- /src/icons/min-w-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-w-24.png -------------------------------------------------------------------------------- /src/icons/min-w-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/min-w-30.png -------------------------------------------------------------------------------- /src/icons/restore-k-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-k-10.png -------------------------------------------------------------------------------- /src/icons/restore-k-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-k-12.png -------------------------------------------------------------------------------- /src/icons/restore-k-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-k-15.png -------------------------------------------------------------------------------- /src/icons/restore-k-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-k-20.png -------------------------------------------------------------------------------- /src/icons/restore-k-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-k-24.png -------------------------------------------------------------------------------- /src/icons/restore-k-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-k-30.png -------------------------------------------------------------------------------- /src/icons/restore-w-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-w-10.png -------------------------------------------------------------------------------- /src/icons/restore-w-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-w-12.png -------------------------------------------------------------------------------- /src/icons/restore-w-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-w-15.png -------------------------------------------------------------------------------- /src/icons/restore-w-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-w-20.png -------------------------------------------------------------------------------- /src/icons/restore-w-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-w-24.png -------------------------------------------------------------------------------- /src/icons/restore-w-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfunt/electron-seamless-titlebar-tutorial/d41ed9affbc194c145c615be5101968b8a868af7/src/icons/restore-w-30.png -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World! 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 |
15 | Electron quick start 16 |
17 | 18 |
19 | 20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 | 33 |
34 |
35 |
36 | 37 |
38 |

Hello World!

39 |

40 | Electron version: 41 |

42 |

43 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit nulla ut libero varius sollicitudin. Morbi suscipit pretium velit id dictum. Curabitur congue faucibus lorem vel placerat. Morbi id sapien ut leo tincidunt consectetur quis eu odio. Quisque aliquet, nisl eget dictum sodales, mauris sapien fringilla nisl, eget aucto urna libero sit amet lectus. Nam et semper diam. Quisque augue velit, vulputate sit amet nisl vel, accumsan euismod mauris. Suspendisse erat lectus, semper vel pulvinar vitae, condimentum in urna. Pellentesque habitant morbi tristique senectus et netus malesuada fames ac turpis egestas. Suspendisse ullamcorper felis risus, sed porta ligula vulputate a. Maecenas sapien dolor, eleifend a rhoncus placerat, laoreet ut augue. Curabitur quis auctor est, ut congue neque. 44 |

45 |

46 | Donec lobortis pellentesque magna, at aliquam sapien et egestas vel. Aenean ac arcu vitae nisi luctus iaculis nec nec tortor. In nunc dolor, tincidunt in tincidunt et, scelerisque at velit. Nulla auctor vulputate ex, eget tempus mauris rhoncus in. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque lectus ex, pharetra ut ornare non, mattis quis nunc. Nulla porta, nisl et ullamcorper pretium, eros sem porttitor tellus, eu tincidunt turpis mauris sed turpis. Sed a nulla est in lacus consequat consectetur. In vitae cursus orci. Nulla vehicula posuere mollis. Fusce eu ipsum at velit tincidunt bibendum non eu lorem. Mauris id augue sapien. Vestibulum posuere elit sit amet iaculis dictum. Vivamus suscipit maximus risus, id egestas ligula venenatis quis. Pellentesque lobortis sapien vitae nisi venenatis rutrum. Aenean lacus libero, aliquam vitae nisl vitae, eleifend fermentum nisi. Nulla non ante nec tortor venenatis fermentum id at justo. Maecenas faucibus aliquam nibh non auctor. 47 |

48 |

49 | Morbi cursus augue quis nulla tincidunt, ut vulputate libero semper. Nunc suscipit a purus vel bibendum. Nunc rhoncus ante eget elementum finibus. Nulla facilisi. Praesent sed eros rhoncus, molestie eros et, mollis mauris. Fusce non placerat lacus. Sed in iaculis orci, ut congue odio. In nec lacus feugiat, rutrum purus ut, efficitur nunc. Etiam eget augue sed dui ultricies porttitor in nec leo. Quisque dui leo, sollicitudin blandit molestie, posuere eu augue. Phasellus eget risus lobortis, ornare ex nec viverra sapien. Aliquam mi ipsum, eleifend ac odio eleifend, tristique tempus odio. Sed ac id tortor laoreet elementum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit nulla ut libero varius sollicitudin. 50 |

51 |

52 | Morbi cursus augue quis nulla tincidunt, ut vulputate libero semper. Nunc suscipit a purus vel bibendum. Nunc rhoncus ante eget elementum finibus. Nulla facilisi. Praesent sed eros rhoncus, molestie eros et, mollis mauris. Fusce non placerat lacus. Sed in iaculis orci, ut congue odio. In nec lacus feugiat, rutrum purus ut, efficitur nunc. Etiam eget augue sed dui ultricies porttitor in nec leo. Quisque dui leo, sollicitudin blandit molestie, posuere eu augue. Phasellus eget risus lobortis, ornare ex nec viverra sapien. Aliquam mi ipsum, eleifend ac odio eleifend, tristique tempus odio. Sed ac id tortor laoreet elementum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit nulla ut libero varius sollicitudin. 53 |

54 |
55 | 56 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // Modules to control application life and create native browser window 2 | const {app, BrowserWindow} = require('electron'); 3 | 4 | // Keep a global reference of the window object, if you don't, the window will 5 | // be closed automatically when the JavaScript object is garbage collected. 6 | let mainWindow; 7 | 8 | function createWindow () { 9 | // Create the browser window. 10 | mainWindow = new BrowserWindow({ 11 | width: 800, 12 | height: 600, 13 | frame: false, 14 | backgroundColor: '#FFF', 15 | webPreferences: { 16 | nodeIntegration: true 17 | } 18 | }); 19 | 20 | // and load the index.html of the app. 21 | mainWindow.loadFile('index.html'); 22 | 23 | // Open the DevTools. 24 | // mainWindow.webContents.openDevTools(); 25 | 26 | // Emitted when the window is closed. 27 | mainWindow.on('closed', () => { 28 | // Dereference the window object, usually you would store windows 29 | // in an array if your app supports multi windows, this is the time 30 | // when you should delete the corresponding element. 31 | mainWindow = null; 32 | }); 33 | } 34 | 35 | // This method will be called when Electron has finished 36 | // initialization and is ready to create browser windows. 37 | // Some APIs can only be used after this event occurs. 38 | app.on('ready', createWindow); 39 | 40 | // Quit when all windows are closed. 41 | app.on('window-all-closed', function () { 42 | // On macOS it is common for applications and their menu bar 43 | // to stay active until the user quits explicitly with Cmd + Q 44 | if (process.platform !== 'darwin') { 45 | app.quit(); 46 | } 47 | }); 48 | 49 | app.on('activate', function () { 50 | // On macOS it's common to re-create a window in the app when the 51 | // dock icon is clicked and there are no other windows open. 52 | if (mainWindow === null) { 53 | createWindow(); 54 | } 55 | }); 56 | 57 | // In this file you can include the rest of your app's specific main process 58 | // code. You can also put them in separate files and require them here. 59 | -------------------------------------------------------------------------------- /src/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-seamless-titlebar-tutorial", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@electron/get": { 8 | "version": "1.12.3", 9 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.3.tgz", 10 | "integrity": "sha512-NFwSnVZQK7dhOYF1NQCt+HGqgL1aNdj0LUSx75uCqnZJqyiWCVdAMFV4b4/kC8HjUJAnsvdSEmjEt4G2qNQ9+Q==", 11 | "dev": true, 12 | "requires": { 13 | "debug": "^4.1.1", 14 | "env-paths": "^2.2.0", 15 | "filenamify": "^4.1.0", 16 | "fs-extra": "^8.1.0", 17 | "global-agent": "^2.0.2", 18 | "global-tunnel-ng": "^2.7.1", 19 | "got": "^9.6.0", 20 | "progress": "^2.0.3", 21 | "semver": "^6.2.0", 22 | "sumchecker": "^3.0.1" 23 | } 24 | }, 25 | "@sindresorhus/is": { 26 | "version": "0.14.0", 27 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 28 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 29 | "dev": true 30 | }, 31 | "@szmarczak/http-timer": { 32 | "version": "1.1.2", 33 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 34 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 35 | "dev": true, 36 | "requires": { 37 | "defer-to-connect": "^1.0.1" 38 | } 39 | }, 40 | "@types/node": { 41 | "version": "12.19.15", 42 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", 43 | "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==", 44 | "dev": true 45 | }, 46 | "boolean": { 47 | "version": "3.0.2", 48 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz", 49 | "integrity": "sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==", 50 | "dev": true, 51 | "optional": true 52 | }, 53 | "buffer-crc32": { 54 | "version": "0.2.13", 55 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 56 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 57 | "dev": true 58 | }, 59 | "buffer-from": { 60 | "version": "1.1.1", 61 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 62 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 63 | "dev": true 64 | }, 65 | "cacheable-request": { 66 | "version": "6.1.0", 67 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 68 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 69 | "dev": true, 70 | "requires": { 71 | "clone-response": "^1.0.2", 72 | "get-stream": "^5.1.0", 73 | "http-cache-semantics": "^4.0.0", 74 | "keyv": "^3.0.0", 75 | "lowercase-keys": "^2.0.0", 76 | "normalize-url": "^4.1.0", 77 | "responselike": "^1.0.2" 78 | }, 79 | "dependencies": { 80 | "get-stream": { 81 | "version": "5.2.0", 82 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 83 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 84 | "dev": true, 85 | "requires": { 86 | "pump": "^3.0.0" 87 | } 88 | }, 89 | "lowercase-keys": { 90 | "version": "2.0.0", 91 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 92 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 93 | "dev": true 94 | } 95 | } 96 | }, 97 | "clone-response": { 98 | "version": "1.0.2", 99 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 100 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 101 | "dev": true, 102 | "requires": { 103 | "mimic-response": "^1.0.0" 104 | } 105 | }, 106 | "concat-stream": { 107 | "version": "1.6.2", 108 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 109 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 110 | "dev": true, 111 | "requires": { 112 | "buffer-from": "^1.0.0", 113 | "inherits": "^2.0.3", 114 | "readable-stream": "^2.2.2", 115 | "typedarray": "^0.0.6" 116 | } 117 | }, 118 | "config-chain": { 119 | "version": "1.1.12", 120 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", 121 | "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", 122 | "dev": true, 123 | "optional": true, 124 | "requires": { 125 | "ini": "^1.3.4", 126 | "proto-list": "~1.2.1" 127 | } 128 | }, 129 | "core-js": { 130 | "version": "3.8.3", 131 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", 132 | "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==", 133 | "dev": true, 134 | "optional": true 135 | }, 136 | "core-util-is": { 137 | "version": "1.0.2", 138 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 139 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 140 | "dev": true 141 | }, 142 | "debug": { 143 | "version": "4.3.1", 144 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 145 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 146 | "dev": true, 147 | "requires": { 148 | "ms": "2.1.2" 149 | } 150 | }, 151 | "decompress-response": { 152 | "version": "3.3.0", 153 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 154 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 155 | "dev": true, 156 | "requires": { 157 | "mimic-response": "^1.0.0" 158 | } 159 | }, 160 | "defer-to-connect": { 161 | "version": "1.1.3", 162 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 163 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 164 | "dev": true 165 | }, 166 | "define-properties": { 167 | "version": "1.1.3", 168 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 169 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 170 | "dev": true, 171 | "optional": true, 172 | "requires": { 173 | "object-keys": "^1.0.12" 174 | } 175 | }, 176 | "detect-node": { 177 | "version": "2.0.4", 178 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", 179 | "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", 180 | "dev": true, 181 | "optional": true 182 | }, 183 | "duplexer3": { 184 | "version": "0.1.4", 185 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 186 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 187 | "dev": true 188 | }, 189 | "electron": { 190 | "version": "9.4.0", 191 | "resolved": "https://registry.npmjs.org/electron/-/electron-9.4.0.tgz", 192 | "integrity": "sha512-hOC4q0jkb+UDYZRy8vrZ1IANnq+jznZnbkD62OEo06nU+hIbp2IrwDRBNuSLmQ3cwZMVir0WSIA1qEVK0PkzGA==", 193 | "dev": true, 194 | "requires": { 195 | "@electron/get": "^1.0.1", 196 | "@types/node": "^12.0.12", 197 | "extract-zip": "^1.0.3" 198 | } 199 | }, 200 | "encodeurl": { 201 | "version": "1.0.2", 202 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 203 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 204 | "dev": true, 205 | "optional": true 206 | }, 207 | "end-of-stream": { 208 | "version": "1.4.4", 209 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 210 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 211 | "dev": true, 212 | "requires": { 213 | "once": "^1.4.0" 214 | } 215 | }, 216 | "env-paths": { 217 | "version": "2.2.0", 218 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", 219 | "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", 220 | "dev": true 221 | }, 222 | "es6-error": { 223 | "version": "4.1.1", 224 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 225 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 226 | "dev": true, 227 | "optional": true 228 | }, 229 | "escape-string-regexp": { 230 | "version": "1.0.5", 231 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 232 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 233 | "dev": true 234 | }, 235 | "extract-zip": { 236 | "version": "1.7.0", 237 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", 238 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", 239 | "dev": true, 240 | "requires": { 241 | "concat-stream": "^1.6.2", 242 | "debug": "^2.6.9", 243 | "mkdirp": "^0.5.4", 244 | "yauzl": "^2.10.0" 245 | }, 246 | "dependencies": { 247 | "debug": { 248 | "version": "2.6.9", 249 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 250 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 251 | "dev": true, 252 | "requires": { 253 | "ms": "2.0.0" 254 | } 255 | }, 256 | "ms": { 257 | "version": "2.0.0", 258 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 259 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 260 | "dev": true 261 | } 262 | } 263 | }, 264 | "fd-slicer": { 265 | "version": "1.1.0", 266 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 267 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 268 | "dev": true, 269 | "requires": { 270 | "pend": "~1.2.0" 271 | } 272 | }, 273 | "filename-reserved-regex": { 274 | "version": "2.0.0", 275 | "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", 276 | "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", 277 | "dev": true 278 | }, 279 | "filenamify": { 280 | "version": "4.2.0", 281 | "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.2.0.tgz", 282 | "integrity": "sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA==", 283 | "dev": true, 284 | "requires": { 285 | "filename-reserved-regex": "^2.0.0", 286 | "strip-outer": "^1.0.1", 287 | "trim-repeated": "^1.0.0" 288 | } 289 | }, 290 | "fs-extra": { 291 | "version": "8.1.0", 292 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 293 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 294 | "dev": true, 295 | "requires": { 296 | "graceful-fs": "^4.2.0", 297 | "jsonfile": "^4.0.0", 298 | "universalify": "^0.1.0" 299 | } 300 | }, 301 | "get-stream": { 302 | "version": "4.1.0", 303 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 304 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 305 | "dev": true, 306 | "requires": { 307 | "pump": "^3.0.0" 308 | } 309 | }, 310 | "global-agent": { 311 | "version": "2.1.12", 312 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz", 313 | "integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==", 314 | "dev": true, 315 | "optional": true, 316 | "requires": { 317 | "boolean": "^3.0.1", 318 | "core-js": "^3.6.5", 319 | "es6-error": "^4.1.1", 320 | "matcher": "^3.0.0", 321 | "roarr": "^2.15.3", 322 | "semver": "^7.3.2", 323 | "serialize-error": "^7.0.1" 324 | }, 325 | "dependencies": { 326 | "semver": { 327 | "version": "7.3.4", 328 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 329 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 330 | "dev": true, 331 | "optional": true, 332 | "requires": { 333 | "lru-cache": "^6.0.0" 334 | } 335 | } 336 | } 337 | }, 338 | "global-tunnel-ng": { 339 | "version": "2.7.1", 340 | "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", 341 | "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", 342 | "dev": true, 343 | "optional": true, 344 | "requires": { 345 | "encodeurl": "^1.0.2", 346 | "lodash": "^4.17.10", 347 | "npm-conf": "^1.1.3", 348 | "tunnel": "^0.0.6" 349 | } 350 | }, 351 | "globalthis": { 352 | "version": "1.0.1", 353 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", 354 | "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", 355 | "dev": true, 356 | "optional": true, 357 | "requires": { 358 | "define-properties": "^1.1.3" 359 | } 360 | }, 361 | "got": { 362 | "version": "9.6.0", 363 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 364 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 365 | "dev": true, 366 | "requires": { 367 | "@sindresorhus/is": "^0.14.0", 368 | "@szmarczak/http-timer": "^1.1.2", 369 | "cacheable-request": "^6.0.0", 370 | "decompress-response": "^3.3.0", 371 | "duplexer3": "^0.1.4", 372 | "get-stream": "^4.1.0", 373 | "lowercase-keys": "^1.0.1", 374 | "mimic-response": "^1.0.1", 375 | "p-cancelable": "^1.0.0", 376 | "to-readable-stream": "^1.0.0", 377 | "url-parse-lax": "^3.0.0" 378 | } 379 | }, 380 | "graceful-fs": { 381 | "version": "4.2.4", 382 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 383 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 384 | "dev": true 385 | }, 386 | "http-cache-semantics": { 387 | "version": "4.1.0", 388 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 389 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 390 | "dev": true 391 | }, 392 | "inherits": { 393 | "version": "2.0.4", 394 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 395 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 396 | "dev": true 397 | }, 398 | "ini": { 399 | "version": "1.3.8", 400 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 401 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 402 | "dev": true, 403 | "optional": true 404 | }, 405 | "isarray": { 406 | "version": "1.0.0", 407 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 408 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 409 | "dev": true 410 | }, 411 | "json-buffer": { 412 | "version": "3.0.0", 413 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 414 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 415 | "dev": true 416 | }, 417 | "json-stringify-safe": { 418 | "version": "5.0.1", 419 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 420 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 421 | "dev": true, 422 | "optional": true 423 | }, 424 | "jsonfile": { 425 | "version": "4.0.0", 426 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 427 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 428 | "dev": true, 429 | "requires": { 430 | "graceful-fs": "^4.1.6" 431 | } 432 | }, 433 | "keyv": { 434 | "version": "3.1.0", 435 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 436 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 437 | "dev": true, 438 | "requires": { 439 | "json-buffer": "3.0.0" 440 | } 441 | }, 442 | "lodash": { 443 | "version": "4.17.21", 444 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 445 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 446 | "dev": true, 447 | "optional": true 448 | }, 449 | "lowercase-keys": { 450 | "version": "1.0.1", 451 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 452 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 453 | "dev": true 454 | }, 455 | "lru-cache": { 456 | "version": "6.0.0", 457 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 458 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 459 | "dev": true, 460 | "optional": true, 461 | "requires": { 462 | "yallist": "^4.0.0" 463 | } 464 | }, 465 | "matcher": { 466 | "version": "3.0.0", 467 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 468 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 469 | "dev": true, 470 | "optional": true, 471 | "requires": { 472 | "escape-string-regexp": "^4.0.0" 473 | }, 474 | "dependencies": { 475 | "escape-string-regexp": { 476 | "version": "4.0.0", 477 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 478 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 479 | "dev": true, 480 | "optional": true 481 | } 482 | } 483 | }, 484 | "mimic-response": { 485 | "version": "1.0.1", 486 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 487 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 488 | "dev": true 489 | }, 490 | "minimist": { 491 | "version": "1.2.5", 492 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 493 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 494 | "dev": true 495 | }, 496 | "mkdirp": { 497 | "version": "0.5.5", 498 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 499 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 500 | "dev": true, 501 | "requires": { 502 | "minimist": "^1.2.5" 503 | } 504 | }, 505 | "ms": { 506 | "version": "2.1.2", 507 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 508 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 509 | "dev": true 510 | }, 511 | "normalize-url": { 512 | "version": "4.5.1", 513 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", 514 | "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", 515 | "dev": true 516 | }, 517 | "npm-conf": { 518 | "version": "1.1.3", 519 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", 520 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", 521 | "dev": true, 522 | "optional": true, 523 | "requires": { 524 | "config-chain": "^1.1.11", 525 | "pify": "^3.0.0" 526 | } 527 | }, 528 | "object-keys": { 529 | "version": "1.1.1", 530 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 531 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 532 | "dev": true, 533 | "optional": true 534 | }, 535 | "once": { 536 | "version": "1.4.0", 537 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 538 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 539 | "dev": true, 540 | "requires": { 541 | "wrappy": "1" 542 | } 543 | }, 544 | "p-cancelable": { 545 | "version": "1.1.0", 546 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 547 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 548 | "dev": true 549 | }, 550 | "pend": { 551 | "version": "1.2.0", 552 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 553 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 554 | "dev": true 555 | }, 556 | "pify": { 557 | "version": "3.0.0", 558 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 559 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 560 | "dev": true, 561 | "optional": true 562 | }, 563 | "prepend-http": { 564 | "version": "2.0.0", 565 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 566 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 567 | "dev": true 568 | }, 569 | "process-nextick-args": { 570 | "version": "2.0.1", 571 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 572 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 573 | "dev": true 574 | }, 575 | "progress": { 576 | "version": "2.0.3", 577 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 578 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 579 | "dev": true 580 | }, 581 | "proto-list": { 582 | "version": "1.2.4", 583 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 584 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", 585 | "dev": true, 586 | "optional": true 587 | }, 588 | "pump": { 589 | "version": "3.0.0", 590 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 591 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 592 | "dev": true, 593 | "requires": { 594 | "end-of-stream": "^1.1.0", 595 | "once": "^1.3.1" 596 | } 597 | }, 598 | "readable-stream": { 599 | "version": "2.3.7", 600 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 601 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 602 | "dev": true, 603 | "requires": { 604 | "core-util-is": "~1.0.0", 605 | "inherits": "~2.0.3", 606 | "isarray": "~1.0.0", 607 | "process-nextick-args": "~2.0.0", 608 | "safe-buffer": "~5.1.1", 609 | "string_decoder": "~1.1.1", 610 | "util-deprecate": "~1.0.1" 611 | } 612 | }, 613 | "responselike": { 614 | "version": "1.0.2", 615 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 616 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 617 | "dev": true, 618 | "requires": { 619 | "lowercase-keys": "^1.0.0" 620 | } 621 | }, 622 | "roarr": { 623 | "version": "2.15.4", 624 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", 625 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", 626 | "dev": true, 627 | "optional": true, 628 | "requires": { 629 | "boolean": "^3.0.1", 630 | "detect-node": "^2.0.4", 631 | "globalthis": "^1.0.1", 632 | "json-stringify-safe": "^5.0.1", 633 | "semver-compare": "^1.0.0", 634 | "sprintf-js": "^1.1.2" 635 | } 636 | }, 637 | "safe-buffer": { 638 | "version": "5.1.2", 639 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 640 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 641 | "dev": true 642 | }, 643 | "semver": { 644 | "version": "6.3.0", 645 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 646 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 647 | "dev": true 648 | }, 649 | "semver-compare": { 650 | "version": "1.0.0", 651 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 652 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", 653 | "dev": true, 654 | "optional": true 655 | }, 656 | "serialize-error": { 657 | "version": "7.0.1", 658 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", 659 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", 660 | "dev": true, 661 | "optional": true, 662 | "requires": { 663 | "type-fest": "^0.13.1" 664 | } 665 | }, 666 | "sprintf-js": { 667 | "version": "1.1.2", 668 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 669 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", 670 | "dev": true, 671 | "optional": true 672 | }, 673 | "string_decoder": { 674 | "version": "1.1.1", 675 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 676 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 677 | "dev": true, 678 | "requires": { 679 | "safe-buffer": "~5.1.0" 680 | } 681 | }, 682 | "strip-outer": { 683 | "version": "1.0.1", 684 | "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", 685 | "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", 686 | "dev": true, 687 | "requires": { 688 | "escape-string-regexp": "^1.0.2" 689 | } 690 | }, 691 | "sumchecker": { 692 | "version": "3.0.1", 693 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", 694 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", 695 | "dev": true, 696 | "requires": { 697 | "debug": "^4.1.0" 698 | } 699 | }, 700 | "to-readable-stream": { 701 | "version": "1.0.0", 702 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 703 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 704 | "dev": true 705 | }, 706 | "trim-repeated": { 707 | "version": "1.0.0", 708 | "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", 709 | "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", 710 | "dev": true, 711 | "requires": { 712 | "escape-string-regexp": "^1.0.2" 713 | } 714 | }, 715 | "tunnel": { 716 | "version": "0.0.6", 717 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 718 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 719 | "dev": true, 720 | "optional": true 721 | }, 722 | "type-fest": { 723 | "version": "0.13.1", 724 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 725 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", 726 | "dev": true, 727 | "optional": true 728 | }, 729 | "typedarray": { 730 | "version": "0.0.6", 731 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 732 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 733 | "dev": true 734 | }, 735 | "universalify": { 736 | "version": "0.1.2", 737 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 738 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 739 | "dev": true 740 | }, 741 | "url-parse-lax": { 742 | "version": "3.0.0", 743 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 744 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 745 | "dev": true, 746 | "requires": { 747 | "prepend-http": "^2.0.0" 748 | } 749 | }, 750 | "util-deprecate": { 751 | "version": "1.0.2", 752 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 753 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 754 | "dev": true 755 | }, 756 | "wrappy": { 757 | "version": "1.0.2", 758 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 759 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 760 | "dev": true 761 | }, 762 | "yallist": { 763 | "version": "4.0.0", 764 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 765 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 766 | "dev": true, 767 | "optional": true 768 | }, 769 | "yauzl": { 770 | "version": "2.10.0", 771 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 772 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 773 | "dev": true, 774 | "requires": { 775 | "buffer-crc32": "~0.2.3", 776 | "fd-slicer": "~1.1.0" 777 | } 778 | } 779 | } 780 | } 781 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-seamless-titlebar-tutorial", 3 | "version": "1.0.0", 4 | "description": "A minimal Electron application", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "electron ." 8 | }, 9 | "repository": "https://github.com/binaryfunt/electron-seamless-titlebar-tutorial", 10 | "author": "binaryfunt", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "electron": "^9.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // All of the Node.js APIs are available in this process. 4 | const remote = require('electron').remote; 5 | 6 | const win = remote.getCurrentWindow(); /* Note this is different to the 7 | html global `window` variable */ 8 | 9 | // When document has loaded, initialise 10 | document.onreadystatechange = (event) => { 11 | if (document.readyState == "complete") { 12 | handleWindowControls(); 13 | 14 | document.getElementById('electron-ver').innerHTML = `${process.versions.electron}` 15 | } 16 | }; 17 | 18 | window.onbeforeunload = (event) => { 19 | /* If window is reloaded, remove win event listeners 20 | (DOM element listeners get auto garbage collected but not 21 | Electron win listeners as the win is not dereferenced unless closed) */ 22 | win.removeAllListeners(); 23 | } 24 | 25 | function handleWindowControls() { 26 | // Make minimise/maximise/restore/close buttons work when they are clicked 27 | document.getElementById('min-button').addEventListener("click", event => { 28 | win.minimize(); 29 | }); 30 | 31 | document.getElementById('max-button').addEventListener("click", event => { 32 | win.maximize(); 33 | }); 34 | 35 | document.getElementById('restore-button').addEventListener("click", event => { 36 | win.unmaximize(); 37 | }); 38 | 39 | document.getElementById('close-button').addEventListener("click", event => { 40 | win.close(); 41 | }); 42 | 43 | // Toggle maximise/restore buttons when maximisation/unmaximisation occurs 44 | toggleMaxRestoreButtons(); 45 | win.on('maximize', toggleMaxRestoreButtons); 46 | win.on('unmaximize', toggleMaxRestoreButtons); 47 | 48 | function toggleMaxRestoreButtons() { 49 | if (win.isMaximized()) { 50 | document.body.classList.add('maximized'); 51 | } else { 52 | document.body.classList.remove('maximized'); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | /* Basic styling */ 2 | * {margin: 0; padding: 0; border: 0; vertical-align: baseline;} 3 | html {box-sizing: border-box;} 4 | *, *:before, *:after {box-sizing: inherit;} 5 | html, body {height: 100%; margin: 0;} 6 | 7 | body { 8 | font-family: "Segoe UI", sans-serif; 9 | background: #1A2933; 10 | color: #FFF; 11 | } 12 | 13 | h1 { 14 | margin: 0 0 10px 0; 15 | font-weight: 600; 16 | line-height: 1.2; 17 | } 18 | 19 | p { 20 | margin-top: 10px; 21 | color: rgba(255,255,255,0.4); 22 | } 23 | 24 | /* Styling of window frame and titlebar */ 25 | body { 26 | border: 1px solid #48545c; 27 | overflow-y: hidden; 28 | } 29 | 30 | #titlebar { 31 | display: block; 32 | position: fixed; 33 | height: 32px; 34 | width: calc(100% - 2px); 35 | } 36 | 37 | .maximized #titlebar { 38 | width: 100%; 39 | padding: 0; 40 | } 41 | 42 | #main { 43 | height: calc(100% - 32px); 44 | margin-top: 32px; 45 | padding: 20px; 46 | overflow-y: auto; 47 | } 48 | 49 | #titlebar { 50 | padding: 4px; 51 | } 52 | 53 | #titlebar #drag-region { 54 | width: 100%; 55 | height: 100%; 56 | -webkit-app-region: drag; 57 | } 58 | 59 | #titlebar { 60 | color: #FFF; 61 | } 62 | 63 | #titlebar #drag-region { 64 | display: grid; 65 | grid-template-columns: auto 138px; 66 | } 67 | 68 | #window-title { 69 | grid-column: 1; 70 | display: flex; 71 | align-items: center; 72 | margin-left: 8px; 73 | overflow: hidden; 74 | font-family: "Segoe UI", sans-serif; 75 | font-size: 12px; 76 | } 77 | 78 | .maximized #window-title { 79 | margin-left: 12px; 80 | } 81 | 82 | #window-title span { 83 | overflow: hidden; 84 | text-overflow: ellipsis; 85 | white-space: nowrap; 86 | line-height: 1.5; 87 | } 88 | 89 | #window-controls { 90 | display: grid; 91 | grid-template-columns: repeat(3, 46px); 92 | position: absolute; 93 | top: 0; 94 | right: 0; 95 | height: 100%; 96 | } 97 | 98 | #window-controls { 99 | -webkit-app-region: no-drag; 100 | } 101 | 102 | #window-controls .button { 103 | grid-row: 1 / span 1; 104 | display: flex; 105 | justify-content: center; 106 | align-items: center; 107 | width: 100%; 108 | height: 100%; 109 | } 110 | 111 | @media (-webkit-device-pixel-ratio: 1.5), (device-pixel-ratio: 1.5), 112 | (-webkit-device-pixel-ratio: 2), (device-pixel-ratio: 2), 113 | (-webkit-device-pixel-ratio: 3), (device-pixel-ratio: 3) { 114 | #window-controls .icon { 115 | width: 10px; 116 | height: 10px; 117 | } 118 | } 119 | 120 | #window-controls .button { 121 | user-select: none; 122 | } 123 | 124 | #window-controls .button:hover { 125 | background: rgba(255,255,255,0.1); 126 | } 127 | 128 | #window-controls .button:active { 129 | background: rgba(255,255,255,0.2); 130 | } 131 | 132 | #close-button:hover { 133 | background: #E81123 !important; 134 | } 135 | 136 | #close-button:active { 137 | background: #F1707A !important; 138 | } 139 | #close-button:active .icon { 140 | filter: invert(1); 141 | } 142 | 143 | #min-button { 144 | grid-column: 1; 145 | } 146 | #max-button, #restore-button { 147 | grid-column: 2; 148 | } 149 | #close-button { 150 | grid-column: 3; 151 | } 152 | 153 | #restore-button { 154 | display: none !important; 155 | } 156 | 157 | .maximized #restore-button { 158 | display: flex !important; 159 | } 160 | 161 | .maximized #max-button { 162 | display: none; 163 | } 164 | --------------------------------------------------------------------------------