mirror of
https://github.com/zen-browser/desktop.git
synced 2026-02-05 19:37:22 +00:00
Merge pull request #8266 from zen-browser/haptic-feedback
This commit is contained in:
@@ -19,6 +19,9 @@ pref('zen.view.show-newtab-button-top', true);
|
||||
|
||||
pref('zen.mediacontrols.enabled', true);
|
||||
|
||||
// Exposure:
|
||||
pref('zen.haptic-feedback.enabled', true);
|
||||
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
pref('zen.rice.api.url', 'https://share.zen-browser.app', locked);
|
||||
pref('zen.injections.match-urls', 'https://zen-browser.app/*,https://share.zen-browser.app/*', locked);
|
||||
|
||||
@@ -11,3 +11,8 @@
|
||||
value: 1
|
||||
mirror: always
|
||||
#endif
|
||||
|
||||
- name: zen.haptic-feedback.enabled
|
||||
type: bool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
@@ -62,5 +62,9 @@ panel[type='arrow'] {
|
||||
--panel-border-color: transparent;
|
||||
/* This should be kept in sync with GetMenuMaskImage() */
|
||||
--panel-border-radius: 6px;
|
||||
|
||||
&::part(content) {
|
||||
background-color: light-dark(rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0.2)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,6 +942,9 @@
|
||||
}
|
||||
|
||||
removeTabContainersDragoverClass() {
|
||||
if (this._dragIndicator) {
|
||||
Services.zen.playHapticFeedback();
|
||||
}
|
||||
this.dragIndicator.remove();
|
||||
this._dragIndicator = null;
|
||||
ZenWorkspaces.activeWorkspaceIndicator?.removeAttribute('open');
|
||||
@@ -1043,16 +1046,19 @@
|
||||
|
||||
// Calculate middle to decide 'before' or 'after'
|
||||
const rect = targetTab.getBoundingClientRect();
|
||||
|
||||
let shouldPlayHapticFeedback = false;
|
||||
if (isVertical) {
|
||||
const separation = 8;
|
||||
const middleY = targetTab.screenY + rect.height / 2;
|
||||
const indicator = this.dragIndicator;
|
||||
let top = 0;
|
||||
if (event.screenY > middleY) {
|
||||
top = rect.top + rect.height + 'px';
|
||||
top = Math.round(rect.top + rect.height) + 'px';
|
||||
} else {
|
||||
top = rect.top + 'px';
|
||||
top = Math.round(rect.top) + 'px';
|
||||
}
|
||||
if (indicator.style.top !== top) {
|
||||
shouldPlayHapticFeedback = true;
|
||||
}
|
||||
indicator.setAttribute('orientation', 'horizontal');
|
||||
indicator.style.setProperty('--indicator-left', rect.left + separation / 2 + 'px');
|
||||
@@ -1065,9 +1071,12 @@
|
||||
const indicator = this.dragIndicator;
|
||||
let left = 0;
|
||||
if (event.screenX > middleX) {
|
||||
left = rect.left + rect.width + 1 + 'px';
|
||||
left = Math.round(rect.left + rect.width + 1) + 'px';
|
||||
} else {
|
||||
left = rect.left - 2 + 'px';
|
||||
left = Math.round(rect.left - 2) + 'px';
|
||||
}
|
||||
if (indicator.style.left !== left) {
|
||||
shouldPlayHapticFeedback = true;
|
||||
}
|
||||
indicator.setAttribute('orientation', 'vertical');
|
||||
indicator.style.setProperty('--indicator-top', rect.top + separation / 2 + 'px');
|
||||
@@ -1075,6 +1084,9 @@
|
||||
indicator.style.left = left;
|
||||
indicator.style.removeProperty('top');
|
||||
}
|
||||
if (shouldPlayHapticFeedback) {
|
||||
Services.zen.playHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
async onTabLabelChanged(tab) {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsISharePicker.h"
|
||||
|
||||
#include "mozilla/StaticPrefs_zen.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "mozilla/WindowsVersion.h"
|
||||
#endif
|
||||
@@ -57,11 +59,16 @@ using mozilla::dom::WindowGlobalChild;
|
||||
*canShare = false; \
|
||||
return NS_OK;
|
||||
|
||||
/*
|
||||
* @brief Check if the current context can share data.
|
||||
* @param data The data to share.
|
||||
* @returns True if the current context can share data, false otherwise.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
ZenCommonUtils::PlayHapticFeedback() {
|
||||
// We don't have any haptic feedback on non-macOS platforms
|
||||
// so we can just return.
|
||||
if (!mozilla::StaticPrefs::zen_haptic_feedback_enabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
return PlayHapticFeedbackInternal();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ZenCommonUtils::CanShare(bool* canShare) {
|
||||
auto aWindow = GetMostRecentWindow();
|
||||
@@ -103,7 +110,7 @@ nsresult ZenCommonUtils::ShareInternal(nsCOMPtr<mozIDOMWindowProxy>& aWindow, ns
|
||||
auto ZenCommonUtils::IsSharingSupported() -> bool {
|
||||
#if defined(XP_WIN) && !defined(__MINGW32__)
|
||||
// The first public build that supports ShareCanceled API
|
||||
return IsWindows10BuildOrLater(18956);
|
||||
return mozilla::IsWindows10BuildOrLater(18956);
|
||||
#elif defined(NS_ZEN_CAN_SHARE_NATIVE)
|
||||
return NS_ZEN_CAN_SHARE_NATIVE;
|
||||
#else
|
||||
|
||||
@@ -32,17 +32,28 @@ class ZenCommonUtils final : public nsIZenCommonUtils {
|
||||
*/
|
||||
static auto IsSharingSupported() -> bool;
|
||||
/**
|
||||
* @brief Helper function to share data via the native dialogs.
|
||||
* @param aWindow The window to use for the share dialog.
|
||||
* @param url The URL to share.
|
||||
* @param title The title of the share.
|
||||
* @param text The text to share.
|
||||
* @returns A promise that resolves when the share is complete.
|
||||
*/
|
||||
* @brief Helper function to share data via the native dialogs.
|
||||
* @param aWindow The window to use for the share dialog.
|
||||
* @param url The URL to share.
|
||||
* @param title The title of the share.
|
||||
* @param text The text to share.
|
||||
* @returns A promise that resolves when the share is complete.
|
||||
*/
|
||||
static auto ShareInternal(nsCOMPtr<mozIDOMWindowProxy>& aWindow, nsIURI* url,
|
||||
const nsACString& title, const nsACString& text, uint32_t aX, uint32_t aY,
|
||||
uint32_t aWidth, uint32_t aHeight)
|
||||
-> nsresult;
|
||||
/**
|
||||
* @brief Helper function to play haptic feedback.
|
||||
*/
|
||||
#if !defined(XP_MACOSX)
|
||||
static auto PlayHapticFeedbackInternal() -> nsresult {
|
||||
// No-op on non-macOS platforms
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#else
|
||||
static auto PlayHapticFeedbackInternal() -> nsresult;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace zen
|
||||
|
||||
35
src/zen/toolkit/common/cocoa/ZenHapticFeedback.mm
Normal file
35
src/zen/toolkit/common/cocoa/ZenHapticFeedback.mm
Normal file
@@ -0,0 +1,35 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ZenCommonUtils.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "WidgetUtils.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
extern mozilla::LazyLogModule gCocoaUtilsLog;
|
||||
#undef LOG
|
||||
#define LOG(...) MOZ_LOG(gCocoaUtilsLog, mozilla::LogLevel::Info, (__VA_ARGS__))
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
namespace zen {
|
||||
|
||||
nsresult ZenCommonUtils::PlayHapticFeedbackInternal() {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
if (@available(macOS 10.14, *)) {
|
||||
id<NSHapticFeedbackPerformer> performer = [NSHapticFeedbackManager defaultPerformer];
|
||||
[performer performFeedbackPattern:NSHapticFeedbackPatternAlignment
|
||||
performanceTime:NSHapticFeedbackPerformanceTimeDefault];
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
// Note: This is a no-op on older versions of iOS/macOS
|
||||
}
|
||||
return NS_OK;
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(NS_OK);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -74,5 +74,6 @@ auto nsZenNativeShareInternal::ShowNativeDialog(nsCOMPtr<mozIDOMWindowProxy>& aW
|
||||
[sharingPicker showRelativeToRect:rect
|
||||
ofView:cocoaMru.contentView
|
||||
preferredEdge:NSMaxYEdge];
|
||||
[sharingPicker release];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
SOURCES += [
|
||||
"ZenHapticFeedback.mm",
|
||||
"ZenShareInternal.mm",
|
||||
]
|
||||
|
||||
@@ -9,4 +10,4 @@ LOCAL_INCLUDES += [
|
||||
"/widget",
|
||||
"/widget/cocoa",
|
||||
"/xpcom/base",
|
||||
]
|
||||
]
|
||||
|
||||
@@ -28,5 +28,9 @@ interface nsIZenCommonUtils : nsISupports {
|
||||
* @returns True if the current context can share data, false otherwise.
|
||||
*/
|
||||
boolean canShare();
|
||||
/*
|
||||
* @brief Play a single haptic feedback note if supported.
|
||||
*/
|
||||
void playHapticFeedback();
|
||||
};
|
||||
|
||||
|
||||
@@ -267,6 +267,7 @@
|
||||
}
|
||||
if (previousTexture !== this.currentTexture) {
|
||||
this.updateCurrentWorkspace();
|
||||
Services.zen.playHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
}
|
||||
|
||||
&::-moz-range-track {
|
||||
background: var(--zen-colors-border);
|
||||
background: light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.3));
|
||||
border-radius: 999px;
|
||||
height: 6px;
|
||||
}
|
||||
@@ -225,9 +225,9 @@
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
&:first-of-type {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-width: 3px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-width: 4px;
|
||||
z-index: 2;
|
||||
transition: transform 0.1s;
|
||||
&:hover {
|
||||
@@ -264,7 +264,7 @@
|
||||
transform: translateX(-50%);
|
||||
& .separator,
|
||||
& #PanelUI-zen-gradient-generator-color-toggle-algo {
|
||||
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.5));
|
||||
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.15));
|
||||
}
|
||||
|
||||
& button {
|
||||
@@ -356,13 +356,13 @@
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
border-radius: 50%;
|
||||
background: light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.2));
|
||||
background: light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.3));
|
||||
position: absolute;
|
||||
transition: opacity 0.2s;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
&:not(.active) {
|
||||
opacity: 0.2;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user