Repository: GregVido/mica-electron
Branch: main
Commit: 2caa79980dc5
Files: 23
Total size: 68.7 KB
Directory structure:
gitextract_n378x8h9/
├── .gitignore
├── LICENSE
├── README.md
├── build.bat
├── data
├── exemple.js
├── files/
│ ├── css/
│ │ ├── dark.css
│ │ └── styles.css
│ ├── index.html
│ └── js/
│ └── scripts.js
├── main.js
├── module/
│ ├── app.cpp
│ └── assets/
│ ├── dwm.cpp
│ ├── dwm.h
│ ├── types.h
│ ├── user32.cpp
│ ├── win.cpp
│ └── winstyle.h
├── package.json
├── src/
│ ├── micaElectron_arm64.node
│ ├── micaElectron_ia32.node
│ └── micaElectron_x64.node
└── types/
└── index.d.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules
.vscode
bin
build/**
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
<h1 align=center>Mica Electron</h1>
<div align=center>
<img src="https://micadiscord.com/img/preview/title.png" name="exemple">
<b>Mica Electron</b> is a tool to add mica effect on electron app.<br>
This is created by <a href="https://www.youtube.com/gregvido">GregVido</a>.<br>
<b>Mica electron is now compatible with windows 10</b>
</div>
<details>
<summary>Exemple of effects</summary>
<div align=center>
<img src="https://micadiscord.com/img/preview/demo-1.png" name="demo 0" width="30%">
<img src="https://micadiscord.com/img/preview/demo-2.png" name="demo 1" width="30%">
<img src="https://micadiscord.com/img/preview/demo-3.png" name="demo 2" width="30%">
<a href='https://micadiscord.com/img/mica-electron-preview.gif'>Click here to see the animation preview.</a>
</div>
</details><br>
## ☕ Support the project
If you like **Mica Electron** and want to support its development, you can buy me a coffee ❤️
👉 https://www.buymeacoffee.com/gregvido
## Quickstart
```bash
$ npm install mica-electron
```
```js
const electron = require('electron');
const { PARAMS, VALUE, MicaBrowserWindow, IS_WINDOWS_11, WIN10 } = require('mica-electron');
const path = require('path');
electron.app.on('ready', () => {
const win = new MicaBrowserWindow({
width: 800,
height: 600,
autoHideMenuBar: true,
show: false,
// frame: false // -> now work, you can remove the frame properly !!
});
win.setDarkTheme();
win.setMicaEffect();
// win.alwaysFocused(true); // -> allows you to keep the mica effects even if the window is no focus (decrease performance)
win.loadFile(path.join(__dirname, 'files', 'index.html'));
win.webContents.once('dom-ready', () => {
win.show();
});
});
```
<details>
<summary>Apply effect for windows 11</summary>
You can apply different mica effect :
```js
win.setMicaEffect(); // Mica Effect
win.setMicaTabbedEffect(); // Mica Tabbed
win.setMicaAcrylicEffect(); // Acrylic for windows 11
```
<div align=center>
<img src="https://micadiscord.com/img/preview/demo-1.png" name="corner 0" width="20%">
<img src="https://micadiscord.com/img/preview/demo-2.png" name="corner 1" width="20%">
<img src="https://micadiscord.com/img/preview/demo-3.png" name="corner 2" width="20%">
</div>
</details>
<details>
<summary>Change theme for windows 11</summary>
You can change theme :
```js
win.setAutoTheme(); // Same theme as computer
win.setLightTheme(); // Force light theme
win.setDarkTheme(); // Force dark theme
```
</details>
<details>
<summary>Apply effect for windows 10</summary>
You can apply different blur effect :
```js
win.setTransparent(); // Transparent window
win.setBlur(); // Blurred window
win.setAcrylic(); // Acrylic window
```
</details>
<details>
<summary>Change radius</summary>
You can change corner radius :
```js
win.setRoundedCorner(); // Rounded
win.setSmallRoundedCorner(); // Small rounded
win.setSquareCorner(); // Square
```
<div align=center>
<img src="https://micadiscord.com/img/preview/corner-1.png" name="corner 0" width="10%">
<img src="https://micadiscord.com/img/preview/corner-2.png" name="corner 1" width="10%">
<img src="https://micadiscord.com/img/preview/corner-3.png" name="corner 2" width="10%">
</div>
</details>
<details>
<summary>Change window colors</summary>
You can change window colors :
```js
win.setBorderColor('#f40b0b'); // Border color
win.setBorderColor(null); // -> disable effect
win.setCaptionColor('#262626'); // Background titlebar color
win.setCaptionColor(null); // -> disable effect
win.setTitleTextColor('#fff'); // Title text color
win.setTitleTextColor(null); // -> disable effect
```
<div align=center>
<img src="https://micadiscord.com/img/preview/border.png" name="border" width="50%">
</div>
</details>
<details>
<summary>Change custom transparent effect for windows 10 <b>NEW!</b></summary>
You can change window colors :
```js
win.setCustomEffect(WIN10.TRANSPARENT, '#34ebc0', 0.5); // Transparent
win.setCustomEffect(WIN10.ACRYLIC, '#34ebc0', 0.4); // Acrylic
```
<div align=center>
<img src="https://micadiscord.com/img/mica-electron-custom-exemple.png" name="border" width="40%">
<img src="https://micadiscord.com/img/mica-electron-custom-blur-exemple.png" name="border" width="40%">
</div>
</details>
<br>
## Source Install / Manual Compilation
To compile from source it's easiest to use
[`node-gyp`](https://github.com/TooTallNate/node-gyp):
``` bash
$ npm install -g node-gyp
```
Now you can compile `mica-electron`:
``` bash
$ cd .\node_modules\mica-electron\
$ ./build.bat
```
## Objects details
<details>
<summary>PARAMS Object</summary>
The params is a number, you can has an object to help you:
```js
const PARAMS = {
BACKGROUND: {
AUTO: 0,
NONE: 1,
ACRYLIC: 3, // Acrylic
MICA: 2, // Mica
TABBED_MICA: 4 // Mica tabbed
},
CORNER: 5,
BORDER_COLOR: 6,
CAPTION_COLOR: 7,
TEXT_COLOR: 8,
FRAME: 9
}
```
</details>
<details>
<summary>VALUE Object</summary>
The value is a number, you can has an object to help you:
```js
const VALUE = {
THEME: {
AUTO: 5, // select theme by the windows theme
DARK: 1, // select the dark theme
LIGHT: 2, // select the white theme
},
CORNER: {
DEFAULT: 0,
DONOTROUND: 1,
ROUND: 2,
ROUNDSMALL: 3
},
COLOR: {
RED: 0x000000FF,
GREEN: 0x0000FF00,
BLUE: 0x00FF0000,
BLACK: 0x00000000,
WHITE: 0x00FFFFFF,
FROM_RGB: (r, g, b) => {
return r + (g << 8) + (b << 16);
}
},
FALSE: 0,
TRUE: 1
}
```
</details>
<details>
<summary>IS_WINDOWS_11</summary>
IS_WINDOWS_11 is a boolean constant to detect the OS version. If it is true then it's a windows 11 computer, otherwise it is another version (10, 8, 7 ...)
</details>
<details>
<summary>WIN10 Object</summary>
The value is a number, you can has an object to help you:
```js
const WIN10 = {
TRANSPARENT: 2,
BLURBEHIND: 3, // didn't work on windows 11
ACRYLIC: 4
}
```
</details><br>
## FAQ
<details>
<summary>Error: '...\micaElectron.node' was compiled against a different Node.js version using ...</summary>
If you are an error of nodejs version, use electron-packager to rebuild the project with the good version.
```bash
$ npm install electron
$ npm install electron-rebuild
$ .\node_modules\.bin\electron-rebuild
```
</details>
<details>
<summary>Build for 32 bits ?</summary>
If you want use `mica-electron` with 32 bits electron app, rebuild C++ script
``` bash
$ cd .\node_modules\mica-electron\
$ node-gyp rebuild --arch=ia32
$ cd ..\..\
$ .\node_modules\.bin\electron-rebuild --arch=ia32
```
</details>
<br>
## Awesome applications using Mica-Electron
- [MicaDiscord](https://www.micadiscord.com/) by GregVido and Arbitro
- [Cider](https://github.com/ciderapp/Cider) by [Cider Collective](https://github.com/ciderapp)
- [Fluent Browser](https://github.com/ThePiGuy3141/fluent-browser) by <a href="https://github.com/ThePiGuy3141">ThePiGuy3141</a>
- [Mica-Snap](https://github.com/GregVido/Mica-Snap) by GregVido
- [SysMocap](https://github.com/xianfei/SysMocap) by [xianfei](https://github.com/xianfei)
================================================
FILE: build.bat
================================================
@echo off
REM =========================
REM ANSI colors
REM =========================
for /f %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
set C_RESET=%ESC%[0m
set C_TITLE=%ESC%[96m
set C_INFO=%ESC%[94m
set C_OK=%ESC%[92m
set C_WARN=%ESC%[93m
set C_ERR=%ESC%[91m
set C_LINE=%ESC%[90m
set INCLUDE_ARM64=true
REM -------------------------
REM Parse arguments
REM -------------------------
for %%i in (%*) do (
if "%%i"=="--include-arm64" (
set INCLUDE_ARM64=true
)
)
echo %C_LINE%-------------------------%C_RESET%
echo %C_TITLE%MicaElectron Builder v1.1%C_RESET%
echo %C_LINE%-------------------------%C_RESET%
echo.
REM -------------------------
REM Safety checks
REM -------------------------
where node >nul 2>&1 || (
echo %C_ERR%[ERROR]%C_RESET% Node.js not found in PATH
exit /b 1
)
where node-gyp >nul 2>&1 || (
echo %C_ERR%[ERROR]%C_RESET% node-gyp not found in PATH
exit /b 1
)
if exist data (
ren data binding.gyp || (
echo %C_ERR%[ERROR]%C_RESET% Failed to rename data to binding.gyp
exit /b 1
)
)
if not exist binding.gyp (
echo %C_ERR%[ERROR]%C_RESET% binding.gyp not found
exit /b 1
)
REM -------------------------
REM Reset src folder
REM -------------------------
echo %C_LINE%-------------------------%C_RESET%
echo %C_INFO%Resetting src folder...%C_RESET%
if exist src (
rmdir /s /q src || (
echo %C_ERR%[ERROR]%C_RESET% Failed to remove src folder
goto restore_gyp
)
)
mkdir src || (
echo %C_ERR%[ERROR]%C_RESET% Failed to create src folder
goto restore_gyp
)
REM -------------------------
REM Build x64
REM -------------------------
echo %C_LINE%-------------------------%C_RESET%
node-gyp rebuild >nul 2>&1 | echo %C_INFO%Building x64...%C_RESET%
if errorlevel 1 (
echo %C_ERR%[ERROR]%C_RESET% x64 build failed
goto restore_gyp
)
if not exist build\Release\micaElectron.node (
echo %C_ERR%[ERROR]%C_RESET% x64 output file not found
goto restore_gyp
)
move build\Release\micaElectron.node src\micaElectron_x64.node >nul || (
echo %C_ERR%[ERROR]%C_RESET% Failed to move x64 binary
goto restore_gyp
)
echo %C_OK%[OK]%C_RESET% x64 build completed
echo.
REM -------------------------
REM Build ia32
REM -------------------------
echo %C_LINE%-------------------------%C_RESET%
node-gyp rebuild --arch=ia32 >nul 2>&1 | echo %C_INFO%Building ia32...%C_RESET%
if errorlevel 1 (
echo %C_ERR%[ERROR]%C_RESET% ia32 build failed
goto restore_gyp
)
if not exist build\Release\micaElectron.node (
echo %C_ERR%[ERROR]%C_RESET% ia32 output file not found
goto restore_gyp
)
move build\Release\micaElectron.node src\micaElectron_ia32.node >nul || (
echo %C_ERR%[ERROR]%C_RESET% Failed to move ia32 binary
goto restore_gyp
)
echo %C_OK%[OK]%C_RESET% ia32 build completed
echo.
REM -------------------------
REM Build ARM64 (optional)
REM -------------------------
if "%INCLUDE_ARM64%"=="true" (
echo %C_LINE%-------------------------%C_RESET%
node-gyp rebuild --arch=arm64 >nul 2>&1 | echo %C_INFO%Building arm64...%C_RESET%
if errorlevel 1 (
echo %C_ERR%[ERROR]%C_RESET% arm64 build failed
goto restore_gyp
)
if not exist build\Release\micaElectron.node (
echo %C_ERR%[ERROR]%C_RESET% arm64 output file not found
goto restore_gyp
)
move build\Release\micaElectron.node src\micaElectron_arm64.node >nul || (
echo %C_ERR%[ERROR]%C_RESET% Failed to move arm64 binary
goto restore_gyp
)
echo %C_OK%[OK]%C_RESET% arm64 build completed
echo.
)
REM -------------------------
REM Cleanup
REM -------------------------
echo %C_LINE%-------------------------%C_RESET%
echo %C_INFO%Cleaning build artifacts...%C_RESET%
if exist build (
rmdir /s /q build || (
echo %C_ERR%[ERROR]%C_RESET% Failed to remove build folder
goto restore_gyp
)
)
REM -------------------------
REM Restore binding.gyp
REM -------------------------
:restore_gyp
if exist binding.gyp (
ren binding.gyp data
)
echo %C_LINE%-------------------------%C_RESET%
echo %C_OK%Build finished successfully%C_RESET%
echo %C_LINE%-------------------------%C_RESET%
exit /b 0
================================================
FILE: data
================================================
{
"targets": [
{
"target_name": "micaElectron",
"sources": [ "module/app.cpp" ]
}
],
'variables':{
'openssl_fips':0
}
}
================================================
FILE: exemple.js
================================================
const { app, ipcMain } = require('electron');
const { PARAMS, VALUE, MicaBrowserWindow, IS_WINDOWS_11, WIN10 } = require('./main.js');
const path = require('path');
app.on('ready', () => {
const win = new MicaBrowserWindow({
width: 800,
height: 600,
autoHideMenuBar: true,
show: false,
// frame: false, // -> now work, you can remove the frame properly !!
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
win.setLightTheme();
if (IS_WINDOWS_11)
win.setMicaTabbedEffect();
else
win.setCustomEffect(WIN10.ACRYLIC, '#401896', .2);
// win.alwaysFocused(true); // -> allows you to keep the mica effects even if the window is no focus (decrease performance)
win.loadFile(path.join(__dirname, 'files', 'index.html'));
win.webContents.once('dom-ready', () => {
win.show();
});
// Change theme
ipcMain.on('theme', (evt, newValue) => {
switch (newValue) {
case VALUE.THEME.AUTO:
win.setAutoTheme();
break
case VALUE.THEME.LIGHT:
win.setLightTheme();
break
case VALUE.THEME.DARK:
win.setDarkTheme();
break
}
});
// Change effect
ipcMain.on('effect', (evt, newParams) => {
switch (newParams) {
case PARAMS.BACKGROUND.MICA:
win.setMicaEffect();
break
case PARAMS.BACKGROUND.TABBED_MICA:
win.setMicaTabbedEffect();
break
case PARAMS.BACKGROUND.ACRYLIC:
win.setMicaAcrylicEffect();
break
}
});
// apply effect (corner, background-color, ...)
ipcMain.on('params', (evt, params, value) => {
switch (params) {
case PARAMS.CORNER:
switch (value) {
case VALUE.CORNER.ROUND:
win.setRoundedCorner();
break
case VALUE.CORNER.ROUNDSMALL:
win.setSmallRoundedCorner();
break
case VALUE.CORNER.DONOTROUND:
win.setSquareCorner();
break
}
break
case PARAMS.BORDER_COLOR:
win.setBorderColor(value);
break
case PARAMS.CAPTION_COLOR:
win.setCaptionColor(value);
break
case PARAMS.TEXT_COLOR:
win.setTitleTextColor(value);
break
case 10:
switch (value) {
case 0:
win.setTransparent();
break
case 1:
win.setBlur();
break
case 2:
win.setAcrylic();
break
}
break
}
});
});
================================================
FILE: files/css/dark.css
================================================
main,
fieldset {
background-color: #000000e3;
border: 1px solid #353535;
color: #fff;
}
fieldset {
background-color: #00000096;
}
button {
background: #000;
border: 1px solid rgb(24, 24, 24);
color: #fff;
}
button:hover {
background: #141414;
}
/* Track */
::-webkit-scrollbar-track {
background: #888;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #f1f1f1;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #f8f8f8;
}
================================================
FILE: files/css/styles.css
================================================
body {
font-family: Arial, Helvetica, sans-serif;
background-color: transparent;
padding: 10px;
}
h1 {
-webkit-app-region: drag;
}
main,
fieldset {
margin: auto;
width: 60%;
text-align: center;
background-color: #ffffffe3;
padding: 10px;
border: 1px solid #cacaca;
border-radius: 15px;
color: #000;
}
fieldset {
margin-top: 10px;
background-color: #ffffff96;
}
legend {
text-align: left;
}
button {
background: #fff;
border: 1px solid rgb(231, 231, 231);
padding: 7px 15px;
transition: .2s background;
color: #000;
}
button:hover {
background: #ebebeb;
}
/* width */
::-webkit-scrollbar {
width: 4px;
}
/* Track */
::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #555;
}
================================================
FILE: files/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World</title>
<link rel="stylesheet" href="css/styles.css">
<script src="js/scripts.js"></script>
</head>
<body>
<main>
<h1>Hello World</h1>
</main>
<fieldset>
<legend>Effect</legend>
<button onclick="setEffect(3)">Acrylic</button>
<button onclick="setEffect(2)">Mica</button>
<button onclick="setEffect(4)">Mica Tabbed</button>
</fieldset>
<fieldset>
<legend>Theme</legend>
<button onclick="setTheme(5)">Auto</button>
<button onclick="setTheme(1)">Dark</button>
<button onclick="setTheme(2)">Light</button>
</fieldset>
<fieldset>
<legend>Corner</legend>
<button onclick="setParams(5, 2)">Round</button>
<button onclick="setParams(5, 3)">Small Round</button>
<button onclick="setParams(5, 1)">Square</button>
</fieldset>
<fieldset>
<legend>Window Color</legend>
<input type="color" id="colorBorder" name="colorBorder" value="#e6e6e6">
<label for="colorBorder">Border</label>
<input type="color" id="colorCaption" name="colorCaption" value="#e6e6e6">
<label for="colorCaption">Caption</label>
<input type="color" id="colorTitle" name="colorTitle" value="#e6e6e6">
<label for="colorTitle">Title</label>
</fieldset>
<fieldset>
<legend>Windows 10 Effect</legend>
<button onclick="setParams(10, 0)">Transparent</button>
<button onclick="setParams(10, 1)">Blur</button>
<button onclick="setParams(10, 2)">Acrylic</button>
</fieldset>
</body>
</html>
================================================
FILE: files/js/scripts.js
================================================
const { ipcRenderer } = require('electron');
const darkTheme = document.createElement('link');
darkTheme.rel = 'stylesheet';
darkTheme.href = 'css/dark.css';
function setTheme(theme) {
ipcRenderer.send('theme', theme);
if (theme == 1)
document.head.appendChild(darkTheme);
else
document.head.removeChild(darkTheme);
}
function setEffect(effect) {
ipcRenderer.send('effect', effect);
}
function setParams(params, value) {
ipcRenderer.send('params', params, value);
}
function htmlToColor(color) {
let r = color.slice(0, 2);
let g = color.slice(2, 4);
let b = color.slice(4, 6);
return parseInt("0x" + b + g + r);
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
document.head[event.matches ? 'appendChild' : 'removeChild'](darkTheme);
});
window.onload = () => {
const colorBorder = document.getElementById('colorBorder');
const colorCaption = document.getElementById('colorCaption');
const colorTitle = document.getElementById('colorTitle');
colorBorder.addEventListener('input', () => {
setParams(6, colorBorder.value);
});
colorCaption.addEventListener('input', () => {
setParams(7, colorCaption.value);
});
colorTitle.addEventListener('input', () => {
setParams(8, colorTitle.value);
});
}
================================================
FILE: main.js
================================================
/*
Copyright 2024 GregVido
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const electron = require('electron');
const os = require('os');
const fs = require('fs');
const path = require('path');
const IS_ELECTRON_RECENT_VERSION = process.versions.electron >= '27.0.0' && process.versions.electron <= '40.0.0';
const filepath = path.join(__dirname, 'src', '/micaElectron_' + process.arch);
let executeDwm, redraw, executeUser32;
if (fs.existsSync(filepath + '.node')) {
/* If mica-electron is running on windows */
if (process.platform == 'win32') {
const micaBuild = require(filepath);
executeDwm = micaBuild.executeDwm;
redraw = micaBuild.redraw;
executeUser32 = micaBuild.executeUser32;
}
else {
console.log('Mica-Electron only works on Windows!');
console.log('Mica-Electron: Disabled');
}
}
else {
console.log('./src/micaElectron_' + process.arch + '.node does not exist!');
console.log('Mica-Electron: Disabled');
}
electron.app.commandLine.appendSwitch("enable-transparent-visuals");
/**
* Detect if OS is windows 11
* @returns {Boolean} True if windows 11
*/
function isWin11() {
const version = os.release().split('.');
if (version.length == 3)
return version[2] >= '22000';
return false;
}
const WINDOWS_11 = isWin11();
/**
* Remove a frame from a window
* @param {BrowserWindow} window Target to remove frame
*/
function redrawFrame(window) {
if (redraw) {
const HWND = window.getNativeWindowHandle()["readInt32LE"]();
const bounds = window.getBounds();
// executeDwm(HWND, PARAMS.FRAME, VALUE.FALSE);
redraw(HWND, bounds.x, bounds.y, bounds.width, bounds.height);
}
}
const PARAMS = {
BACKGROUND: {
AUTO: 0,
NONE: 1,
ACRYLIC: 3, // Acrylic
MICA: 2, // Mica
TABBED_MICA: 4 // Mica tabbed
},
CORNER: 5,
BORDER_COLOR: 6,
CAPTION_COLOR: 7,
TEXT_COLOR: 8,
FRAME: 9,
MARGIN: 10
}
const VALUE = {
THEME: {
AUTO: 5, // select theme by the windows theme
DARK: 1, // select the dark theme
LIGHT: 2, // select the white theme
},
CORNER: {
DEFAULT: 0,
DONOTROUND: 1,
ROUND: 2,
ROUNDSMALL: 3
},
COLOR: {
RED: 0x000000FF,
GREEN: 0x0000FF00,
BLUE: 0x00FF0000,
BLACK: 0x00000000,
WHITE: 0x00FFFFFF,
FROM_RGB: (r, g, b) => {
return r + (g << 8) + (b << 16);
}
},
FALSE: 0,
TRUE: 1
}
const WIN10 = {
TRANSPARENT: 2,
BLURBEHIND: 3,
ACRYLIC: 4
}
/**
* Convert HTML color to windows color
* @param {String} str HTML color
* @return {Number} windows color (int, 24 bits)
*/
let getColorByString = (str) => {
if (str.startsWith('#')) {
const hexs = str.slice(1);
if (hexs.length == 3) {
const r = parseInt(hexs[0] + hexs[0], 16);
const g = parseInt(hexs[1] + hexs[1], 16);
const b = parseInt(hexs[2] + hexs[2], 16);
return VALUE.COLOR.FROM_RGB(r, g, b);
}
else if (hexs.length == 6) {
const r = parseInt(hexs.slice(0, 2), 16);
const g = parseInt(hexs.slice(2, 4), 16);
const b = parseInt(hexs.slice(4, 6), 16);
return VALUE.COLOR.FROM_RGB(r, g, b);
}
}
else if (str.startsWith('rgb(')) {
const data = str.slice(4).split(')')[0].split(',');
const r = parseInt(data[0]);
const g = parseInt(data[1]);
const b = parseInt(data[2]);
return VALUE.COLOR.FROM_RGB(r, g, b);
}
else if (str.length == 8) { // color from getAccentColor()
const r = parseInt(str.slice(0, 2), 16);
const g = parseInt(str.slice(2, 4), 16);
const b = parseInt(str.slice(4, 6), 16);
return VALUE.COLOR.FROM_RGB(r, g, b);
}
}
class BrowserWindow extends electron.BrowserWindow {
/** @type {Number} */
effect = PARAMS.BACKGROUND.AUTO;
/** @type {Number} */
theme = VALUE.THEME.AUTO;
/** @type {Boolean} */
useDWM = false;
/** @type {Boolean} */
hasFrameless = false;
/** @type {Boolean} */
forceFocus = false;
/** @type {Boolean} */
hasMargin = false;
/**
* Create electron BrowserWindow with mica effect features
* @param {...Object} args
*/
constructor(...args) {
if (args.length > 0) {
args[0].transparent = false;
args[0].backgroundColor = '#00ffffff';
} else
args.push({
backgroundColor: '#00ffffff'
});
if (IS_ELECTRON_RECENT_VERSION)
args[0].transparent = true;
super(...args);
this.hasFrameless = args[0].frame === false || args[0].titleBarStyle == 'hidden';
let applyEffect = () => {
if (args.length > 0 && this.useDWM) {
this.executeDwm(this.effect, this.theme);
}
}
let frameRemoved = true;
let onWindowShow = () => {
applyEffect();
if (frameRemoved) {
frameRemoved = false;
setTimeout(() => {
this.hide();
if (IS_ELECTRON_RECENT_VERSION) {
this.interceptMessage();
this.applyStyle();
if (this.hasFrameless)
this.removeCaption();
}
redrawFrame(this);
this.show();
}, 60);
}
}
this.on('show', onWindowShow);
this.on('restore', onWindowShow);
this.on('close', () => {
if (this.marginTimer)
clearInterval(this.marginTimer);
});
this.on('resize', () => {
if (this.hasFrameless)
setTimeout(applyEffect, 60); // refresh effect
});
}
/**
* Enable resize/maximize for the window
*/
applyStyle() {
this.executeDwm(PARAMS.FRAME, 1);
}
/**
* Restore the full screen action
*/
interceptMessage() {
this.executeDwm(PARAMS.FRAME, 2);
}
/**
* Remove Window Caption
*/
removeCaption() {
this.executeDwm(PARAMS.FRAME, 4);
}
/**
* Disable transparent for mica effect
*/
disableMargin() {
if (this.marginTimer) {
clearInterval(this.marginTimer);
this.marginTimer = null;
}
if (this.useDWM)
this.executeDwm(PARAMS.MARGIN, 1);
this.hasMargin = false;
}
/**
* Enable transparent for mica effect
*/
enableMargin() {
if (this.marginTimer)
clearInterval(this.marginTimer);
this.hasMargin = true;
if (!this.hasFrameless && !this.forceFocus)
this.executeDwm(PARAMS.MARGIN, 0);
else
this.marginTimer = setInterval(() => {
try {
if (this.hasFrameless)
this.executeDwm(PARAMS.MARGIN, 0);
if (this.forceFocus)
this.executeDwm(PARAMS.FRAME, 5);
} catch (e) {
clearInterval(this.marginTimer);
this.marginTimer = null;
}
}, 1);
}
/**
* Focus on the window all the time so as not to lose the mica effect (decrease performance)
* @param {Boolean} enable
*/
alwaysFocused(enable) {
this.forceFocus = enable;
if (this.hasMargin)
this.enableMargin();
}
/**
* Apply MicaEffect (only windows 11)
*/
setMicaEffect() {
this.disableUser32();
this.enableMargin();
this.executeDwm(PARAMS.BACKGROUND.MICA, this.theme);
}
/**
* Apply MicaTabbed Effect (only windows 11)
*/
setMicaTabbedEffect() {
this.disableUser32();
this.enableMargin();
this.executeDwm(PARAMS.BACKGROUND.TABBED_MICA, this.theme);
}
/**
* Apply Acrylic Effect (only windows 11)
*/
setMicaAcrylicEffect() {
this.disableUser32();
this.enableMargin();
this.executeDwm(PARAMS.BACKGROUND.ACRYLIC, this.theme);
}
/**
* Apply dark theme to the electron app
*/
setDarkTheme() {
electron.nativeTheme.themeSource = 'dark';
if (WINDOWS_11)
this.executeDwm(this.effect, VALUE.THEME.DARK);
}
/**
* Apply light theme to the electron app
*/
setLightTheme() {
electron.nativeTheme.themeSource = 'light';
if (WINDOWS_11)
this.executeDwm(this.effect, VALUE.THEME.LIGHT);
}
/**
* Apply auto detection theme to the electron app
*/
setAutoTheme() {
electron.nativeTheme.themeSource = 'system';
if (WINDOWS_11)
this.executeDwm(this.effect, VALUE.THEME.AUTO);
}
/**
* Apply rounded corner to the electron app
*/
setRoundedCorner() {
this.executeDwm(PARAMS.CORNER, VALUE.CORNER.ROUND);
}
/**
* Apply rounded corner to the electron app
*/
setSmallRoundedCorner() {
this.executeDwm(PARAMS.CORNER, VALUE.CORNER.ROUNDSMALL);
}
/**
* Apply square corner to the electron app
*/
setSquareCorner() {
this.executeDwm(PARAMS.CORNER, VALUE.CORNER.DONOTROUND);
}
/**
* Set border color to the electron app
* @param {String} color HTML color (#RRGGBB, #RGB, or rgb(r, g, b))
*/
setBorderColor(color) {
if (color != null) {
color = getColorByString(color);
this.executeDwm(PARAMS.BORDER_COLOR, color);
}
else
this.executeDwm(PARAMS.BORDER_COLOR, 0xFFFFFFFF);
}
/**
* Set caption color to the electron app
* @param {String} color HTML color (#RRGGBB, #RGB, or rgb(r, g, b))
*/
setCaptionColor(color) {
if (color != null) {
color = getColorByString(color);
this.executeDwm(PARAMS.CAPTION_COLOR, color);
}
else
this.executeDwm(PARAMS.CAPTION_COLOR, 0xFFFFFFFF);
}
/**
* Set title text color to the electron app
* @param {String} color HTML color (#RRGGBB, #RGB, or rgb(r, g, b))
*/
setTitleTextColor(color) {
if (color != null) {
color = getColorByString(color);
this.executeDwm(PARAMS.TEXT_COLOR, color);
}
else
this.executeDwm(PARAMS.TEXT_COLOR, 0xFFFFFFFF);
}
/**
* Apply transparent Effect (windows 7+)
*/
setTransparent() {
if (WINDOWS_11)
this.disableDWM();
this.executeUser32(WIN10.TRANSPARENT, 0x00ffffff);
}
/**
* Apply blur Effect (windows 7+)
*/
setBlur() {
if (WINDOWS_11)
this.disableDWM();
this.executeUser32(WIN10.BLURBEHIND, 0x00ffffff);
}
/**
* Apply Acrylic Effect (windows 7+)
*/
setAcrylic() {
if (WINDOWS_11)
this.disableDWM();
this.executeUser32(WIN10.ACRYLIC, 0x00909090);
}
/**
* Apply custom effect of SetWindowCompositionAttribute (windows 7+)
* @param {Number} nAccentState
* @param {String} color HTML color
* @param {Number} a Alpha intensity (0 < a < 1)
*/
setCustomEffect(nAccentState, color, a) {
if (WINDOWS_11)
this.disableDWM();
a = Math.min(Math.max(Math.round(a * 255), 0), 255);
const colorToInt = getColorByString(color);
this.executeUser32(nAccentState, (a << 24) + colorToInt);
}
/**
* Disable windows 10 effect
*/
disableUser32() {
if (!this.useDWM)
this.executeUser32(0, 0xffffffff);
this.useDWM = true;
}
/**
* Disable windows 11 effect
*/
disableDWM() {
if (this.useDWM)
this.executeDwm(PARAMS.BACKGROUND.NONE, this.theme);
this.disableMargin();
this.useDWM = false;
}
/**
* Execute function 'DwmSetWindowAttribute' from dwmapi.dll
* @param {Number} params ID of the dwAttribute
* @param {Number} value New value for the params
*/
executeDwm(params, value) {
if (executeDwm) {
const HWND = this.getNativeWindowHandle()["readInt32LE"]();
executeDwm(HWND, params, value);
if (params >= 0 && params <= 4) {
this.effect = params;
this.theme = value;
}
}
}
/**
* Execute function 'SetWindowCompositionAttribute' from user32.dll
* @param {Number} params ID of the dwAttribute
* @param {Number} value New value for the params
*/
executeUser32(params, value) {
if (executeUser32) {
const HWND = this.getNativeWindowHandle()["readInt32LE"]();
executeUser32(HWND, params, value);
}
}
}
module.exports = {
PARAMS: PARAMS,
VALUE: VALUE,
MicaBrowserWindow: BrowserWindow,
IS_WINDOWS_11: WINDOWS_11,
WIN10: WIN10
};
================================================
FILE: module/app.cpp
================================================
/*
Copyright 2024 GregVido
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma warning(disable : 4996) // GetVersion() was declared deprecated
#pragma warning(disable : 4312) // long -> HWND size >
#include <node_api.h>
#include "assets/win.cpp"
#include "assets/winstyle.h"
#include "assets/dwm.cpp"
#include "assets/user32.cpp"
#include "assets/types.h"
namespace micaElectron
{
napi_value executeDwm(napi_env env, napi_callback_info args)
{
size_t argc;
napi_get_cb_info(env, args, &argc, nullptr, nullptr, nullptr);
napi_value *argv = new napi_value[argc];
napi_get_cb_info(env, args, &argc, argv, nullptr, nullptr);
if (argc < 1)
napi_throw_error(env, nullptr, "HWND argument missing.");
else if (argc < 2)
napi_throw_error(env, nullptr, "PARAMS argument missing.");
else if (argc < 3)
napi_throw_error(env, nullptr, "VALUE argument missing.");
else
{
napi_valuetype HWNDType;
napi_valuetype ParamsType;
napi_valuetype ValueType;
napi_typeof(env, argv[0], &HWNDType);
napi_typeof(env, argv[1], &ParamsType);
napi_typeof(env, argv[2], &ValueType);
bool isHWNDNumber = HWNDType == napi_number;
bool isParamsNumber = ParamsType == napi_number;
bool isValueNumber = ValueType == napi_number;
if (!isHWNDNumber)
napi_throw_error(env, nullptr, "HWND argument must be an integer.");
else if (!isParamsNumber)
napi_throw_error(env, nullptr, "PARAMS argument must be an integer.");
else if (!isValueNumber)
napi_throw_error(env, nullptr, "VALUE argument must be an integer.");
else
{
int64_t hwnd64;
int32_t params32;
int32_t value32;
napi_get_value_int64(env, argv[0], &hwnd64);
napi_get_value_int32(env, argv[1], ¶ms32);
napi_get_value_int32(env, argv[2], &value32);
HWND hwnd = (HWND)hwnd64;
int params = (int)params32;
int value = (int)value32;
if (params == WINDOW_EDIT)
{
switch (value)
{
case RESET_BORDER:
resetBorderApp(hwnd);
break;
case ENABLE_MAXIMIZE:
enableMaximizeBox(hwnd);
break;
case INTERCEPT_MSG:
interceptMessage(hwnd);
break;
case ENABLE_CAPTION:
disableCaption(hwnd);
break;
case DISABLE_CAPTION:
enableCaption(hwnd);
break;
case FOCUS_WINDOW:
SetFocus(hwnd);
break;
case 10:
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, NULL, 0, 0, 1920, 1080, 0x0020);
break;
default:
break;
}
}
else if (!isWin11())
napi_throw_error(env, nullptr, "Mica-Electron work only on Windows 11.");
else
{
enableDWM();
if (params <= MICA_EFFECT)
{
setAppTheme(value, hwnd);
bool success = applyMicaEffect(params, hwnd);
if (!success)
{
napi_throw_error(env, nullptr, "You use old version of windows 11, you have don't have ACRYLIC and MICA_TABBED.");
return nullptr;
}
}
else
{
switch (params)
{
case CORNER_TYPE:
setCorner(value, hwnd);
break;
case BORDER_COLOR:
setBorderColor(value, hwnd);
break;
case CAPTION_COLOR:
setCaptionColor(value, hwnd);
break;
case TEXT_COLOR:
setTextColor(value, hwnd);
break;
case MARGIN_TYPE:
setMargin(value, hwnd);
break;
default:
break;
}
}
disableDWM();
}
}
}
return nullptr;
}
napi_value executeUser32(napi_env env, napi_callback_info args)
{
size_t argc;
napi_get_cb_info(env, args, &argc, nullptr, nullptr, nullptr);
napi_value *argv = new napi_value[argc];
napi_get_cb_info(env, args, &argc, argv, nullptr, nullptr);
if (argc < 1)
napi_throw_error(env, nullptr, "HWND argument missing.");
else if (argc < 2)
napi_throw_error(env, nullptr, "PARAMS argument missing.");
else if (argc < 3)
napi_throw_error(env, nullptr, "VALUE argument missing.");
else
{
napi_valuetype HWNDType;
napi_valuetype ParamsType;
napi_valuetype ValueType;
napi_typeof(env, argv[0], &HWNDType);
napi_typeof(env, argv[1], &ParamsType);
napi_typeof(env, argv[2], &ValueType);
bool isHWNDNumber = HWNDType == napi_number;
bool isParamsNumber = ParamsType == napi_number;
bool isValueNumber = ValueType == napi_number;
if (!isHWNDNumber)
napi_throw_error(env, nullptr, "HWND argument must be an integer.");
else if (!isParamsNumber)
napi_throw_error(env, nullptr, "PARAMS argument must be an integer.");
else if (!isValueNumber)
napi_throw_error(env, nullptr, "VALUE argument must be an integer.");
else
{
int64_t hwnd64;
int32_t params32;
int32_t value32;
napi_get_value_int64(env, argv[0], &hwnd64);
napi_get_value_int32(env, argv[1], ¶ms32);
napi_get_value_int32(env, argv[2], &value32);
enableUser32();
HWND hwnd = (HWND)hwnd64;
int params = (int)params32;
int value = (int)value32;
applyWindows10Effect(params, value, hwnd);
disableUser32();
}
}
return nullptr;
}
napi_value redraw(napi_env env, napi_callback_info args)
{
size_t argc;
napi_get_cb_info(env, args, &argc, nullptr, nullptr, nullptr);
napi_value *argv = new napi_value[argc];
napi_get_cb_info(env, args, &argc, argv, nullptr, nullptr);
if (argc < 1)
napi_throw_error(env, nullptr, "HWND argument missing.");
else if (argc < 2)
napi_throw_error(env, nullptr, "X argument missing.");
else if (argc < 3)
napi_throw_error(env, nullptr, "Y argument missing.");
else if (argc < 4)
napi_throw_error(env, nullptr, "WIDTH argument missing.");
else if (argc < 5)
napi_throw_error(env, nullptr, "HEIGHT argument missing.");
else
{
napi_valuetype HWNDType;
napi_valuetype XType;
napi_valuetype YType;
napi_valuetype WidthType;
napi_valuetype HeightType;
napi_typeof(env, argv[0], &HWNDType);
napi_typeof(env, argv[1], &XType);
napi_typeof(env, argv[2], &YType);
napi_typeof(env, argv[3], &WidthType);
napi_typeof(env, argv[4], &HeightType);
bool isHWNDNumber = HWNDType == napi_number;
bool isXNumber = XType == napi_number;
bool isYNumber = YType == napi_number;
bool isWidthNumber = WidthType == napi_number;
bool isHeightNumber = HeightType == napi_number;
if (!isHWNDNumber)
napi_throw_error(env, nullptr, "HWND argument must be an integer.");
else if (!isXNumber)
napi_throw_error(env, nullptr, "X argument must be an integer.");
else if (!isYNumber)
napi_throw_error(env, nullptr, "Y argument must be an integer.");
else if (!isWidthNumber)
napi_throw_error(env, nullptr, "WIDTH argument must be an integer.");
else if (!isHeightNumber)
napi_throw_error(env, nullptr, "HEIGHT argument must be an integer.");
else
{
int64_t hwnd64;
int32_t x32;
int32_t y32;
int32_t width32;
int32_t height32;
napi_get_value_int64(env, argv[0], &hwnd64);
napi_get_value_int32(env, argv[1], &x32);
napi_get_value_int32(env, argv[2], &y32);
napi_get_value_int32(env, argv[3], &width32);
napi_get_value_int32(env, argv[4], &height32);
HWND hwnd = (HWND)hwnd64;
int x = (int)x32;
int y = (int)y32;
int width = (int)width32;
int height = (int)height32;
SetWindowPos(hwnd, 0, x, y, width, height, 0x0020);
}
}
return nullptr;
}
napi_value init(napi_env env, napi_value exports)
{
napi_status status;
napi_value fn1;
napi_value fn2;
napi_value fn3;
status = napi_create_function(env, nullptr, 0, executeDwm, nullptr, &fn1);
if (status != napi_ok)
return nullptr;
status = napi_set_named_property(env, exports, "executeDwm", fn1);
if (status != napi_ok)
return nullptr;
status = napi_create_function(env, nullptr, 0, executeUser32, nullptr, &fn2);
if (status != napi_ok)
return nullptr;
status = napi_set_named_property(env, exports, "executeUser32", fn2);
if (status != napi_ok)
return nullptr;
status = napi_create_function(env, nullptr, 0, redraw, nullptr, &fn3);
if (status != napi_ok)
return nullptr;
status = napi_set_named_property(env, exports, "redraw", fn3);
if (status != napi_ok)
return nullptr;
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, init)
}
================================================
FILE: module/assets/dwm.cpp
================================================
/*
Copyright 2024 GregVido
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "dwm.h"
#include "winstyle.h"
#include <dwmapi.h>
HINSTANCE dwmapi;
pDwmSetWindowAttribute SetWindowAttribute;
pDwmExtendFrameIntoClientArea ExtendFrameIntoClientArea;
bool dwmEnabled = false;
void enableDWM()
{
dwmapi = LoadLibrary(TEXT("dwmapi.dll"));
SetWindowAttribute = (pDwmSetWindowAttribute)GetProcAddress(dwmapi, "DwmSetWindowAttribute");
ExtendFrameIntoClientArea = (pDwmExtendFrameIntoClientArea)GetProcAddress(dwmapi, "DwmExtendFrameIntoClientArea");
dwmEnabled = true;
}
void disableDWM()
{
FreeLibrary(dwmapi);
dwmEnabled = false;
}
void setAppTheme(int value, HWND hwnd)
{
if (dwmEnabled)
{
int useDarkTheme = 0x00;
// if dark mod, apply dark effect
if (value == 1 /* DARK */ || (value == 5 /* AUTO */ && !is_light_theme()))
useDarkTheme = 0x01;
SetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &useDarkTheme, sizeof(int));
}
}
bool applyMicaEffect(int type, HWND hwnd)
{
if(dwmEnabled) {
bool insider = isInsider();
if (insider)
SetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &type, sizeof(int));
else if (type > 2)
return false;
else
{
int micaEnable = 0x00;
if (type == 1)
micaEnable = 0x02;
else if (type == 2)
micaEnable = 0x01;
SetWindowAttribute(hwnd, DWMWA_MICA_EFFECT, &micaEnable, sizeof(int));
}
}
return true;
}
void setCorner(int type, HWND hwnd) {
if(dwmEnabled)
SetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &type, sizeof(int));
}
void setBorderColor(int type, HWND hwnd) {
if(dwmEnabled)
SetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &type, sizeof(int));
}
void setCaptionColor(int type, HWND hwnd) {
if(dwmEnabled)
SetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, &type, sizeof(int));
}
void setTextColor(int type, HWND hwnd) {
if(dwmEnabled)
SetWindowAttribute(hwnd, DWMWA_TEXT_COLOR, &type, sizeof(int));
}
void setMargin(int type, HWND hwnd) {
if(dwmEnabled) {
MARGINS margins;
if(type == 0)
margins = {-1};
else
margins = {};
ExtendFrameIntoClientArea(hwnd, &margins);
}
}
================================================
FILE: module/assets/dwm.h
================================================
#ifndef DWM_H
#define DWM_H
#define DWMWA_MICA_EFFECT DWORD(1029)
#define DWMWA_SYSTEMBACKDROP_TYPE DWORD(38)
#define DWMWA_USE_IMMERSIVE_DARK_MODE DWORD(20)
#define DWMWA_WINDOW_CORNER_PREFERENCE DWORD(33)
#define DWMWA_BORDER_COLOR DWORD(34)
#define DWMWA_CAPTION_COLOR DWORD(35)
#define DWMWA_TEXT_COLOR DWORD(36)
#endif
================================================
FILE: module/assets/types.h
================================================
#ifndef TYPE_H
#define TYPE_H
#define MICA_EFFECT 4
#define CORNER_TYPE 5
#define BORDER_COLOR 6
#define CAPTION_COLOR 7
#define TEXT_COLOR 8
#define WINDOW_EDIT 9
#define RESET_BORDER 0
#define ENABLE_MAXIMIZE 1
#define INTERCEPT_MSG 2
#define ENABLE_CAPTION 3
#define DISABLE_CAPTION 4
#define FOCUS_WINDOW 5
#define MARGIN_TYPE 10
#endif
================================================
FILE: module/assets/user32.cpp
================================================
/*
Copyright 2024 GregVido
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "winstyle.h"
HINSTANCE user32;
pSetWindowCompositionAttribute SetWindowCompositionAttributeUser32;
bool user32Enabled = false;
void enableUser32()
{
user32 = LoadLibrary(TEXT("user32.dll"));
SetWindowCompositionAttributeUser32 = (pSetWindowCompositionAttribute)GetProcAddress(user32, "SetWindowCompositionAttribute");
user32Enabled = true;
}
void disableUser32()
{
FreeLibrary(user32);
user32Enabled = false;
}
void resetBorderApp(HWND hwnd)
{
SetWindowLongA(hwnd, -16, 0x004F0000L);
}
void enableMaximizeBox(HWND hwnd)
{
LONG_PTR style = GetWindowLongA(hwnd, GWL_STYLE);
style |= WS_SIZEBOX;
style |= WS_THICKFRAME;
style |= WS_MAXIMIZEBOX;
SetWindowLongA(hwnd, GWL_STYLE, style);
}
void interceptMessage(HWND hwnd)
{
originalWndProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WindowProc);
}
void disableCaption(HWND hwnd)
{
LONG_PTR style = GetWindowLongA(hwnd, GWL_STYLE);
style &= ~WS_CAPTION;
SetWindowLongA(hwnd, GWL_STYLE, style);
}
void enableCaption(HWND hwnd)
{
LONG_PTR style = GetWindowLongA(hwnd, GWL_STYLE);
style |= WS_CAPTION;
SetWindowLongA(hwnd, GWL_STYLE, style);
}
void applyWindows10Effect(int nAccentState, int nColor, HWND hwnd)
{
if (user32Enabled)
{
ACCENTPOLICY policy;
policy.nAccentState = nAccentState;
policy.nFlags = 2;
policy.nColor = nColor;
policy.nAnimationId = 0;
WINCOMATTRPDATA data;
data.nAttribute = 19;
data.pData = &policy;
data.ulDataSize = sizeof(policy);
SetWindowCompositionAttributeUser32(hwnd, &data);
}
}
================================================
FILE: module/assets/win.cpp
================================================
/*
Copyright 2024 GregVido
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <dwmapi.h>
#include <vector>
#include <string>
#include <stdexcept>
WNDPROC originalWndProc;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SYSCOMMAND:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
case WM_SIZE:
/*
if (wParam == SIZE_MAXIMIZED)
return DefWindowProc(hwnd, uMsg, wParam, lParam);*/
return CallWindowProc(originalWndProc, hwnd, uMsg, wParam, lParam);
default:
return CallWindowProc(originalWndProc, hwnd, uMsg, wParam, lParam);
}
}
DWORD getBuild()
{
DWORD dwVersion = 0;
DWORD dwMajorVersion = 0;
DWORD dwMinorVersion = 0;
DWORD dwBuild = 0;
dwVersion = GetVersion();
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if (dwVersion < 0x80000000)
dwBuild = (DWORD)(HIWORD(dwVersion));
return dwBuild;
}
bool isInsider()
{
return getBuild() >= 22621;
}
bool isWin11()
{
return getBuild() >= 22000;
}
bool is_light_theme()
{
// based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application
// The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian
auto buffer = std::vector<char>(4);
auto cbData = static_cast<DWORD>(buffer.size() * sizeof(char));
auto res = RegGetValueW(
HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
L"AppsUseLightTheme",
RRF_RT_REG_DWORD, // expected value type
nullptr,
buffer.data(),
&cbData);
if (res != ERROR_SUCCESS)
{
throw std::runtime_error("Error: error_code=" + std::to_string(res));
}
// convert bytes written to our buffer to an int, assuming little-endian
auto i = int(buffer[3] << 24 |
buffer[2] << 16 |
buffer[1] << 8 |
buffer[0]);
return i == 1;
}
================================================
FILE: module/assets/winstyle.h
================================================
#include <dwmapi.h>
#ifndef WIN_STYLE_H
#define WIN_STYLE_H
struct ACCENTPOLICY
{
int nAccentState;
int nFlags;
int nColor;
int nAnimationId;
};
struct WINCOMATTRPDATA
{
int nAttribute;
PVOID pData;
ULONG ulDataSize;
};
typedef BOOL(WINAPI *pSetWindowCompositionAttribute)(HWND, WINCOMATTRPDATA *);
typedef BOOL(WINAPI *pDwmSetWindowAttribute)(HWND, DWORD, int *, int);
typedef BOOL(WINAPI *pSetLayeredWindowAttributes)(HWND, int, byte, int);
typedef BOOL(WINAPI *pDwmExtendFrameIntoClientArea)(HWND, MARGINS *);
typedef BOOL(WINAPI *pSetWindowPos)(HWND, HWND, int, int, int, int, int);
typedef HWND(WINAPI *pSetWindowLongA)(HWND, int, long);
typedef LONG(WINAPI *pGetWindowLongA)(HWND, int);
#endif
================================================
FILE: package.json
================================================
{
"name": "mica-electron",
"version": "1.5.17",
"description": "Tool to add mica effect of windows 11 in electron app",
"main": "main.js",
"types": "./types/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/GregVido/mica-electron.git"
},
"keywords": [
"electron",
"mica",
"windows 11",
"acrylic",
"transparent",
"glasstron"
],
"author": "GregVido",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/GregVido/mica-electron/issues"
},
"homepage": "https://github.com/GregVido/mica-electron",
"devDependencies": {
"electron": "^33.2.1",
"@electron/rebuild": "^3.7.1"
}
}
================================================
FILE: types/index.d.ts
================================================
import "electron";
declare module "mica-electron" {
// TODO: rework CSS colors
// type HexColor = `#${string}`;
// type RGBColor = `rgb(${number}, ${number}, ${number})`;
// type CSSColor = string;
export class MicaBrowserWindow extends Electron.BrowserWindow {
/**
* Current theme value, represented by an integer
*/
public theme: number;
/**
* Current effect value, represented by an integer
*/
public effect: number;
/**
* Shows whether this window is using DWM or User32
*/
public useDWM: boolean;
/**
* Shows whether this window is frameless
*/
public hasFrameless: boolean;
/**
* Disable transparent for mica effect
*/
public disableMargin(): void;
/**
* Enable transparent for mica effect
*/
public enableMargin(): void;
/**
* Apply the Mica effect (Windows 11 only)
*/
public setMicaEffect(): void;
/**
* Apply the Tabbed Mica effect (Windows 11 only)
*/
public setMicaTabbedEffect(): void
/**
* Apply the Acrylic effect (Windows 11 only)
*/
public setMicaAcrylicEffect(): void;
/**
* Change theme to dark
*/
public setDarkTheme(): void;
/**
* Change theme to light
*/
public setLightTheme(): void;
/**
* Make theme automatically adapt to the system
*/
public setAutoTheme(): void;
/**
* Set corner radius to normal (Windows 11 only)
*/
public setRoundedCorner(): void;
/**
* Set corner radius to small (Windows 11 only)
*/
public setSmallRoundedCorner(): void;
/**
* Set corner radius to 0 (Windows 11 only)
*/
public setSquareCorner(): void;
/**
* Change window's border color
*/
public setBorderColor(color: string): void;
/**
* Change window's titlebar color
*/
public setCaptionColor(color: string): void;
/**
* Change window's title text color
*/
public setTitleTextColor(color: string): void;
/**
* Apply the Transparent Effect (Windows 7+)
*/
public setTransparent(): void;
/**
* Apply the Blur Effect (Windows 7+)
*/
public setBlur(): void;
/**
* Apply the Acrylic Effect (Windows 7+)
*/
public setAcrylic(): void;
/**
* Apply a custom effect of SetWindowCompositionAttribute (Windows 7+)
*/
public setCustomEffect(nAccentState: number, color: string, alpha: number): void;
/**
* Disables support for Windows 10 effects (Acrylic and Blur)
*/
public disableUser32(): void;
/**
* Disables support for Windows 11 effects (Mica and Acrylic)
*/
public disableDWM(): void;
/**
* Executes the `DwmSetWindowAttribute` function from `dwmapi.dll`
*/
public executeDwm(params: number, value: number): void;
/**
* Executes the `SetWindowCompositionAttribute` function from `user32.dll`
*/
public executeUser32(params: number, value: number): void;
}
/**
* Shows if the machine is running Windows 11
*/
export const IS_WINDOWS_11: boolean;
/**
* Values specifying several window properties
*/
export const PARAMS: {
/**
* Effects configuration
*/
BACKGROUND: {
AUTO: 0,
NONE: 1,
/**
* Acrylic Effect
*/
ACRYLIC: 3,
/**
* Mica Effect
*/
MICA: 2,
/**
* Mica Tabbed Effect
*/
TABBED_MICA: 4
},
/**
* Corner radius configuration
*/
CORNER: 5,
/**
* Border color configuration
*/
BORDER_COLOR: 6,
/**
* Titlebar color configuration
*/
CAPTION_COLOR: 7,
/**
* Text color configuration
*/
TEXT_COLOR: 8,
FRAME: 9,
MARGIN: 10
};
/**
* Values which can be used in several effects
*/
export const VALUE: {
/**
* Theme values
*/
THEME: {
/**
* Automatic theme
*/
AUTO: 5,
/**
* Dark theme
*/
DARK: 1,
/**
* Light theme
*/
LIGHT: 2,
},
/**
* Corner radius values
*/
CORNER: {
/**
* Default corners
*/
DEFAULT: 0,
/**
* Square corners
*/
DONOTROUND: 1,
/**
* Rounded corners
*/
ROUND: 2,
/**
* Small rounded corners
*/
ROUNDSMALL: 3
},
/**
* Color values
*/
COLOR: {
RED: 0x000000FF,
GREEN: 0x0000FF00,
BLUE: 0x00FF0000,
BLACK: 0x00000000,
WHITE: 0x00FFFFFF,
/**
* Convert red, green and blue values into a single hex color
*/
FROM_RGB: (red: number, green: number, blue: number) => number
},
/**
* Falsely value
*/
FALSE: 0,
/**
* Truthful value
*/
TRUE: 1
};
/**
* Windows 10 effects
*/
export const WIN10: {
/**
* Transparent Effect
*/
TRANSPARENT: 2,
/**
* Blur Effect
*/
BLURBEHIND: 3,
/**
* Acrylic Effect
*/
ACRYLIC: 4
}
}
gitextract_n378x8h9/
├── .gitignore
├── LICENSE
├── README.md
├── build.bat
├── data
├── exemple.js
├── files/
│ ├── css/
│ │ ├── dark.css
│ │ └── styles.css
│ ├── index.html
│ └── js/
│ └── scripts.js
├── main.js
├── module/
│ ├── app.cpp
│ └── assets/
│ ├── dwm.cpp
│ ├── dwm.h
│ ├── types.h
│ ├── user32.cpp
│ ├── win.cpp
│ └── winstyle.h
├── package.json
├── src/
│ ├── micaElectron_arm64.node
│ ├── micaElectron_ia32.node
│ └── micaElectron_x64.node
└── types/
└── index.d.ts
SYMBOL INDEX (74 symbols across 8 files)
FILE: files/js/scripts.js
function setTheme (line 7) | function setTheme(theme) {
function setEffect (line 17) | function setEffect(effect) {
function setParams (line 21) | function setParams(params, value) {
function htmlToColor (line 25) | function htmlToColor(color) {
FILE: main.js
constant IS_ELECTRON_RECENT_VERSION (line 22) | const IS_ELECTRON_RECENT_VERSION = process.versions.electron >= '27.0.0'...
function isWin11 (line 54) | function isWin11() {
constant WINDOWS_11 (line 61) | const WINDOWS_11 = isWin11();
function redrawFrame (line 67) | function redrawFrame(window) {
constant PARAMS (line 78) | const PARAMS = {
constant VALUE (line 94) | const VALUE = {
constant WIN10 (line 120) | const WIN10 = {
class BrowserWindow (line 167) | class BrowserWindow extends electron.BrowserWindow {
method constructor (line 190) | constructor(...args) {
method applyStyle (line 258) | applyStyle() {
method interceptMessage (line 265) | interceptMessage() {
method removeCaption (line 272) | removeCaption() {
method disableMargin (line 279) | disableMargin() {
method enableMargin (line 293) | enableMargin() {
method alwaysFocused (line 321) | alwaysFocused(enable) {
method setMicaEffect (line 331) | setMicaEffect() {
method setMicaTabbedEffect (line 340) | setMicaTabbedEffect() {
method setMicaAcrylicEffect (line 349) | setMicaAcrylicEffect() {
method setDarkTheme (line 358) | setDarkTheme() {
method setLightTheme (line 367) | setLightTheme() {
method setAutoTheme (line 376) | setAutoTheme() {
method setRoundedCorner (line 385) | setRoundedCorner() {
method setSmallRoundedCorner (line 392) | setSmallRoundedCorner() {
method setSquareCorner (line 399) | setSquareCorner() {
method setBorderColor (line 407) | setBorderColor(color) {
method setCaptionColor (line 420) | setCaptionColor(color) {
method setTitleTextColor (line 433) | setTitleTextColor(color) {
method setTransparent (line 445) | setTransparent() {
method setBlur (line 454) | setBlur() {
method setAcrylic (line 463) | setAcrylic() {
method setCustomEffect (line 475) | setCustomEffect(nAccentState, color, a) {
method disableUser32 (line 487) | disableUser32() {
method disableDWM (line 496) | disableDWM() {
method executeDwm (line 508) | executeDwm(params, value) {
method executeUser32 (line 525) | executeUser32(params, value) {
FILE: module/app.cpp
type micaElectron (line 29) | namespace micaElectron
function napi_value (line 32) | napi_value executeDwm(napi_env env, napi_callback_info args)
function napi_value (line 183) | napi_value executeUser32(napi_env env, napi_callback_info args)
function napi_value (line 248) | napi_value redraw(napi_env env, napi_callback_info args)
function napi_value (line 334) | napi_value init(napi_env env, napi_value exports)
FILE: module/assets/dwm.cpp
function enableDWM (line 27) | void enableDWM()
function disableDWM (line 36) | void disableDWM()
function setAppTheme (line 42) | void setAppTheme(int value, HWND hwnd)
function applyMicaEffect (line 56) | bool applyMicaEffect(int type, HWND hwnd)
function setCorner (line 84) | void setCorner(int type, HWND hwnd) {
function setBorderColor (line 89) | void setBorderColor(int type, HWND hwnd) {
function setCaptionColor (line 94) | void setCaptionColor(int type, HWND hwnd) {
function setTextColor (line 99) | void setTextColor(int type, HWND hwnd) {
function setMargin (line 104) | void setMargin(int type, HWND hwnd) {
FILE: module/assets/user32.cpp
function enableUser32 (line 25) | void enableUser32()
function disableUser32 (line 32) | void disableUser32()
function resetBorderApp (line 38) | void resetBorderApp(HWND hwnd)
function enableMaximizeBox (line 43) | void enableMaximizeBox(HWND hwnd)
function interceptMessage (line 54) | void interceptMessage(HWND hwnd)
function disableCaption (line 60) | void disableCaption(HWND hwnd)
function enableCaption (line 67) | void enableCaption(HWND hwnd)
function applyWindows10Effect (line 74) | void applyWindows10Effect(int nAccentState, int nColor, HWND hwnd)
FILE: module/assets/win.cpp
function LRESULT (line 25) | LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM ...
function DWORD (line 45) | DWORD getBuild()
function isInsider (line 63) | bool isInsider()
function isWin11 (line 68) | bool isWin11()
function is_light_theme (line 73) | bool is_light_theme()
FILE: module/assets/winstyle.h
type ACCENTPOLICY (line 6) | struct ACCENTPOLICY
type WINCOMATTRPDATA (line 14) | struct WINCOMATTRPDATA
type WINCOMATTRPDATA (line 21) | typedef BOOL(WINAPI *pSetWindowCompositionAttribute)(HWND, WINCOMATTRPDA...
type DWORD (line 22) | typedef BOOL(WINAPI *pDwmSetWindowAttribute)(HWND, DWORD, int *, int);
type byte (line 24) | typedef BOOL(WINAPI *pSetLayeredWindowAttributes)(HWND, int, byte, int);
type MARGINS (line 25) | typedef BOOL(WINAPI *pDwmExtendFrameIntoClientArea)(HWND, MARGINS *);
type HWND (line 27) | typedef BOOL(WINAPI *pSetWindowPos)(HWND, HWND, int, int, int, int, int);
FILE: types/index.d.ts
class MicaBrowserWindow (line 9) | class MicaBrowserWindow extends Electron.BrowserWindow {
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (74K chars).
[
{
"path": ".gitignore",
"chars": 33,
"preview": "node_modules\n.vscode\nbin\nbuild/**"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 7425,
"preview": "<h1 align=center>Mica Electron</h1>\n<div align=center>\n<img src=\"https://micadiscord.com/img/preview/title.png\" name=\"ex"
},
{
"path": "build.bat",
"chars": 4222,
"preview": "@echo off\n\nREM =========================\nREM ANSI colors\nREM =========================\nfor /f %%a in ('echo prompt $E ^|"
},
{
"path": "data",
"chars": 151,
"preview": "{\n \"targets\": [\n {\n \"target_name\": \"micaElectron\",\n \"sources\": [ \"module/app.cpp\" ]\n }\n ],\n 'variable"
},
{
"path": "exemple.js",
"chars": 3134,
"preview": "const { app, ipcMain } = require('electron');\nconst { PARAMS, VALUE, MicaBrowserWindow, IS_WINDOWS_11, WIN10 } = require"
},
{
"path": "files/css/dark.css",
"chars": 498,
"preview": "main,\nfieldset {\n background-color: #000000e3;\n border: 1px solid #353535;\n color: #fff;\n}\n\nfieldset {\n back"
},
{
"path": "files/css/styles.css",
"chars": 912,
"preview": "body {\n font-family: Arial, Helvetica, sans-serif;\n background-color: transparent;\n padding: 10px;\n}\n\nh1 {\n "
},
{
"path": "files/index.html",
"chars": 1811,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
},
{
"path": "files/js/scripts.js",
"chars": 1362,
"preview": "const { ipcRenderer } = require('electron');\n\nconst darkTheme = document.createElement('link');\ndarkTheme.rel = 'stylesh"
},
{
"path": "main.js",
"chars": 13755,
"preview": "/*\nCopyright 2024 GregVido\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file ex"
},
{
"path": "module/app.cpp",
"chars": 9805,
"preview": "/*\nCopyright 2024 GregVido\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file ex"
},
{
"path": "module/assets/dwm.cpp",
"chars": 2889,
"preview": "/*\nCopyright 2024 GregVido\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file ex"
},
{
"path": "module/assets/dwm.h",
"chars": 325,
"preview": "#ifndef DWM_H\n#define DWM_H\n\n#define DWMWA_MICA_EFFECT DWORD(1029)\n#define DWMWA_SYSTEMBACKDROP_TYPE DWORD(38)\n#define D"
},
{
"path": "module/assets/types.h",
"chars": 344,
"preview": "#ifndef TYPE_H\n#define TYPE_H\n\n#define MICA_EFFECT 4\n#define CORNER_TYPE 5\n#define BORDER_COLOR 6\n#define CAPTION_COLOR "
},
{
"path": "module/assets/user32.cpp",
"chars": 2254,
"preview": "/*\nCopyright 2024 GregVido\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file ex"
},
{
"path": "module/assets/win.cpp",
"chars": 2509,
"preview": "/*\nCopyright 2024 GregVido\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file ex"
},
{
"path": "module/assets/winstyle.h",
"chars": 713,
"preview": "#include <dwmapi.h>\n\n#ifndef WIN_STYLE_H\n#define WIN_STYLE_H\n\nstruct ACCENTPOLICY\n{\n\tint nAccentState;\n\tint nFlags;\n\tint"
},
{
"path": "package.json",
"chars": 759,
"preview": "{\n \"name\": \"mica-electron\",\n \"version\": \"1.5.17\",\n \"description\": \"Tool to add mica effect of windows 11 in electron "
},
{
"path": "types/index.d.ts",
"chars": 6137,
"preview": "import \"electron\";\n\ndeclare module \"mica-electron\" {\n // TODO: rework CSS colors\n // type HexColor = `#${string}`;"
}
]
// ... and 3 more files (download for full content)
About this extraction
This page contains the full source code of the GregVido/mica-electron GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 23 files (68.7 KB), approximately 17.9k tokens, and a symbol index with 74 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.