mirror of
https://github.com/zen-browser/desktop.git
synced 2025-10-05 01:16:35 +00:00
Compare commits
2 Commits
dev
...
glance-ref
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1694f81637 | ||
![]() |
bdf015fd99 |
@@ -33,8 +33,6 @@ zen-glance-trigger-shift-click =
|
||||
.label = Shift + Click
|
||||
zen-glance-trigger-meta-click =
|
||||
.label = Meta (Command) + Click
|
||||
zen-glance-trigger-mantain-click =
|
||||
.label = Hold Click (Coming Soon!)
|
||||
|
||||
zen-look-and-feel-compact-view-header = Show in compact view
|
||||
zen-look-and-feel-compact-view-description = Only show the toolbars you use!
|
||||
|
@@ -8,9 +8,6 @@
|
||||
- name: zen.glance.enable-contextmenu-search
|
||||
value: true
|
||||
|
||||
- name: zen.glance.hold-duration
|
||||
value: 300 # in ms
|
||||
|
||||
- name: zen.glance.open-essential-external-links
|
||||
value: true
|
||||
|
||||
|
@@ -15,6 +15,15 @@ IGNORE_PREFS_FILE_OUT = os.path.join(
|
||||
)
|
||||
|
||||
|
||||
class JSONWithCommentsDecoder(json.JSONDecoder):
|
||||
def __init__(self, **kw):
|
||||
super().__init__(**kw)
|
||||
|
||||
def decode(self, s: str) -> any:
|
||||
s = '\n'.join(l for l in s.split('\n') if not l.lstrip(' ').startswith('//'))
|
||||
return super().decode(s)
|
||||
|
||||
|
||||
def copy_ignore_prefs():
|
||||
print("Copying ignorePrefs.json from src/zen/tests to engine/testing/mochitest...")
|
||||
# if there are prefs that dont exist on output file, copy them from input file
|
||||
@@ -22,7 +31,7 @@ def copy_ignore_prefs():
|
||||
with open(IGNORE_PREFS_FILE_OUT, 'r') as f:
|
||||
all_prefs = json.load(f)
|
||||
with open(IGNORE_PREFS_FILE_IN, 'r') as f_in:
|
||||
new_prefs = json.load(f_in)
|
||||
new_prefs = json.load(f_in, cls=JSONWithCommentsDecoder)
|
||||
all_prefs.extend(p for p in new_prefs if p not in all_prefs)
|
||||
with open(IGNORE_PREFS_FILE_OUT, 'w') as f_out:
|
||||
json.dump(all_prefs, f_out, indent=2)
|
||||
|
@@ -124,7 +124,6 @@
|
||||
#ifdef XP_MACOSX
|
||||
<menuitem data-l10n-id="zen-glance-trigger-meta-click" value="meta"/>
|
||||
#endif
|
||||
<menuitem data-l10n-id="zen-glance-trigger-mantain-click" value="mantain" disabled="true"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
|
@@ -8,12 +8,12 @@
|
||||
#tabbrowser-tabpanels[dragging-split='true'] {
|
||||
width: -moz-available;
|
||||
position: relative;
|
||||
overflow: clip;
|
||||
|
||||
&.browserSidebarContainer {
|
||||
:root:not([zen-no-padding='true']) & {
|
||||
:root:not([zen-no-padding='true']) &:not(.zen-glance-overlay) {
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
& browser[type='content'] {
|
||||
|
@@ -177,16 +177,15 @@ body > #confetti {
|
||||
#zen-sidebar-foot-buttons & {
|
||||
--tab-border-radius: 6px;
|
||||
--toolbarbutton-border-radius: var(--tab-border-radius);
|
||||
--toolbarbutton-inner-padding: 6px;
|
||||
--toolbarbutton-inner-padding: 5px;
|
||||
--toolbarbutton-outer-padding: 2px;
|
||||
}
|
||||
|
||||
transition:
|
||||
background-color 0.1s,
|
||||
transform 0.2s;
|
||||
|
||||
&:active:hover {
|
||||
transform: scale(0.95);
|
||||
scale 0.2s;
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,10 @@
|
||||
// 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/.
|
||||
export class ZenGlanceChild extends JSWindowActorChild {
|
||||
#activationMethod;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.mouseUpListener = this.handleMouseUp.bind(this);
|
||||
this.mouseDownListener = this.handleMouseDown.bind(this);
|
||||
this.clickListener = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
@@ -22,51 +21,34 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
}
|
||||
}
|
||||
|
||||
async getActivationMethod() {
|
||||
if (this._activationMethod === undefined) {
|
||||
this._activationMethod = await this.sendQuery('ZenGlance:GetActivationMethod');
|
||||
}
|
||||
return this._activationMethod;
|
||||
}
|
||||
|
||||
async getHoverActivationDelay() {
|
||||
if (this._hoverActivationDelay === undefined) {
|
||||
this._hoverActivationDelay = await this.sendQuery('ZenGlance:GetHoverActivationDelay');
|
||||
}
|
||||
return this._hoverActivationDelay;
|
||||
async #initActivationMethod() {
|
||||
this.#activationMethod = await this.sendQuery('ZenGlance:GetActivationMethod');
|
||||
}
|
||||
|
||||
async initiateGlance() {
|
||||
this.mouseIsDown = false;
|
||||
const activationMethod = await this.getActivationMethod();
|
||||
if (activationMethod === 'mantain') {
|
||||
this.contentWindow.addEventListener('mousedown', this.mouseDownListener);
|
||||
this.contentWindow.addEventListener('mouseup', this.mouseUpListener);
|
||||
|
||||
this.contentWindow.document.removeEventListener('click', this.clickListener);
|
||||
} else if (
|
||||
activationMethod === 'ctrl' ||
|
||||
activationMethod === 'alt' ||
|
||||
activationMethod === 'shift'
|
||||
) {
|
||||
this.contentWindow.document.addEventListener('click', this.clickListener, { capture: true });
|
||||
|
||||
this.contentWindow.removeEventListener('mousedown', this.mouseDownListener);
|
||||
this.contentWindow.removeEventListener('mouseup', this.mouseUpListener);
|
||||
}
|
||||
await this.#initActivationMethod();
|
||||
this.contentWindow.document.addEventListener('click', this.clickListener, { capture: true });
|
||||
}
|
||||
|
||||
ensureOnlyKeyModifiers(event) {
|
||||
return !(event.ctrlKey ^ event.altKey ^ event.shiftKey ^ event.metaKey);
|
||||
}
|
||||
|
||||
openGlance(target) {
|
||||
openGlance(target, originalTarget) {
|
||||
let url = target.href;
|
||||
// Add domain to relative URLs
|
||||
if (!url.match(/^(?:[a-z]+:)?\/\//i)) {
|
||||
url = this.contentWindow.location.origin + url;
|
||||
}
|
||||
const rect = target.getBoundingClientRect();
|
||||
// Get the largest element we can get. If the `A` element
|
||||
// is a parent of the original target, use the anchor element,
|
||||
// otherwise use the original target.
|
||||
let rect = originalTarget.getBoundingClientRect();
|
||||
const anchorRect = target.getBoundingClientRect();
|
||||
if (anchorRect.width * anchorRect.height > rect.width * rect.height) {
|
||||
rect = anchorRect;
|
||||
}
|
||||
this.sendAsyncMessage('ZenGlance:OpenGlance', {
|
||||
url,
|
||||
clientX: rect.left,
|
||||
@@ -76,35 +58,11 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseUp(event) {
|
||||
if (this.hasClicked) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.hasClicked = false;
|
||||
}
|
||||
this.mouseIsDown = null;
|
||||
}
|
||||
|
||||
async handleMouseDown(event) {
|
||||
const target = event.target.closest('A');
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
this.mouseIsDown = target;
|
||||
const hoverActivationDelay = await this.getHoverActivationDelay();
|
||||
this.contentWindow.setTimeout(() => {
|
||||
if (this.mouseIsDown === target) {
|
||||
this.hasClicked = true;
|
||||
this.openGlance(target);
|
||||
}
|
||||
}, hoverActivationDelay);
|
||||
}
|
||||
|
||||
handleClick(event) {
|
||||
if (this.ensureOnlyKeyModifiers(event) || event.button !== 0 || event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
const activationMethod = this._activationMethod;
|
||||
const activationMethod = this.#activationMethod;
|
||||
if (activationMethod === 'ctrl' && !event.ctrlKey) {
|
||||
return;
|
||||
} else if (activationMethod === 'alt' && !event.altKey) {
|
||||
@@ -113,8 +71,6 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
return;
|
||||
} else if (activationMethod === 'meta' && !event.metaKey) {
|
||||
return;
|
||||
} else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') {
|
||||
return;
|
||||
}
|
||||
// get closest A element
|
||||
const target = event.target.closest('A');
|
||||
@@ -122,7 +78,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.openGlance(target);
|
||||
this.openGlance(target, event.originalTarget || event.target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,9 +11,6 @@ export class ZenGlanceParent extends JSWindowActorParent {
|
||||
case 'ZenGlance:GetActivationMethod': {
|
||||
return Services.prefs.getStringPref('zen.glance.activation-method', 'ctrl');
|
||||
}
|
||||
case 'ZenGlance:GetHoverActivationDelay': {
|
||||
return Services.prefs.getIntPref('zen.glance.hold-duration', 500);
|
||||
}
|
||||
case 'ZenGlance:OpenGlance': {
|
||||
this.openGlance(this.browsingContext.topChromeWindow, message.data);
|
||||
break;
|
||||
@@ -31,7 +28,38 @@ export class ZenGlanceParent extends JSWindowActorParent {
|
||||
}
|
||||
}
|
||||
|
||||
openGlance(window, data) {
|
||||
#imageBitmapToBase64(imageBitmap) {
|
||||
// 1. Create a canvas with the same size as the ImageBitmap
|
||||
const canvas = this.browsingContext.topChromeWindow.document.createElement('canvas');
|
||||
canvas.width = imageBitmap.width;
|
||||
canvas.height = imageBitmap.height;
|
||||
|
||||
// 2. Draw the ImageBitmap onto the canvas
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(imageBitmap, 0, 0);
|
||||
|
||||
// 3. Convert the canvas content to a Base64 string (PNG by default)
|
||||
const base64String = canvas.toDataURL('image/png');
|
||||
return base64String;
|
||||
}
|
||||
|
||||
async openGlance(window, data) {
|
||||
const win = this.browsingContext.topChromeWindow;
|
||||
const tabPanels = win.gBrowser.tabpanels;
|
||||
// Make the rect relative to the tabpanels. We dont do it directly on the
|
||||
// content process since it does not take into account scroll. This way, we can
|
||||
// be sure that the coordinates are correct.
|
||||
const tabPanelsRect = tabPanels.getBoundingClientRect();
|
||||
const rect = new DOMRect(
|
||||
data.clientX + tabPanelsRect.left,
|
||||
data.clientY + tabPanelsRect.top,
|
||||
data.width,
|
||||
data.height
|
||||
);
|
||||
const elementData = await this.#imageBitmapToBase64(
|
||||
await win.browsingContext.currentWindowGlobal.drawSnapshot(rect, 1, 'transparent', true)
|
||||
);
|
||||
data.elementData = elementData;
|
||||
window.gZenGlanceManager.openGlance(data);
|
||||
}
|
||||
}
|
||||
|
@@ -14,11 +14,11 @@
|
||||
gap: 12px;
|
||||
max-width: 56px;
|
||||
|
||||
:root[zen-right-side='true'] & {
|
||||
:root:not([zen-right-side='true']) & {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
:root:not([zen-right-side='true']) & {
|
||||
:root[zen-right-side='true'] & {
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
}
|
||||
|
||||
.browserSidebarContainer.zen-glance-background,
|
||||
.browserSidebarContainer.zen-glance-overlay .browserContainer {
|
||||
.browserSidebarContainer.zen-glance-overlay .browserContainer:not([fade-out='true']) {
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
}
|
||||
@@ -116,14 +116,19 @@
|
||||
}
|
||||
|
||||
& .browserContainer {
|
||||
background: light-dark(rgb(255, 255, 255), rgb(32, 32, 32));
|
||||
transform: translate(-50%, -50%);
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
flex: unset !important;
|
||||
/* Promote to its own layer during transitions to reduce jank */
|
||||
will-change: transform, opacity, top, left, width, height;
|
||||
will-change: transform, top, left;
|
||||
width: 85%;
|
||||
height: 100%;
|
||||
|
||||
&:not([has-finished-animation='true']) #statuspanel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&[has-finished-animation='true'] {
|
||||
position: relative !important;
|
||||
@@ -140,10 +145,15 @@
|
||||
}
|
||||
|
||||
& browser {
|
||||
background: light-dark(rgb(255, 255, 255), rgb(32, 32, 32)) !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
transition: opacity 0.08s;
|
||||
|
||||
@starting-style {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&[animate='true'] {
|
||||
@@ -153,8 +163,17 @@
|
||||
|
||||
&[fade-out='true'] {
|
||||
& browser {
|
||||
transition: opacity 0.2s ease;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.zen-glance-element-preview {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
}
|
||||
|
@@ -958,10 +958,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
* @returns {Element} The tab browser panel.
|
||||
*/
|
||||
get tabBrowserPanel() {
|
||||
if (!this._tabBrowserPanel) {
|
||||
this._tabBrowserPanel = document.getElementById('tabbrowser-tabpanels');
|
||||
}
|
||||
return this._tabBrowserPanel;
|
||||
return gBrowser.tabpanels;
|
||||
}
|
||||
|
||||
get splitViewActive() {
|
||||
|
@@ -1,6 +1,14 @@
|
||||
// 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/.
|
||||
//
|
||||
// This file lists preferences that are ignored when running mochitests.
|
||||
// Add here any preference that is not relevant for testing Zen Modus.
|
||||
// This prevents unnecessary test re-runs when these preferences are changed.
|
||||
[
|
||||
"zen.mods.updated-value-observer",
|
||||
"zen.mods.last-update",
|
||||
"zen.view.compact.enable-at-startup",
|
||||
"zen.urlbar.suggestions-learner",
|
||||
"browser.newtabpage.activity-stream.trendingSearch.defaultSearchEngine"
|
||||
]
|
||||
|
@@ -99,7 +99,7 @@
|
||||
|
||||
#createWorkspaceIcon(workspace) {
|
||||
const button = document.createXULElement('toolbarbutton');
|
||||
button.setAttribute('class', 'subviewbutton toolbarbutton-1');
|
||||
button.setAttribute('class', 'subviewbutton');
|
||||
button.setAttribute('tooltiptext', workspace.name);
|
||||
button.setAttribute('zen-workspace-id', workspace.uuid);
|
||||
button.setAttribute('context', 'zenWorkspaceMoreActions');
|
||||
|
@@ -3018,7 +3018,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
|
||||
parent.removeAttribute('icons-overflow');
|
||||
return;
|
||||
}
|
||||
const maxButtonSize = 28; // IMPORTANT: This should match the CSS size of the icons
|
||||
const maxButtonSize = 26; // IMPORTANT: This should match the CSS size of the icons
|
||||
const minButtonSize = 15;
|
||||
const separation = 3; // Space between icons
|
||||
|
||||
|
@@ -33,8 +33,8 @@
|
||||
|
||||
& toolbarbutton {
|
||||
margin: 0;
|
||||
max-width: 28px;
|
||||
height: 28px;
|
||||
max-width: 26px;
|
||||
height: 26px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 !important;
|
||||
@@ -63,8 +63,7 @@
|
||||
transition:
|
||||
filter 0.2s,
|
||||
opacity 0.2s,
|
||||
width 0.1s,
|
||||
transform 0.2s;
|
||||
width 0.1s;
|
||||
|
||||
&[active='true'],
|
||||
&:hover,
|
||||
|
Reference in New Issue
Block a user