Skip to content

Commit

Permalink
feat: improve the 3 colored buttons when hovering (closes #516)
Browse files Browse the repository at this point in the history
  • Loading branch information
lwouis committed Aug 26, 2020
1 parent 078bce5 commit 208ee4f
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 12 deletions.
26 changes: 22 additions & 4 deletions alt-tab-macos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
BF0C829583ED47E458528F3A /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C889529FF19620EDAC295 /* [email protected] */; };
BF0C83E902F75A97E8FD374A /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8D3333653ACAEF730DD8 /* [email protected] */; };
BF0C8406805BDEC5B69E8803 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8E25373671B528AD448D /* [email protected] */; };
BF0C8477850829E15FD4DD43 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8F9CE1699644A22EAF2C /* [email protected] */; };
BF0C852D28E458CDD6FA3E44 /* app.icns in Resources */ = {isa = PBXBuildFile; fileRef = BF0C84E11784B3B0900D0963 /* app.icns */; };
BF0C89DF22C7B7D0C27DA2A4 /* WindowControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C884157B87BF0E17EF7F8 /* WindowControlView.swift */; };
BF0C8C9CA44285E493918A74 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8E54658B4DAEA0528200 /* [email protected] */; };
BF0C8CB668FFABBCA23880B6 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C817D9C335EE4A0536601 /* [email protected] */; };
BF0C8F80281B50D57C95ECCF /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = BF0C83BD867F6A874F9953C9 /* [email protected] */; };
BF0C8FA2D756D3258E3A16B6 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C81DF55C6B0A279CE0FE1 /* Localizable.strings */; };
D04BA004884A273D4D2D3EF1 /* HelperExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAD91161791D42FEC4A60 /* HelperExtensions.swift */; };
D04BA0182F4734A5C8BB63DC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA5461DAEE9B5350C3020 /* Localizable.strings */; };
Expand Down Expand Up @@ -124,13 +128,17 @@
481FE54624D2D387001032F1 /* alt-tab-macos-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "alt-tab-macos-Bridging-Header.h"; sourceTree = "<group>"; };
59DD4BE63D42EEFF1182BA7F /* Pods-alt-tab-macos.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-alt-tab-macos.release.xcconfig"; path = "Target Support Files/Pods-alt-tab-macos/Pods-alt-tab-macos.release.xcconfig"; sourceTree = "<group>"; };
672F94799CC7C90282AEB3EA /* Pods-alt-tab-macos.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-alt-tab-macos.debug.xcconfig"; path = "Target Support Files/Pods-alt-tab-macos/Pods-alt-tab-macos.debug.xcconfig"; sourceTree = "<group>"; };
BF0C817D9C335EE4A0536601 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
BF0C81B8A30416D774B5B60E /* fullscreen.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = fullscreen.svg; sourceTree = "<group>"; };
BF0C81C1B55A0519C3272B09 /* close.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = close.svg; sourceTree = "<group>"; };
BF0C828AF7BCC4F47E70B28F /* menubar-2.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "menubar-2.svg"; sourceTree = "<group>"; };
BF0C833D471343CEA3DEFE56 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
BF0C83BD867F6A874F9953C9 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
BF0C843C2EDF4EF3A7A2C64A /* app.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = app.svg; sourceTree = "<group>"; };
BF0C84E11784B3B0900D0963 /* app.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = app.icns; sourceTree = "<group>"; };
BF0C86370093A080DD5974D8 /* convert_svg_to_png.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = convert_svg_to_png.sh; sourceTree = "<group>"; };
BF0C87B913292EE53EDE4220 /* menubar-1.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "menubar-1.svg"; sourceTree = "<group>"; };
BF0C884157B87BF0E17EF7F8 /* WindowControlView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowControlView.swift; sourceTree = "<group>"; };
BF0C889529FF19620EDAC295 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
BF0C88BF67CF4D71002A60EB /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
BF0C88D6043B83B535BEAAA2 /* no */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = no; path = Localizable.strings; sourceTree = "<group>"; };
Expand All @@ -140,6 +148,7 @@
BF0C8E54658B4DAEA0528200 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
BF0C8F0D1F5E9980C2E1A073 /* no */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = no; path = InfoPlist.strings; sourceTree = "<group>"; };
BF0C8F88F4326C82F16FD738 /* minimize.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = minimize.svg; sourceTree = "<group>"; };
BF0C8F9CE1699644A22EAF2C /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
C0712B3BEA2B3780398C0999 /* Pods_alt_tab_macos.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_alt_tab_macos.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D04BA015A45DE7AFDC9794FE /* Window.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Window.swift; sourceTree = "<group>"; };
D04BA03200F5A8FC0CD03607 /* CGWindowID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGWindowID.swift; sourceTree = "<group>"; };
Expand All @@ -162,7 +171,7 @@
D04BA123744B0C27E9F54B05 /* codesign_sparkle_embedded_apps.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = codesign_sparkle_embedded_apps.sh; sourceTree = "<group>"; };
D04BA18724DC58FA95DB33DB /* Podfile.lock */ = {isa = PBXFileReference; lastKnownFileType = file.lock; path = Podfile.lock; sourceTree = "<group>"; };
D04BA18B55AA6C9EE41985D0 /* Contributing.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Contributing.md; sourceTree = "<group>"; };
D04BA19E22F2B73DB785E5DB /* subset_fonticon.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = subset_fonticon.sh; sourceTree = "<group>"; };
D04BA19E22F2B73DB785E5DB /* subset_font.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = subset_font.sh; sourceTree = "<group>"; };
D04BA1B438BF3E65044D1138 /* ControlsTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlsTab.swift; sourceTree = "<group>"; };
D04BA1D80F4EEF2A91BAD29C /* release.config.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = release.config.js; sourceTree = "<group>"; };
D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThumbnailFontIconView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -297,7 +306,7 @@
D04BACE22DC907F03D193075 /* GeneralTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneralTab.swift; sourceTree = "<group>"; };
D04BACEE8D430B8CAAD8C4CD /* BoldLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoldLabel.swift; sourceTree = "<group>"; };
D04BAD1297730B191E96E7FE /* ThumbnailTitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThumbnailTitleView.swift; sourceTree = "<group>"; };
D04BAD19B495AC18AC782A39 /* fonticon_to_image.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = fonticon_to_image.sh; sourceTree = "<group>"; };
D04BAD19B495AC18AC782A39 /* convert_font_to_png.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = convert_font_to_png.sh; sourceTree = "<group>"; };
D04BAD215A8F61F2D9952181 /* Introduction.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Introduction.md; sourceTree = "<group>"; };
D04BAD241A6928F45355B315 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = Localizable.strings; sourceTree = "<group>"; };
D04BAD2A5EFA477F1BC436B4 /* import_certificate_into_new_keychain.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = import_certificate_into_new_keychain.sh; sourceTree = "<group>"; };
Expand Down Expand Up @@ -418,6 +427,9 @@
BF0C81C1B55A0519C3272B09 /* close.svg */,
BF0C8F88F4326C82F16FD738 /* minimize.svg */,
BF0C81B8A30416D774B5B60E /* fullscreen.svg */,
BF0C8F9CE1699644A22EAF2C /* [email protected] */,
BF0C817D9C335EE4A0536601 /* [email protected] */,
BF0C83BD867F6A874F9953C9 /* [email protected] */,
);
path = "window-controls";
sourceTree = "<group>";
Expand Down Expand Up @@ -699,6 +711,7 @@
D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */,
D04BA258B56193958D60978A /* ThumbnailView.swift */,
D04BAA998119CAA8B70A2B67 /* ThumbnailsView.swift */,
BF0C884157B87BF0E17EF7F8 /* WindowControlView.swift */,
);
path = "main-window";
sourceTree = "<group>";
Expand All @@ -723,16 +736,17 @@
D04BAD6700415D6F7C8B2BEE /* travis.sh */,
D04BA81B25C166EFB3223639 /* extract_l10n_strings.sh */,
D04BA4FB0047656BEA21F1BE /* codesign */,
D04BA19E22F2B73DB785E5DB /* subset_fonticon.sh */,
D04BA19E22F2B73DB785E5DB /* subset_font.sh */,
D04BA48E6F24E0948C4CB4F7 /* import_l10n_strings_from_poeditor.sh */,
D04BAA5ECAE8BB8F8656DEDF /* update_contributors.sh */,
D04BAD65AA870A49D2F89DBC /* ensure_generated_files_are_up_to_date.sh */,
D04BA4D5DF349429527824A2 /* determine_version.sh */,
D04BAAE6E6823304D66B74F8 /* update_website.sh */,
D04BA7A758026814667273DC /* convert_iconset_to_icns.sh */,
D04BA6ED38651224DB117A5A /* upload_symbols_to_appcenter.sh */,
D04BAD19B495AC18AC782A39 /* fonticon_to_image.sh */,
D04BAD19B495AC18AC782A39 /* convert_font_to_png.sh */,
D04BA59FD487D0DEBBA66A94 /* createicns */,
BF0C86370093A080DD5974D8 /* convert_svg_to_png.sh */,
);
path = scripts;
sourceTree = "<group>";
Expand Down Expand Up @@ -1120,6 +1134,9 @@
BF0C8C9CA44285E493918A74 /* [email protected] in Resources */,
BF0C829583ED47E458528F3A /* [email protected] in Resources */,
BF0C8406805BDEC5B69E8803 /* [email protected] in Resources */,
BF0C8477850829E15FD4DD43 /* [email protected] in Resources */,
BF0C8CB668FFABBCA23880B6 /* [email protected] in Resources */,
BF0C8F80281B50D57C95ECCF /* [email protected] in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1252,6 +1269,7 @@
D04BADA3F2DAB820D6FC6E75 /* AppCenterApplication.m in Sources */,
D04BAA16F21AC41A23DDA63D /* ControlsTab.swift in Sources */,
D04BADE4DDF7597749FB13BD /* PreferencesWindow.swift in Sources */,
BF0C89DF22C7B7D0C27DA2A4 /* WindowControlView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
27 changes: 27 additions & 0 deletions scripts/convert_svg_to_png.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash

set -exu

# needed because of macOS SIP (see https://stackoverflow.com/a/35570229)
export DYLD_LIBRARY_PATH="$MAGICK_HOME/lib"

currentDir="$(pwd)"
size=16

function convert() {
# magick convert \
# -background none \
# -density 144 \
# -resize 24x24 \
# "resources/icons/window-controls/$1.svg" \
# "resources/icons/window-controls/$1-magik.png"
/Applications/Inkscape.app/Contents/Resources/bin/inkscape \
-z \
-w "$((size * 2))" -h "$((size * 2))" \
"$currentDir/resources/icons/window-controls/$1.svg" \
-e "$currentDir/resources/icons/window-controls/$1@2x.png"
}

convert "close"
convert "fullscreen"
convert "minimize"
File renamed without changes.
13 changes: 13 additions & 0 deletions src/api-wrappers/HelperExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,17 @@ extension NSImage {
img.unlockFocus()
return img
}

func tinted(_ tint: NSColor) -> NSImage {
let dimmed = copy() as! NSImage
let scaling = Screen.withMouse()?.backingScaleFactor ?? 1
let scaledSize = NSSize(width: (size.width * scaling).rounded(), height: (size.height * scaling).rounded())
dimmed.size = scaledSize
dimmed.lockFocus()
tint.set()
let imageRect = NSRect(origin: .zero, size: scaledSize)
imageRect.fill(using: .sourceAtop)
dimmed.unlockFocus()
return dimmed
}
}
2 changes: 1 addition & 1 deletion src/logic/Screen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Screen {
}
}

private static func withMouse() -> NSScreen? {
static func withMouse() -> NSScreen? {
return NSScreen.screens.first { NSMouseInRect(NSEvent.mouseLocation, $0.frame, false) }
}

Expand Down
28 changes: 21 additions & 7 deletions src/ui/main-window/ThumbnailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class ThumbnailView: NSStackView {
var hiddenIcon = ThumbnailFontIconView(.circledSlashSign)
var spaceIcon = ThumbnailFontIconView(.circledNumber0)
var dockLabelIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledNumber0, (Preferences.fontIconSize * 0.7).rounded(), NSColor(srgbRed: 1, green: 0.30, blue: 0.25, alpha: 1), nil), NSColor.white, true)
var closeIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledMultiplySign, Preferences.fontIconSize, NSColor(srgbRed: 1, green: 0.35, blue: 0.32, alpha: 1), nil), NSColor(srgbRed: 0.64, green: 0.03, blue: 0.02, alpha: 1))
var minimizeIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledMinusSign, Preferences.fontIconSize, NSColor(srgbRed: 0.91, green: 0.75, blue: 0.16, alpha: 1), nil), NSColor(srgbRed: 0.71, green: 0.55, blue: 0.09, alpha: 1))
var maximizeIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledPlusSign, Preferences.fontIconSize, NSColor(srgbRed: 0.32, green: 0.76, blue: 0.17, alpha: 1), nil), NSColor(srgbRed: 0.04, green: 0.39, blue: 0.02, alpha: 1))
var closeIcon = WindowControlView("close", 16)
var minimizeIcon = WindowControlView("minimize", 16)
var maximizeIcon = WindowControlView("fullscreen", 16)
var hStackView: NSStackView!
var mouseUpCallback: (() -> Void)!
var mouseMovedCallback: (() -> Void)!
Expand Down Expand Up @@ -54,11 +54,11 @@ class ThumbnailView: NSStackView {
thumbnail.addSubview(closeIcon, positioned: .above, relativeTo: nil)
thumbnail.addSubview(minimizeIcon, positioned: .above, relativeTo: nil)
thumbnail.addSubview(maximizeIcon, positioned: .above, relativeTo: nil)
let windowsControlSpacing = CGFloat(3)
[closeIcon, minimizeIcon, maximizeIcon].forEach {
$0.topAnchor.constraint(equalTo: thumbnail.topAnchor, constant: 1).isActive = true
$0.topAnchor.constraint(equalTo: thumbnail.topAnchor, constant: 2).isActive = true
}
closeIcon.leftAnchor.constraint(equalTo: thumbnail.leftAnchor).isActive = true
closeIcon.leftAnchor.constraint(equalTo: thumbnail.leftAnchor, constant: 3).isActive = true
let windowsControlSpacing = CGFloat(6)
minimizeIcon.leftAnchor.constraint(equalTo: closeIcon.rightAnchor, constant: windowsControlSpacing).isActive = true
maximizeIcon.leftAnchor.constraint(equalTo: minimizeIcon.rightAnchor, constant: windowsControlSpacing).isActive = true
[closeIcon, minimizeIcon, maximizeIcon].forEach { $0.isHidden = true }
Expand Down Expand Up @@ -192,11 +192,25 @@ class ThumbnailView: NSStackView {
if !isHighlighted {
mouseMovedCallback()
}
hoverWindowControls()
}

func hoverWindowControls() {
let controls = [closeIcon, minimizeIcon, maximizeIcon]
if let target = thumbnail.hitTest(convert(window!.convertPoint(fromScreen: NSEvent.mouseLocation), from: nil)),
target is NSImageView {
if let control = (controls.first { $0 == target }) {
control.hovered(true)
controls.filter { $0 != control }.forEach { $0.hovered(false) }
} else {
controls.forEach { $0.hovered(false) }
}
}
}

override func mouseUp(with event: NSEvent) {
if event.clickCount >= 1 {
let target = thumbnail.hitTest(convert(event.locationInWindow, from: nil))?.superview
let target = thumbnail.hitTest(convert(event.locationInWindow, from: nil))
if target == closeIcon {
window_!.close()
} else if target == minimizeIcon {
Expand Down
24 changes: 24 additions & 0 deletions src/ui/main-window/WindowControlView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Cocoa

class WindowControlView: NSImageView {
var originalImage: NSImage!
var hoveredImage: NSImage!
var size: NSSize!

convenience init(_ imageName: String, _ size_: Int) {
self.init()
translatesAutoresizingMaskIntoConstraints = false
size = NSSize(width: size_, height: size_)
let image = NSImage.initCopy(imageName)
image.size = size
originalImage = image
hoveredImage = image.tinted(.init(white: 0, alpha: 0.25))
hovered(false)
}

func hovered(_ isHovered: Bool) {
image = isHovered ? hoveredImage : originalImage
image!.size = size
frame.size = size
}
}

0 comments on commit 208ee4f

Please sign in to comment.