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
// MANDATORY: set window preferred size before calling pack()
window.preferredSize = Dimension(800, 600)
window.pack()
skiaLayer.disableTitleBar(64f)
window.pack()
skiaLayer.paint(window.graphics)
window.isVisible = true
}
......@@ -69,6 +69,10 @@ internal open class HardwareLayer(
get() = platformOperations.isFullscreen(this)
set(value) = platformOperations.setFullscreen(this, value)
fun disableTitleBar(customHeaderHeight: Float) {
platformOperations.disableTitleBar(this, customHeaderHeight)
}
private external fun getContentHandle(platformInfo: Long): Long
private external fun getWindowHandle(platformInfo: Long): Long
......
......@@ -7,7 +7,7 @@ import javax.swing.SwingUtilities
internal interface PlatformOperations {
fun isFullscreen(component: Component): Boolean
fun setFullscreen(component: Component, value: Boolean)
fun disableTitleBar(platformInfo: Long)
fun disableTitleBar(component: Component, headerHeight: Float)
fun orderEmojiAndSymbolsPopup()
fun getDpiScale(component: Component): Float
}
......@@ -27,8 +27,8 @@ internal val platformOperations: PlatformOperations by lazy {
return component.graphicsConfiguration.defaultTransform.scaleX.toFloat()
}
override fun disableTitleBar(platformInfo: Long) {
osxDisableTitleBar(platformInfo)
override fun disableTitleBar(component: Component, headerHeight: Float) {
osxDisableTitleBar(component, headerHeight)
}
override fun orderEmojiAndSymbolsPopup() {
......@@ -49,7 +49,7 @@ internal val platformOperations: PlatformOperations by lazy {
device.setFullScreenWindow(if (value) window else null)
}
override fun disableTitleBar(platformInfo: Long) {
override fun disableTitleBar(component: Component, headerHeight: Float) {
}
override fun orderEmojiAndSymbolsPopup() {
......@@ -74,7 +74,7 @@ internal val platformOperations: PlatformOperations by lazy {
device.setFullScreenWindow(if (value) window else null)
}
override fun disableTitleBar(platformInfo: Long) {
override fun disableTitleBar(component: Component, headerHeight: Float) {
}
override fun orderEmojiAndSymbolsPopup() {
......@@ -94,7 +94,7 @@ internal val platformOperations: PlatformOperations by lazy {
// OSX
external private fun osxIsFullscreenNative(component: Component): 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()
// Linux
......
......@@ -526,10 +526,8 @@ actual open class SkiaLayer internal constructor(
}
}
fun SkiaLayer.disableTitleBar() {
backedLayer.useDrawingSurfacePlatformInfo {
platformOperations.disableTitleBar(it)
}
fun SkiaLayer.disableTitleBar(customHeaderHeight: Float) {
backedLayer.disableTitleBar(customHeaderHeight)
}
fun orderEmojiAndSymbolsPopup() {
......
......@@ -8,6 +8,28 @@
#import <Metal/Metal.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
@property jobject canvasGlobalRef;
......@@ -17,6 +39,10 @@
@end
@implementation LayerHandler
{
BOOL _titlebarDisabled;
CGFloat _customHeaderHeight;
}
- (id) init
{
......@@ -27,19 +53,141 @@
self.canvasGlobalRef = NULL;
self.container = nil;
self.window = nil;
_titlebarDisabled = NO;
}
return self;
}
-(void) dealloc {
-(void) dealloc
{
self.canvasGlobalRef = NULL;
[self.container release];
[self.window release];
[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];
return (masks & NSWindowStyleMaskFullScreen) != 0;
}
......@@ -177,15 +325,13 @@ JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_HardwareLayer_getContentHandle(
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);
if (window == nil) return;
dispatch_sync(dispatch_get_main_queue(), ^{
[window setTitlebarAppearsTransparent:YES];
[window setTitleVisibility:NSWindowTitleHidden];
[window setStyleMask:[window styleMask]|NSWindowStyleMaskFullSizeContentView];
});
LayerHandler *layer = findByObject(env, component);
if (layer != NULL)
{
[layer disableTitlebar:((CGFloat) customHeaderHeight)];
}
}
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