mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
Native window decorations: avoid using C-runtime, which reduces the DLL size from 100kb to 8kb
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,3 +9,5 @@ out/
|
|||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ library {
|
|||||||
compilerArgs.addAll( toolChain.map {
|
compilerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-O2" )
|
is Gcc, is Clang -> listOf( "-O2" )
|
||||||
is VisualCpp -> listOf( "/O2" )
|
is VisualCpp -> listOf( "/O2", "/Zl", "/GS-" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
@@ -70,8 +70,8 @@ library {
|
|||||||
val jawt = "${org.gradle.internal.jvm.Jvm.current().javaHome}/lib/jawt"
|
val jawt = "${org.gradle.internal.jvm.Jvm.current().javaHome}/lib/jawt"
|
||||||
linkerArgs.addAll( toolChain.map {
|
linkerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-l${jawt}", "-lUser32", "-lshell32", "-lAdvAPI32" )
|
is Gcc, is Clang -> listOf( "-l${jawt}", "-lUser32", "-lshell32", "-lAdvAPI32", "-lKernel32" )
|
||||||
is VisualCpp -> listOf( "${jawt}.lib", "User32.lib", "shell32.lib", "AdvAPI32.lib" )
|
is VisualCpp -> listOf( "${jawt}.lib", "User32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "/NODEFAULTLIB" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
|
|||||||
@@ -14,12 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <jawt.h>
|
#include <jawt.h>
|
||||||
#include <jawt_md.h>
|
#include <jawt_md.h>
|
||||||
#include <map>
|
|
||||||
#include "FlatWndProc.h"
|
#include "FlatWndProc.h"
|
||||||
#include "com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h"
|
#include "com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h"
|
||||||
|
|
||||||
@@ -50,7 +52,7 @@ jmethodID FlatWndProc::onNcHitTestMID;
|
|||||||
jmethodID FlatWndProc::isFullscreenMID;
|
jmethodID FlatWndProc::isFullscreenMID;
|
||||||
jmethodID FlatWndProc::fireStateChangedLaterOnceMID;
|
jmethodID FlatWndProc::fireStateChangedLaterOnceMID;
|
||||||
|
|
||||||
std::map<HWND, FlatWndProc*> FlatWndProc::hwndMap = std::map<HWND, FlatWndProc*>();
|
HWNDMap* FlatWndProc::hwndMap;
|
||||||
|
|
||||||
//---- class FlatWndProc methods ----------------------------------------------
|
//---- class FlatWndProc methods ----------------------------------------------
|
||||||
|
|
||||||
@@ -68,16 +70,20 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
|
|||||||
if( initialized < 0 )
|
if( initialized < 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// create HWND map
|
||||||
|
if( hwndMap == NULL )
|
||||||
|
hwndMap = new HWNDMap();
|
||||||
|
|
||||||
// get window handle
|
// get window handle
|
||||||
HWND hwnd = getWindowHandle( env, window );
|
HWND hwnd = getWindowHandle( env, window );
|
||||||
if( hwnd == NULL || hwndMap.count( hwnd ) > 0 )
|
if( hwnd == NULL || hwndMap->get( hwnd ) != NULL )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
FlatWndProc* fwp = new FlatWndProc();
|
FlatWndProc* fwp = new FlatWndProc();
|
||||||
env->GetJavaVM( &fwp->jvm );
|
env->GetJavaVM( &fwp->jvm );
|
||||||
fwp->obj = env->NewGlobalRef( obj );
|
fwp->obj = env->NewGlobalRef( obj );
|
||||||
fwp->hwnd = hwnd;
|
fwp->hwnd = hwnd;
|
||||||
hwndMap[hwnd] = fwp;
|
hwndMap->put( hwnd, fwp );
|
||||||
|
|
||||||
// replace window procedure
|
// replace window procedure
|
||||||
fwp->defaultWndProc = reinterpret_cast<WNDPROC>(
|
fwp->defaultWndProc = reinterpret_cast<WNDPROC>(
|
||||||
@@ -90,11 +96,14 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
|
void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
|
||||||
if( hwnd == NULL || hwndMap.count( hwnd ) == 0 )
|
if( hwnd == NULL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FlatWndProc* fwp = hwndMap[hwnd];
|
FlatWndProc* fwp = (FlatWndProc*) hwndMap->get( hwnd );
|
||||||
hwndMap.erase( hwnd );
|
if( fwp == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
hwndMap->remove( hwnd );
|
||||||
|
|
||||||
// restore original window procedure
|
// restore original window procedure
|
||||||
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc );
|
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc );
|
||||||
@@ -132,7 +141,7 @@ void FlatWndProc::updateFrame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
|
LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
|
||||||
FlatWndProc* fwp = hwndMap[hwnd];
|
FlatWndProc* fwp = (FlatWndProc*) hwndMap->get( hwnd );
|
||||||
return fwp->WindowProc( hwnd, uMsg, wParam, lParam );
|
return fwp->WindowProc( hwnd, uMsg, wParam, lParam );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +184,7 @@ LRESULT FlatWndProc::WmDestroy( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lPara
|
|||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
getEnv()->DeleteGlobalRef( obj );
|
getEnv()->DeleteGlobalRef( obj );
|
||||||
hwndMap.erase( hwnd );
|
hwndMap->remove( hwnd );
|
||||||
delete this;
|
delete this;
|
||||||
|
|
||||||
// call original AWT window procedure because it may fire window closed event in AwtWindow::WmDestroy()
|
// call original AWT window procedure because it may fire window closed event in AwtWindow::WmDestroy()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include "HWNDMap.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -31,7 +32,7 @@ private:
|
|||||||
static jmethodID isFullscreenMID;
|
static jmethodID isFullscreenMID;
|
||||||
static jmethodID fireStateChangedLaterOnceMID;
|
static jmethodID fireStateChangedLaterOnceMID;
|
||||||
|
|
||||||
static std::map<HWND, FlatWndProc*> hwndMap;
|
static HWNDMap* hwndMap;
|
||||||
|
|
||||||
JavaVM* jvm;
|
JavaVM* jvm;
|
||||||
JNIEnv* env; // attached to AWT-Windows/Win32 thread
|
JNIEnv* env; // attached to AWT-Windows/Win32 thread
|
||||||
|
|||||||
153
flatlaf-natives/flatlaf-natives-windows/src/main/cpp/HWNDMap.cpp
Normal file
153
flatlaf-natives/flatlaf-natives-windows/src/main/cpp/HWNDMap.cpp
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "HWNDMap.h"
|
||||||
|
|
||||||
|
#define DEFAULT_CAPACITY 20
|
||||||
|
#define INCREASE_CAPACITY 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
class LOCK {
|
||||||
|
LPCRITICAL_SECTION lpCriticalSection;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LOCK( LPCRITICAL_SECTION lpCriticalSection ) {
|
||||||
|
this->lpCriticalSection = lpCriticalSection;
|
||||||
|
::EnterCriticalSection( lpCriticalSection );
|
||||||
|
}
|
||||||
|
~LOCK() {
|
||||||
|
::LeaveCriticalSection( lpCriticalSection );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HWNDMap::HWNDMap() {
|
||||||
|
size = 0;
|
||||||
|
capacity = DEFAULT_CAPACITY;
|
||||||
|
table = new Entry[capacity];
|
||||||
|
|
||||||
|
::InitializeCriticalSection( &criticalSection );
|
||||||
|
|
||||||
|
// dump( "<init>" );
|
||||||
|
}
|
||||||
|
|
||||||
|
LPVOID HWNDMap::get( HWND key ) {
|
||||||
|
LOCK lock( &criticalSection );
|
||||||
|
|
||||||
|
int index = binarySearch( key );
|
||||||
|
return (index >= 0) ? table[index].value : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWNDMap::put( HWND key, LPVOID value ) {
|
||||||
|
LOCK lock( &criticalSection );
|
||||||
|
|
||||||
|
int index = binarySearch( key );
|
||||||
|
// printf( "put %p %p = %d --\n", key, value, index );
|
||||||
|
if( index >= 0 ) {
|
||||||
|
// key already in map --> replace
|
||||||
|
table[index].value = value;
|
||||||
|
} else {
|
||||||
|
// insert new key
|
||||||
|
ensureCapacity( size + 1 );
|
||||||
|
|
||||||
|
// make roor for new entry
|
||||||
|
index = -(index + 1);
|
||||||
|
for( int i = size - 1; i >= index; i-- )
|
||||||
|
table[i + 1] = table[i];
|
||||||
|
size++;
|
||||||
|
|
||||||
|
// insert entry
|
||||||
|
table[index].key = key;
|
||||||
|
table[index].value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump( "put" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWNDMap::remove( HWND key ) {
|
||||||
|
LOCK lock( &criticalSection );
|
||||||
|
|
||||||
|
// search for key
|
||||||
|
int index = binarySearch( key );
|
||||||
|
// printf( "remove %p = %d --\n", key, index );
|
||||||
|
if( index < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// remove entry
|
||||||
|
for( int i = index + 1; i < size; i++ )
|
||||||
|
table[i - 1] = table[i];
|
||||||
|
size--;
|
||||||
|
|
||||||
|
// dump( "remove" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int HWNDMap::binarySearch( HWND key ) {
|
||||||
|
int low = 0;
|
||||||
|
int high = size - 1;
|
||||||
|
|
||||||
|
while( low <= high ) {
|
||||||
|
int mid = (low + high) >> 1;
|
||||||
|
|
||||||
|
HWND midKey = table[mid].key;
|
||||||
|
int cmp = midKey - key;
|
||||||
|
if( cmp < 0 )
|
||||||
|
low = mid + 1;
|
||||||
|
else if( cmp > 0 )
|
||||||
|
high = mid - 1;
|
||||||
|
else
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -(low + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWNDMap::ensureCapacity( int minCapacity ) {
|
||||||
|
if( minCapacity <= capacity )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// allocate new table
|
||||||
|
int newCapacity = minCapacity + INCREASE_CAPACITY;
|
||||||
|
Entry* newTable = new Entry[newCapacity];
|
||||||
|
|
||||||
|
// copy old table to new table
|
||||||
|
for( int i = 0; i < capacity; i++ )
|
||||||
|
newTable[i] = table[i];
|
||||||
|
|
||||||
|
// delete old table
|
||||||
|
delete table;
|
||||||
|
|
||||||
|
table = newTable;
|
||||||
|
capacity = newCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void HWNDMap::dump( char* msg ) {
|
||||||
|
printf( "---- %s -----------------------\n", msg );
|
||||||
|
printf( "size %d\n", size );
|
||||||
|
printf( "capacity %d\n", capacity );
|
||||||
|
printf( "table %p\n", table );
|
||||||
|
|
||||||
|
for( int i = 0; i < capacity; i++ )
|
||||||
|
printf( " %d: %p - %p %s\n", i, table[i].key, table[i].value, i >= size ? "UNUSED" : "" );
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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 <windows.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple map that uses a sorted array to store key/value pairs.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
HWND key;
|
||||||
|
LPVOID value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HWNDMap
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int size; // used entries in table
|
||||||
|
int capacity; // total size of table
|
||||||
|
Entry* table;
|
||||||
|
|
||||||
|
// used to synchronize to make it thread safe
|
||||||
|
CRITICAL_SECTION criticalSection;
|
||||||
|
|
||||||
|
public:
|
||||||
|
HWNDMap();
|
||||||
|
|
||||||
|
LPVOID get( HWND key );
|
||||||
|
void put( HWND key, LPVOID value );
|
||||||
|
void remove( HWND key );
|
||||||
|
|
||||||
|
private:
|
||||||
|
int binarySearch( HWND key );
|
||||||
|
void ensureCapacity( int newCapacity );
|
||||||
|
|
||||||
|
// void dump( char* msg );
|
||||||
|
};
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methods that replace C-runtime methods and allow linking/running without C-runtime.
|
||||||
|
*
|
||||||
|
* WARNING: Constructors/destructors of static objects are not invoked!
|
||||||
|
*
|
||||||
|
* https://documentation.help/Far-Manager/msdnmag-issues-01-01-hood-default.aspx.html
|
||||||
|
* www.catch22.net/tuts/win32/reducing-executable-size#the-c-runtime-and-default-libraries
|
||||||
|
* https://www.mvps.org/user32/nocrt.html
|
||||||
|
*
|
||||||
|
* see also LIBCTINY on "Downloads" page here: http://www.wheaty.net/
|
||||||
|
* or https://github.com/leepa/libctiny
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
BOOL WINAPI _DllMainCRTStartup( HINSTANCE instance, DWORD reason, LPVOID reserved ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* __cdecl operator new( size_t cb ) {
|
||||||
|
return ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, cb );
|
||||||
|
}
|
||||||
|
|
||||||
|
void* __cdecl operator new[]( size_t cb ) {
|
||||||
|
return ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, cb );
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl operator delete( void* pv, size_t cb ) {
|
||||||
|
if( pv != NULL )
|
||||||
|
::HeapFree( ::GetProcessHeap(), 0, pv );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern "C"
|
||||||
|
int __cdecl printf( const char* format, ... ) {
|
||||||
|
char szBuff[1024];
|
||||||
|
int retValue;
|
||||||
|
DWORD cbWritten;
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start( argptr, format );
|
||||||
|
retValue = wvsprintfA( szBuff, format, argptr );
|
||||||
|
va_end( argptr );
|
||||||
|
|
||||||
|
WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), szBuff, retValue, &cbWritten, NULL );
|
||||||
|
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user