From 6974de02ac293df6d19a9911f7129bcf9bb93ca5 Mon Sep 17 00:00:00 2001 From: Louis Pontoise Date: Sat, 7 May 2022 02:28:16 +0900 Subject: [PATCH] feat: improve traffic-light icons (closes #1542) --- alt-tab-macos.xcodeproj/project.pbxproj | 34 +--- resources/icons/window-controls/close.svg | 14 -- resources/icons/window-controls/close@2x.png | Bin 1030 -> 0 bytes .../icons/window-controls/fullscreen.svg | 11 - .../icons/window-controls/fullscreen@2x.png | Bin 960 -> 0 bytes resources/icons/window-controls/minimize.svg | 11 - .../icons/window-controls/minimize@2x.png | Bin 848 -> 0 bytes .../TrafficLightButton.swift | 188 ++++++++++++++++++ src/ui/main-window/ThumbnailView.swift | 53 ++--- src/ui/main-window/WindowControlView.swift | 26 --- 10 files changed, 208 insertions(+), 129 deletions(-) delete mode 100644 resources/icons/window-controls/close.svg delete mode 100644 resources/icons/window-controls/close@2x.png delete mode 100755 resources/icons/window-controls/fullscreen.svg delete mode 100644 resources/icons/window-controls/fullscreen@2x.png delete mode 100755 resources/icons/window-controls/minimize.svg delete mode 100644 resources/icons/window-controls/minimize@2x.png create mode 100644 src/ui/generic-components/TrafficLightButton.swift delete mode 100644 src/ui/main-window/WindowControlView.swift diff --git a/alt-tab-macos.xcodeproj/project.pbxproj b/alt-tab-macos.xcodeproj/project.pbxproj index 09b99241..58ee5d38 100644 --- a/alt-tab-macos.xcodeproj/project.pbxproj +++ b/alt-tab-macos.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ BF0C83AB0186CC48FADF66A7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C847B2D68EACFAC1B06D1 /* Localizable.strings */; }; BF0C83E902F75A97E8FD374A /* menubar-2@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8D3333653ACAEF730DD8 /* menubar-2@2x.png */; }; BF0C8406805BDEC5B69E8803 /* screen-recording@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8E25373671B528AD448D /* screen-recording@2x.png */; }; - BF0C8477850829E15FD4DD43 /* close@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8F9CE1699644A22EAF2C /* close@2x.png */; }; BF0C84D7DC2AC65BB1C111EB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8349BA94516E8760BAFA /* Localizable.strings */; }; BF0C852D28E458CDD6FA3E44 /* app.icns in Resources */ = {isa = PBXBuildFile; fileRef = BF0C84E11784B3B0900D0963 /* app.icns */; }; BF0C853B271C4407E87FA183 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8096A88BC18C4902C037 /* InfoPlist.strings */; }; @@ -39,7 +38,6 @@ BF0C894199BB262BDB2D8D37 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8221101CD179DB1121D5 /* InfoPlist.strings */; }; BF0C894325A54CF0B6B53464 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8B8B31D2F421AC258351 /* Localizable.strings */; }; BF0C89C49CFBAAB4646BB8CB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C82A8848224E76B880A83 /* InfoPlist.strings */; }; - BF0C89DF22C7B7D0C27DA2A4 /* WindowControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C884157B87BF0E17EF7F8 /* WindowControlView.swift */; }; BF0C8A739A74695E60F16369 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8062E78677398A4A217B /* InfoPlist.strings */; }; BF0C8A95AAD9DADC95887A2D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C895A9AF79A869EE6B108 /* Localizable.strings */; }; BF0C8AC57CE5E9BBEEE2442A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C885D34CDCE2AFC5A94F7 /* InfoPlist.strings */; }; @@ -47,16 +45,15 @@ BF0C8B2E933E4A0A91D7AF64 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8195F23B30B8F4DD38D1 /* Localizable.strings */; }; BF0C8C1FDE88F7A0429BF466 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8D6F749064299AC47E2F /* InfoPlist.strings */; }; BF0C8C4381FB16A4DFBBB219 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8357200430B9683ECD6F /* InfoPlist.strings */; }; + BF0C8C7E96DB48120462DA00 /* TrafficLightButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8DF400A1AF64EB0CD0B3 /* TrafficLightButton.swift */; }; BF0C8C8E35FF49CAA4BF5FC4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8A970BD1CAD555F31EDA /* Localizable.strings */; }; BF0C8C9CA44285E493918A74 /* menubar-3@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8E54658B4DAEA0528200 /* menubar-3@2x.png */; }; - BF0C8CB668FFABBCA23880B6 /* minimize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C817D9C335EE4A0536601 /* minimize@2x.png */; }; BF0C8CC5057406014FD612CC /* ATShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0C8BA452332236D972C60E /* ATShortcut.swift */; }; BF0C8D1C57D74106018D073C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C87F5D4AD51D6950C98B0 /* InfoPlist.strings */; }; BF0C8D610C93D48F572937F8 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C8FBA6B0F4DEB510C71CB /* Localizable.strings */; }; BF0C8DD7EBC3BA1E86BF4BDB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C841E403C1C6E8C65727E /* InfoPlist.strings */; }; BF0C8EA4654F8059F0AED40E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C82992C31AA542EF9E638 /* InfoPlist.strings */; }; BF0C8F3526BC393290D5BE59 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF0C81EC1C5F3052A75C7D7B /* InfoPlist.strings */; }; - BF0C8F80281B50D57C95ECCF /* fullscreen@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BF0C83BD867F6A874F9953C9 /* fullscreen@2x.png */; }; 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 */; }; @@ -169,14 +166,10 @@ BF0C8118F91A00A04AD4DE26 /* bg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = bg; path = InfoPlist.strings; sourceTree = ""; }; BF0C816D6B12CC13F741E61F /* hi */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = hi; path = Localizable.strings; sourceTree = ""; }; BF0C816F38751995E4F49BB0 /* he */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = he; path = InfoPlist.strings; sourceTree = ""; }; - BF0C817D9C335EE4A0536601 /* minimize@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "minimize@2x.png"; sourceTree = ""; }; BF0C817E063D1405392D6C5B /* he */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = he; path = Localizable.strings; sourceTree = ""; }; - BF0C81B8A30416D774B5B60E /* fullscreen.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = fullscreen.svg; sourceTree = ""; }; - BF0C81C1B55A0519C3272B09 /* close.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = close.svg; sourceTree = ""; }; BF0C828AF7BCC4F47E70B28F /* menubar-2.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "menubar-2.svg"; sourceTree = ""; }; BF0C82C381FCBCF8109735AC /* pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pl; path = InfoPlist.strings; sourceTree = ""; }; BF0C833D471343CEA3DEFE56 /* icon_512x512@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_512x512@2x.png"; sourceTree = ""; }; - BF0C83BD867F6A874F9953C9 /* fullscreen@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "fullscreen@2x.png"; sourceTree = ""; }; BF0C83FC3C53FFB41A3832FD /* fa */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fa; path = InfoPlist.strings; sourceTree = ""; }; BF0C843C2EDF4EF3A7A2C64A /* app.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = app.svg; sourceTree = ""; }; BF0C8465A0A9EA2814A22C35 /* SF-Pro-Text-Regular-Full.otf */ = {isa = PBXFileReference; lastKnownFileType = file.otf; path = "SF-Pro-Text-Regular-Full.otf"; sourceTree = ""; }; @@ -191,7 +184,6 @@ BF0C86E06A44AC151FEA4903 /* sv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sv; path = InfoPlist.strings; sourceTree = ""; }; BF0C87B913292EE53EDE4220 /* menubar-1.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "menubar-1.svg"; sourceTree = ""; }; BF0C87C0514B13DACB6E702B /* fa */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fa; path = Localizable.strings; sourceTree = ""; }; - BF0C884157B87BF0E17EF7F8 /* WindowControlView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowControlView.swift; sourceTree = ""; }; BF0C888D912E73D88919899A /* uk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = uk; path = Localizable.strings; sourceTree = ""; }; BF0C889529FF19620EDAC295 /* accessibility@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "accessibility@2x.png"; sourceTree = ""; }; BF0C8898ADB2A1B49312E87B /* cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = cs; path = InfoPlist.strings; sourceTree = ""; }; @@ -213,6 +205,7 @@ BF0C8D3333653ACAEF730DD8 /* menubar-2@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menubar-2@2x.png"; sourceTree = ""; }; BF0C8D87C20B7308B16498B6 /* et */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = et; path = InfoPlist.strings; sourceTree = ""; }; BF0C8D9E024876AD9A92BE8D /* sr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sr; path = Localizable.strings; sourceTree = ""; }; + BF0C8DF400A1AF64EB0CD0B3 /* TrafficLightButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrafficLightButton.swift; sourceTree = ""; }; BF0C8E25373671B528AD448D /* screen-recording@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "screen-recording@2x.png"; sourceTree = ""; }; BF0C8E54658B4DAEA0528200 /* menubar-3@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menubar-3@2x.png"; sourceTree = ""; }; BF0C8E5D2BD5F7F93DF77DF5 /* sk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = sk; path = InfoPlist.strings; sourceTree = ""; }; @@ -220,8 +213,6 @@ BF0C8EC400A560FDF99F8C35 /* el */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = el; path = Localizable.strings; sourceTree = ""; }; BF0C8EE17F3ABD7A6D44BFFE /* pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pl; path = Localizable.strings; sourceTree = ""; }; BF0C8F0D1F5E9980C2E1A073 /* no */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = no; path = InfoPlist.strings; sourceTree = ""; }; - BF0C8F88F4326C82F16FD738 /* minimize.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = minimize.svg; sourceTree = ""; }; - BF0C8F9CE1699644A22EAF2C /* close@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "close@2x.png"; sourceTree = ""; }; 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 = ""; }; D04BA03200F5A8FC0CD03607 /* CGWindowID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGWindowID.swift; sourceTree = ""; }; @@ -565,19 +556,6 @@ path = app.iconset; sourceTree = ""; }; - BF0C8957AB44FB1E745D6BA5 /* window-controls */ = { - isa = PBXGroup; - children = ( - BF0C81C1B55A0519C3272B09 /* close.svg */, - BF0C8F88F4326C82F16FD738 /* minimize.svg */, - BF0C81B8A30416D774B5B60E /* fullscreen.svg */, - BF0C8F9CE1699644A22EAF2C /* close@2x.png */, - BF0C817D9C335EE4A0536601 /* minimize@2x.png */, - BF0C83BD867F6A874F9953C9 /* fullscreen@2x.png */, - ); - path = "window-controls"; - sourceTree = ""; - }; BF0C8A181CD8C6FD282D6AB5 /* ca.lproj */ = { isa = PBXGroup; children = ( @@ -804,6 +782,7 @@ D04BAA41B9A74189B065D856 /* text */, D04BAE333F7170E87C5AC0EF /* CustomRecorderControl.swift */, D04BA8AC77465E1B2BC947CF /* StackView.swift */, + BF0C8DF400A1AF64EB0CD0B3 /* TrafficLightButton.swift */, ); path = "generic-components"; sourceTree = ""; @@ -938,7 +917,6 @@ D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */, D04BA258B56193958D60978A /* ThumbnailView.swift */, D04BAA998119CAA8B70A2B67 /* ThumbnailsView.swift */, - BF0C884157B87BF0E17EF7F8 /* WindowControlView.swift */, ); path = "main-window"; sourceTree = ""; @@ -994,7 +972,6 @@ BF0C86C288D4FD8F92D3C7DB /* app */, BF0C80536B40523C5DB23BE2 /* menubar */, BF0C8060939B50725E1C3392 /* permission-window */, - BF0C8957AB44FB1E745D6BA5 /* window-controls */, ); path = icons; sourceTree = ""; @@ -1396,9 +1373,6 @@ BF0C8C9CA44285E493918A74 /* menubar-3@2x.png in Resources */, BF0C829583ED47E458528F3A /* accessibility@2x.png in Resources */, BF0C8406805BDEC5B69E8803 /* screen-recording@2x.png in Resources */, - BF0C8477850829E15FD4DD43 /* close@2x.png in Resources */, - BF0C8CB668FFABBCA23880B6 /* minimize@2x.png in Resources */, - BF0C8F80281B50D57C95ECCF /* fullscreen@2x.png in Resources */, BF0C853B271C4407E87FA183 /* InfoPlist.strings in Resources */, BF0C8658CC748011E57691B7 /* Localizable.strings in Resources */, BF0C88D7E209C788558BD943 /* InfoPlist.strings in Resources */, @@ -1585,9 +1559,9 @@ D04BADA3F2DAB820D6FC6E75 /* AppCenterApplication.m in Sources */, D04BAA16F21AC41A23DDA63D /* ControlsTab.swift in Sources */, D04BADE4DDF7597749FB13BD /* PreferencesWindow.swift in Sources */, - BF0C89DF22C7B7D0C27DA2A4 /* WindowControlView.swift in Sources */, BF0C855CF8BA047E180425F9 /* KeyRepeatTimer.swift in Sources */, BF0C8CC5057406014FD612CC /* ATShortcut.swift in Sources */, + BF0C8C7E96DB48120462DA00 /* TrafficLightButton.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/resources/icons/window-controls/close.svg b/resources/icons/window-controls/close.svg deleted file mode 100644 index 4a75c3c8..00000000 --- a/resources/icons/window-controls/close.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - close - - - - - - - - - - - \ No newline at end of file diff --git a/resources/icons/window-controls/close@2x.png b/resources/icons/window-controls/close@2x.png deleted file mode 100644 index e18e9e9289319161d8c105693dfbee20906198b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1030 zcmV+h1o``kP)XZ_#J-ylyD^4oVd=}KSbz;G@Sp3CwwbqX0mT&7L`u-is|2C9EdEv}i zQJZ&N_DL!O8{srU#Fta!_Em%5Jd*y{Ju+ zp3jbtAQgZ9m_K1_;RgB~Iciny`7O7kxDb?JyrfO)N)EwT4_tA;ey!>OX`s5LocDj# zPugR2_lcG-ePv)W$R!co$O~I-MZd&@E!WOT1aJyJ2n5C}^0Mlb_PNLLCpOz`orvev zi5rtM?mYIWb>uj;?;;~@-?yZgf&k*p9}NNbV!XN!J&5o{4xq~#7K%|joAa-JjoFR| zenfaBcQHL|5H2sAz#O;weTeWw?sfx;@p%YXiCYbS^dbVJF4CKC?ui_jn+&23-WC6K zK(5CVkaI58ga-k*q~3&p>A27RkY{-3a$)wEf|!F7cv8U0pfA0WyE#WX{D|N?2VHQ3 zKqbP-_#p3bPRLkwYH8Ft8CnSfQuqZ<#t*q45sUJ12w3w+K-*iuK*Gb#Z&L?%AAih7 zQiMOP-N1sHMQrV6Mr{xS@3;l$JH8k{ek&MAd}hE)(J3$!bND`=n+P%jI3>(>mvjw=jN9jZ z4R|=%C?>capZBmsT&Y|$Pw^bN5wjiRRd|Sh0cADvyf%F$ssI2007*qoM6N<$f_X>$ A{Qv*} diff --git a/resources/icons/window-controls/fullscreen.svg b/resources/icons/window-controls/fullscreen.svg deleted file mode 100755 index 0016e8c9..00000000 --- a/resources/icons/window-controls/fullscreen.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - fullscreen - - - - - - - - \ No newline at end of file diff --git a/resources/icons/window-controls/fullscreen@2x.png b/resources/icons/window-controls/fullscreen@2x.png deleted file mode 100644 index 2187bde46f4becea10c7693b65d7f05411ca2183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 960 zcmV;x13&zUP)hj-0ajm?x!|6Al(i#ni#I|vq2@9SM}=GOdyGBjx&dy~?O3 z8k2OkBBUJUeov6EYyRb&f5J~;p3!i|NT#awuBQ*{RX424sB3Op2QUE}c3T0O^7F(e ziS_JH!JMN;hHj4pV$*%wLi+((;3;)0gIx6T_aJ)AxxsNH5NmE-8~VJ}?q^|%L9kwd z=+Z>6@h(u~T%4$i3}VeK;Q$hYWdJ~#5a$_n<=a@VVF%C9irxCaUIU04z5BVNSpxug z?nz9m9zrU2h%nFQ3CkWQc}@n9Tj$IQd|*_N{#*h&Nk z!4r@&tjtRh-Vf02c5@!m{u|l4pJglP39wf(@EI5r)-{+6Ml-Erng9@6-r_q(oOK|OcxUj9dJ<%U0Ok8Pnnj8%VYegI=yEI>f6n6;a5&H?k&-XteGd`hN~OO& i0`??!yT4wuklz8Yc7Xcc2YPP+0000 - - minimize - - - - - - - - \ No newline at end of file diff --git a/resources/icons/window-controls/minimize@2x.png b/resources/icons/window-controls/minimize@2x.png deleted file mode 100644 index c628cd3e28c085cd9f937bfad53d8654a37f4560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 848 zcmV-W1F!svP) zjcrSgcPug-lU^{w7-@_opGiUde4nwwHhYZuxu<<~q04^n@72*UrNtLdW~ku9q@qrd ziajS)`~^~R=SW4LmMY?eRDlOc@o#`gc6RaiBLnJHm^gG-w>o^GwIB{WC|#no>r$zk zB_s8!WQR!kTdpIajv;5Ox#I7NME%zP07rOMs*D@Bc=?dd&LUI3%#57-YIUw#CUW1t zUc=yd&>@ca8ZK5jBwv;)V883cYx`igmL-z^+|#{1|1c!aTrC zNZ<_$P7c1Suua;B_39BhfKsCjSW=S(d-5{sl(!B5!H3;u+#no-!ea|`fAW={>ix!+ z>gAedTJU9CYmS-^ZCELJHMgYHcn{8$1Sb$aYUX#AIRIHs0nzzuDMq7 z?S6kTS^In(IKG+tx`3F#d0wzaQK!17&?B9+AnshZLe~#N2`oA;pkyLWc;AFLbJ&4p z0-XpY<0Uz?0``Dyke`5t!<*Er-Z>C=&UGL?$mrcvKtMvnK}LDy0Q3fL;Hx6rARuuR zr+aW1C10kjBUuhFC`N*#PI<8bv*y2`LA_!>Cta#K@|d&a*527qgGE7uOtQ_Mhf#{u zYgML(7;=s%&O(k*ZKzj>6OB^=@~r!Wo~9_xAf4HXC&&c;s449(`PcQGtBJB0eh8g_ zKVoH8BpbLN;EaMigVR1&l-JM`P_KM}uV_xlC@2|-i4ry(mJH?`#K0}L;VNU#whj0X z0uuKO3 (NSGradient, NSColor, NSColor) { + if NSColor.currentControlTint == .graphiteControlTint { + return ( + NSGradient(starting: NSColor(red: 0.57, green: 0.57, blue: 0.60, alpha: 1), + ending: NSColor(red: 0.56, green: 0.55, blue: 0.57, alpha: 1))!, + type == .zoomButton ? + NSColor(red: 0.16, green: 0.16, blue: 0.17, alpha: 1) + : type == .miniaturizeButton ? + NSColor(red: 0.35, green: 0.35, blue: 0.37, alpha: 1) + : + NSColor(red: 0.19, green: 0.18, blue: 0.20, alpha: 1), + NSColor(red: 0.51, green: 0.51, blue: 0.53, alpha: 1) + ) + } + if type == .zoomButton { + return ( + NSGradient(starting: NSColor(red: 0.153, green: 0.788, blue: 0.247, alpha: 1), + ending: NSColor(red: 0.153, green: 0.816, blue: 0.255, alpha: 1))!, + NSColor(red: 0.004, green: 0.392, blue: 0, alpha: 1), + NSColor(red: 0.180, green: 0.690, blue: 0.235, alpha: 1) + ) + } + if type == .miniaturizeButton { + return ( + NSGradient(starting: NSColor(red: 1, green: 0.741, blue: 0.180, alpha: 1), + ending: NSColor(red: 1, green: 0.773, blue: 0.184, alpha: 1))!, + NSColor(red: 0.600, green: 0.345, blue: 0.004, alpha: 1), + NSColor(red: 0.875, green: 0.616, blue: 0.094, alpha: 1) + ) + } + return ( + NSGradient(starting: NSColor(red: 1, green: 0.373, blue: 0.337, alpha: 1), + ending: NSColor(red: 1, green: 0.388, blue: 0.357, alpha: 1))!, + NSColor(red: 0.302, green: 0, blue: 0, alpha: 1), + NSColor(red: 0.886, green: 0.243, blue: 0.216, alpha: 1) + ) + } + + private func drawDimming(_ disk: NSBezierPath) { + if (isHighlighted) { + NSColor(calibratedRed: 0, green: 0, blue: 0, alpha: 0.5).setFill() + disk.fill() + } else if (isMouseOver) { + NSColor(calibratedRed: 0, green: 0, blue: 0, alpha: 0.25).setFill() + disk.fill() + } + } + + private func drawDisk(_ backgroundGradient: NSGradient, _ strokeColor: NSColor) -> NSBezierPath { + var disk = NSBezierPath() + disk.appendOval(in: NSMakeRect(bounds.origin.x + 0.5, bounds.origin.y + 0.5, bounds.width - 1, bounds.height - 1)) + backgroundGradient.draw(in: disk, relativeCenterPosition: NSMakePoint(0, 0)) + strokeColor.setStroke() + disk.lineWidth = 0.5 + disk.stroke() + return disk + } + + private func drawSymbol(_ lineColor: NSColor) { + if (type == NSWindow.ButtonType.zoomButton) { + var symbol = NSBezierPath() + symbol.move(to: NSMakePoint(bounds.width * 0.25, bounds.height * 0.75)) + symbol.line(to: NSMakePoint(bounds.width * 0.25, bounds.height * 1 / 3)) + symbol.line(to: NSMakePoint(bounds.width * 2 / 3, bounds.height * 0.75)) + symbol.close() + lineColor.setFill() + symbol.fill() + symbol.move(to: NSMakePoint(bounds.width * 0.75, bounds.height * 0.25)) + symbol.line(to: NSMakePoint(bounds.width * 0.75, bounds.height * 2 / 3)) + symbol.line(to: NSMakePoint(bounds.width * 1 / 3, bounds.height * 0.25)) + symbol.close() + lineColor.setFill() + symbol.fill() + // maximize cross + // NSGraphicsContext.current?.shouldAntialias = false + // var symbol = NSBezierPath() + // symbol.move(to: NSMakePoint(bounds.width / 2, bounds.height * 0.20)) + // symbol.line(to: NSMakePoint(bounds.width / 2, bounds.height * 0.80)) + // symbol.move(to: NSMakePoint(bounds.width * 0.80, bounds.height / 2)) + // symbol.line(to: NSMakePoint(bounds.width * 0.20, bounds.height / 2)) + // symbol.lineWidth = 0.75 + } else if (type == NSWindow.ButtonType.miniaturizeButton) { + NSGraphicsContext.current?.shouldAntialias = false + var symbol = NSBezierPath() + symbol.move(to: NSMakePoint(bounds.width * 0.80, bounds.height / 2)) + symbol.line(to: NSMakePoint(bounds.width * 0.20, bounds.height / 2)) + symbol.lineWidth = 0.75 + lineColor.setStroke() + symbol.stroke() + } else if (type == NSWindow.ButtonType.closeButton) { + var symbol = NSBezierPath() + symbol.move(to: NSMakePoint(bounds.width * 0.30, bounds.height * 0.30)) + symbol.line(to: NSMakePoint(bounds.width * 0.70, bounds.height * 0.70)) + symbol.move(to: NSMakePoint(bounds.width * 0.70, bounds.height * 0.30)) + symbol.line(to: NSMakePoint(bounds.width * 0.30, bounds.height * 0.70)) + symbol.lineWidth = 1 + lineColor.setStroke() + symbol.stroke() + } + } +} + + + +// experiment: use actual buttons from OS through standardWindowButton +// issues: +// * zoom button has a popover that can't be removed +// * overall they look/act depending on the parent window +// e.g. need to set `window.collectionBehavior = .fullScreenPrimary` to get fullscreen button + +//class TrafficLightButton: NSView { +// convenience init(_ nameTest: NSWindow.ButtonType) { +// self.init(frame: .zero) +// let button = NSWindow.standardWindowButton(nameTest, for: [.miniaturizable, .closable, .nonactivatingPanel])! +// button.action = nil +// addSubview(button) +// fit(button.frame.size.width, button.frame.size.height) +// } +// +// /// force the hovered state as if the mouse was on the traffic lights area +// /// see https://stackoverflow.com/a/30417372/2249756 +// @objc func _mouseInGroup(_: Any) -> Bool { +// return true +// } +// +// override func updateTrackingAreas() { +// addTrackingArea(NSTrackingArea(rect: .zero, options: [.mouseEnteredAndExited, .activeAlways, .inVisibleRect], owner: self, userInfo: nil)) +// } +// +// override func mouseEntered(with event: NSEvent) { +// } +// +// override func mouseExited(with event: NSEvent) { +// } +//} diff --git a/src/ui/main-window/ThumbnailView.swift b/src/ui/main-window/ThumbnailView.swift index 1cf39092..3d9823b1 100644 --- a/src/ui/main-window/ThumbnailView.swift +++ b/src/ui/main-window/ThumbnailView.swift @@ -1,6 +1,8 @@ import Cocoa class ThumbnailView: NSStackView { + static let windowsControlSize = CGFloat(16) + static let windowsControlSpacing = CGFloat(8) var window_: Window? var thumbnail = NSImageView() var appIcon = NSImageView() @@ -10,9 +12,9 @@ class ThumbnailView: NSStackView { var hiddenIcon = ThumbnailFontIconView(.circledSlashSign) var spaceIcon = ThumbnailFontIconView(.circledNumber0) var dockLabelIcon = ThumbnailFilledFontIconView(ThumbnailFontIconView(.filledCircledNumber0, 14, NSColor(srgbRed: 1, green: 0.30, blue: 0.25, alpha: 1), nil), NSColor.white) - var closeIcon = WindowControlView("close", 16) - var minimizeIcon = WindowControlView("minimize", 16) - var maximizeIcon = WindowControlView("fullscreen", 16) + var closeIcon = TrafficLightButton(.closeButton, windowsControlSize) + var minimizeIcon = TrafficLightButton(.miniaturizeButton, windowsControlSize) + var maximizeIcon = TrafficLightButton(.zoomButton, windowsControlSize) var hStackView: NSStackView! var mouseUpCallback: (() -> Void)! var mouseMovedCallback: (() -> Void)! @@ -61,13 +63,6 @@ class ThumbnailView: NSStackView { thumbnail.addSubview(closeIcon, positioned: .above, relativeTo: nil) thumbnail.addSubview(minimizeIcon, positioned: .above, relativeTo: nil) thumbnail.addSubview(maximizeIcon, positioned: .above, relativeTo: nil) - [closeIcon, minimizeIcon, maximizeIcon].forEach { - $0.topAnchor.constraint(equalTo: thumbnail.topAnchor, constant: 2).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 } } @@ -80,6 +75,14 @@ class ThumbnailView: NSStackView { isShowingWindowControls = shouldShow [closeIcon, minimizeIcon, maximizeIcon].forEach { $0.isHidden = !shouldShow } } + if isShowingWindowControls { + [closeIcon, minimizeIcon, maximizeIcon].enumerated().forEach { (i, icon: TrafficLightButton) in + icon.setFrameOrigin(.init( + x: 3 + (ThumbnailView.windowsControlSpacing + ThumbnailView.windowsControlSize) * CGFloat(i), + y: thumbnail.frame.height - ThumbnailView.windowsControlSize - 2)) + icon.window_ = window_ + } + } } func highlight(_ highlight: Bool) { @@ -171,7 +174,6 @@ class ThumbnailView: NSStackView { self.mouseUpCallback = { () -> Void in App.app.focusSelectedWindow(element) } self.mouseMovedCallback = { () -> Void in Windows.updateFocusedWindowIndex(index) } showOrHideWindowControls(false) - [closeIcon, minimizeIcon, maximizeIcon].forEach { $0.hovered(false) } // force a display to avoid flickering; see https://github.com/lwouis/alt-tab-macos/issues/197 // quirk: display() should be called last as it resets thumbnail.frame.size somehow if labelChanged { @@ -198,8 +200,8 @@ class ThumbnailView: NSStackView { func getAccessibilityHelp(_ appName: String?, _ dockLabel: Int?) -> String { [appName, dockLabel.map { getAccessibilityTextForBadge($0) }] - .compactMap { $0 } - .joined(separator: " - ") + .compactMap { $0 } + .joined(separator: " - ") } func getAccessibilityTextForBadge(_ dockLabel: Int) -> String { @@ -245,34 +247,11 @@ class ThumbnailView: NSStackView { if Preferences.mouseHoverEnabled && !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)) - if target == closeIcon { - window_!.close() - } else if target == minimizeIcon { - window_!.minDemin() - } else if target == maximizeIcon { - window_!.toggleFullscreen() - } else { - mouseUpCallback() - } + mouseUpCallback() } } diff --git a/src/ui/main-window/WindowControlView.swift b/src/ui/main-window/WindowControlView.swift deleted file mode 100644 index 5f3af100..00000000 --- a/src/ui/main-window/WindowControlView.swift +++ /dev/null @@ -1,26 +0,0 @@ -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) - setAccessibilityLabel(imageName) - setAccessibilityRole(.button) - } - - func hovered(_ isHovered: Bool) { - image = isHovered ? hoveredImage : originalImage - image!.size = size - frame.size = size - } -}