Unverified Commit b508c81c authored by Manuel Unterhofer's avatar Manuel Unterhofer Committed by GitHub

Extend `SkiaLayer.disableTitleBar` to set up a custom window header (#315)

* Extend `SkiaLayer.disableTitleBar` with a parameter that contains the custom header height

The custom header height is used to align the traffic lights within the custom header

* Update PlatformOperations.kt to match the new signature

* Adjust draggable area

* Zoom on double-click

* Restore default controls when entering full screen via our own API

* Restore default controls when entering full screen

* Remove redundant code
parent 7d7fa80a
...@@ -115,6 +115,8 @@ fun createWindow(title: String, exitOnClose: Boolean) = SwingUtilities.invokeLat ...@@ -115,6 +115,8 @@ fun createWindow(title: String, exitOnClose: Boolean) = SwingUtilities.invokeLat
// MANDATORY: set window preferred size before calling pack() // MANDATORY: set window preferred size before calling pack()
window.preferredSize = Dimension(800, 600) window.preferredSize = Dimension(800, 600)
window.pack() window.pack()
skiaLayer.disableTitleBar(64f)
window.pack()
skiaLayer.paint(window.graphics) skiaLayer.paint(window.graphics)
window.isVisible = true window.isVisible = true
} }
...@@ -69,6 +69,10 @@ internal open class HardwareLayer( ...@@ -69,6 +69,10 @@ internal open class HardwareLayer(
get() = platformOperations.isFullscreen(this) get() = platformOperations.isFullscreen(this)
set(value) = platformOperations.setFullscreen(this, value) set(value) = platformOperations.setFullscreen(this, value)
fun disableTitleBar(customHeaderHeight: Float) {
platformOperations.disableTitleBar(this, customHeaderHeight)
}
private external fun getContentHandle(platformInfo: Long): Long private external fun getContentHandle(platformInfo: Long): Long
private external fun getWindowHandle(platformInfo: Long): Long private external fun getWindowHandle(platformInfo: Long): Long
......
...@@ -7,7 +7,7 @@ import javax.swing.SwingUtilities ...@@ -7,7 +7,7 @@ import javax.swing.SwingUtilities
internal interface PlatformOperations { internal interface PlatformOperations {
fun isFullscreen(component: Component): Boolean fun isFullscreen(component: Component): Boolean
fun setFullscreen(component: Component, value: Boolean) fun setFullscreen(component: Component, value: Boolean)
fun disableTitleBar(platformInfo: Long) fun disableTitleBar(component: Component, headerHeight: Float)
fun orderEmojiAndSymbolsPopup() fun orderEmojiAndSymbolsPopup()
fun getDpiScale(component: Component): Float fun getDpiScale(component: Component): Float
} }
...@@ -27,8 +27,8 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -27,8 +27,8 @@ internal val platformOperations: PlatformOperations by lazy {
return component.graphicsConfiguration.defaultTransform.scaleX.toFloat() return component.graphicsConfiguration.defaultTransform.scaleX.toFloat()
} }
override fun disableTitleBar(platformInfo: Long) { override fun disableTitleBar(component: Component, headerHeight: Float) {
osxDisableTitleBar(platformInfo) osxDisableTitleBar(component, headerHeight)
} }
override fun orderEmojiAndSymbolsPopup() { override fun orderEmojiAndSymbolsPopup() {
...@@ -49,7 +49,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -49,7 +49,7 @@ internal val platformOperations: PlatformOperations by lazy {
device.setFullScreenWindow(if (value) window else null) device.setFullScreenWindow(if (value) window else null)
} }
override fun disableTitleBar(platformInfo: Long) { override fun disableTitleBar(component: Component, headerHeight: Float) {
} }
override fun orderEmojiAndSymbolsPopup() { override fun orderEmojiAndSymbolsPopup() {
...@@ -74,7 +74,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -74,7 +74,7 @@ internal val platformOperations: PlatformOperations by lazy {
device.setFullScreenWindow(if (value) window else null) device.setFullScreenWindow(if (value) window else null)
} }
override fun disableTitleBar(platformInfo: Long) { override fun disableTitleBar(component: Component, headerHeight: Float) {
} }
override fun orderEmojiAndSymbolsPopup() { override fun orderEmojiAndSymbolsPopup() {
...@@ -94,7 +94,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -94,7 +94,7 @@ internal val platformOperations: PlatformOperations by lazy {
// OSX // OSX
external private fun osxIsFullscreenNative(component: Component): Boolean external private fun osxIsFullscreenNative(component: Component): Boolean
external private fun osxSetFullscreenNative(component: Component, value: Boolean) external private fun osxSetFullscreenNative(component: Component, value: Boolean)
external private fun osxDisableTitleBar(platformInfo: Long) external private fun osxDisableTitleBar(component: Component, headerHeight: Float)
external private fun osxOrderEmojiAndSymbolsPopup() external private fun osxOrderEmojiAndSymbolsPopup()
// Linux // Linux
......
...@@ -526,10 +526,8 @@ actual open class SkiaLayer internal constructor( ...@@ -526,10 +526,8 @@ actual open class SkiaLayer internal constructor(
} }
} }
fun SkiaLayer.disableTitleBar() { fun SkiaLayer.disableTitleBar(customHeaderHeight: Float) {
backedLayer.useDrawingSurfacePlatformInfo { backedLayer.disableTitleBar(customHeaderHeight)
platformOperations.disableTitleBar(it)
}
} }
fun orderEmojiAndSymbolsPopup() { fun orderEmojiAndSymbolsPopup() {
......
...@@ -8,6 +8,28 @@ ...@@ -8,6 +8,28 @@
#import <Metal/Metal.h> #import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h> #import <QuartzCore/CAMetalLayer.h>
@interface WindowDragView : NSView
@end
@implementation WindowDragView
- (void)mouseDown:(NSEvent *)event
{
[self.window performWindowDragWithEvent:event];
[super mouseDown:event];
}
- (void)mouseUp:(NSEvent *)event
{
if (event.clickCount == 2)
{
[self.window performZoom:nil];
}
[super mouseUp:event];
}
@end
@interface LayerHandler : NSObject @interface LayerHandler : NSObject
@property jobject canvasGlobalRef; @property jobject canvasGlobalRef;
...@@ -17,6 +39,10 @@ ...@@ -17,6 +39,10 @@
@end @end
@implementation LayerHandler @implementation LayerHandler
{
BOOL _titlebarDisabled;
CGFloat _customHeaderHeight;
}
- (id) init - (id) init
{ {
...@@ -27,19 +53,141 @@ ...@@ -27,19 +53,141 @@
self.canvasGlobalRef = NULL; self.canvasGlobalRef = NULL;
self.container = nil; self.container = nil;
self.window = nil; self.window = nil;
_titlebarDisabled = NO;
} }
return self; return self;
} }
-(void) dealloc { -(void) dealloc
{
self.canvasGlobalRef = NULL; self.canvasGlobalRef = NULL;
[self.container release]; [self.container release];
[self.window release]; [self.window release];
[super dealloc]; [super dealloc];
} }
- (BOOL) isFullScreen { - (void) setUpCustomHeader
{
NSView* themeFrame = self.window.contentView.superview;
NSView* titlebarContainer = [self.window standardWindowButton:NSWindowCloseButton].superview.superview;
NSView* titlebar = titlebarContainer.subviews[0];
NSView* titlebarDecoration = titlebarContainer.subviews[1];
NSView* titlebarVisualEffect = titlebar.subviews[0];
NSView* titlebarBackground = titlebar.subviews[1];
NSView* dragger = [[WindowDragView alloc] init];
[titlebarBackground addSubview:dragger];
titlebarContainer.translatesAutoresizingMaskIntoConstraints = NO;
titlebarDecoration.translatesAutoresizingMaskIntoConstraints = NO;
titlebar.translatesAutoresizingMaskIntoConstraints = NO;
titlebarVisualEffect.translatesAutoresizingMaskIntoConstraints = NO;
titlebarBackground.translatesAutoresizingMaskIntoConstraints = NO;
dragger.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[titlebarBackground.leftAnchor constraintEqualToAnchor:themeFrame.leftAnchor],
[titlebarBackground.rightAnchor constraintEqualToAnchor:themeFrame.rightAnchor],
[titlebarBackground.topAnchor constraintEqualToAnchor:themeFrame.topAnchor],
[titlebarBackground.heightAnchor constraintEqualToConstant:_customHeaderHeight],
[titlebarVisualEffect.leftAnchor constraintEqualToAnchor:titlebarBackground.leftAnchor],
[titlebarVisualEffect.rightAnchor constraintEqualToAnchor:titlebarBackground.rightAnchor],
[titlebarVisualEffect.topAnchor constraintEqualToAnchor:titlebarBackground.topAnchor],
[titlebarVisualEffect.bottomAnchor constraintEqualToAnchor:titlebarBackground.bottomAnchor],
[titlebar.leftAnchor constraintEqualToAnchor:titlebarBackground.leftAnchor],
[titlebar.widthAnchor constraintEqualToAnchor:titlebarBackground.widthAnchor],
[titlebar.topAnchor constraintEqualToAnchor:titlebarBackground.topAnchor],
[titlebar.heightAnchor constraintEqualToAnchor:titlebarBackground.heightAnchor],
[titlebarDecoration.leftAnchor constraintEqualToAnchor:titlebarBackground.leftAnchor],
[titlebarDecoration.widthAnchor constraintEqualToAnchor:titlebarBackground.widthAnchor],
[titlebarDecoration.topAnchor constraintEqualToAnchor:titlebarBackground.topAnchor],
[titlebarDecoration.heightAnchor constraintEqualToAnchor:titlebarBackground.heightAnchor],
[titlebarContainer.leftAnchor constraintEqualToAnchor:titlebar.leftAnchor],
[titlebarContainer.rightAnchor constraintEqualToAnchor:titlebar.rightAnchor],
[titlebarContainer.topAnchor constraintEqualToAnchor:titlebar.topAnchor],
[titlebarContainer.heightAnchor constraintEqualToAnchor:titlebar.heightAnchor],
[dragger.leftAnchor constraintEqualToAnchor:titlebarBackground.leftAnchor],
[dragger.rightAnchor constraintEqualToAnchor:titlebarBackground.rightAnchor],
[dragger.topAnchor constraintEqualToAnchor:titlebarBackground.topAnchor],
[dragger.bottomAnchor constraintEqualToAnchor:titlebarBackground.bottomAnchor],
]];
NSView* closeButtonView = [self.window standardWindowButton:NSWindowCloseButton];
NSView* miniaturizeButtonView = [self.window standardWindowButton:NSWindowMiniaturizeButton];
NSView* zoomButtonView = [self.window standardWindowButton:NSWindowZoomButton];
CGFloat horizontalButtonOffset = 20.0;
NSArray* windowButtons = @[ closeButtonView, miniaturizeButtonView, zoomButtonView ];
for (NSUInteger i = 0; i < windowButtons.count; i++) {
NSView* button = [windowButtons objectAtIndex:i];
button.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[button.centerYAnchor constraintEqualToAnchor:titlebar.centerYAnchor],
[button.centerXAnchor constraintEqualToAnchor:titlebar.leftAnchor constant:(_customHeaderHeight/2.0 + (i * horizontalButtonOffset))],
]];
}
}
- (void) resetHeader
{
NSView* titlebarContainer = [self.window standardWindowButton:NSWindowCloseButton].superview.superview;
NSView* titlebar = titlebarContainer.subviews[0];
NSView* titlebarDecoration = titlebarContainer.subviews[1];
NSView* titlebarVisualEffect = titlebar.subviews[0];
NSView* titlebarBackground = titlebar.subviews[1];
NSView* closeButtonView = [self.window standardWindowButton:NSWindowCloseButton];
NSView* miniaturizeButtonView = [self.window standardWindowButton:NSWindowMiniaturizeButton];
NSView* zoomButtonView = [self.window standardWindowButton:NSWindowZoomButton];
NSArray* changedViews = @[titlebarContainer, titlebarDecoration, titlebar, titlebarVisualEffect, titlebarBackground, closeButtonView, miniaturizeButtonView, zoomButtonView];
for (NSView* changedView in changedViews)
{
[changedView removeConstraints:changedView.constraints];
changedView.translatesAutoresizingMaskIntoConstraints = YES;
}
NSView* dragger = titlebar.subviews[1].subviews[0];
[dragger removeFromSuperview];
}
- (void) setWindowControlsHidden: (BOOL) hidden
{
[self.window standardWindowButton:NSWindowCloseButton].superview.hidden = hidden;
}
- (void) disableTitlebar: (CGFloat) customHeaderHeight
{
_customHeaderHeight = customHeaderHeight;
dispatch_sync(dispatch_get_main_queue(), ^{
[self.window setTitlebarAppearsTransparent:YES];
[self.window setTitleVisibility:NSWindowTitleHidden];
[self.window setStyleMask:[self.window styleMask]|NSWindowStyleMaskFullSizeContentView];
if (!self.isFullScreen) {
[self setUpCustomHeader];
}
});
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
[defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.window queue:mainQueue usingBlock:^(NSNotification* notification) {
[self resetHeader];
}];
[defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.window queue:mainQueue usingBlock:^(NSNotification* notification) {
[self setWindowControlsHidden:YES];
}];
[defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.window queue:mainQueue usingBlock:^(NSNotification* notification) {
[self setUpCustomHeader];
[self setWindowControlsHidden:NO];
}];
_titlebarDisabled = YES;
}
- (BOOL) isFullScreen
{
NSUInteger masks = [self.window styleMask]; NSUInteger masks = [self.window styleMask];
return (masks & NSWindowStyleMaskFullScreen) != 0; return (masks & NSWindowStyleMaskFullScreen) != 0;
} }
...@@ -177,15 +325,13 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentHandle( ...@@ -177,15 +325,13 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentHandle(
return (jlong)window; return (jlong)window;
} }
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_PlatformOperationsKt_osxDisableTitleBar(JNIEnv *env, jobject properties, jlong platformInfoPtr) JNIEXPORT void JNICALL Java_org_jetbrains_skiko_PlatformOperationsKt_osxDisableTitleBar(JNIEnv *env, jobject properties, jobject component, jfloat customHeaderHeight)
{ {
NSWindow* window = findWindow(platformInfoPtr); LayerHandler *layer = findByObject(env, component);
if (window == nil) return; if (layer != NULL)
dispatch_sync(dispatch_get_main_queue(), ^{ {
[window setTitlebarAppearsTransparent:YES]; [layer disableTitlebar:((CGFloat) customHeaderHeight)];
[window setTitleVisibility:NSWindowTitleHidden]; }
[window setStyleMask:[window styleMask]|NSWindowStyleMaskFullSizeContentView];
});
} }
JNIEXPORT jint JNICALL Java_org_jetbrains_skiko_SystemTheme_1jvmKt_getCurrentSystemTheme(JNIEnv *env, jobject topLevel) JNIEXPORT jint JNICALL Java_org_jetbrains_skiko_SystemTheme_1jvmKt_getCurrentSystemTheme(JNIEnv *env, jobject topLevel)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment