Skip to content

Commit

Permalink
fix: 修复windows下复制粘贴问题
Browse files Browse the repository at this point in the history
  • Loading branch information
awehook committed Apr 1, 2020
1 parent 777a1f5 commit c2897a1
Show file tree
Hide file tree
Showing 40 changed files with 8,199 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/blink-mind
Submodule blink-mind updated from 80e41c to ed681e
169 changes: 169 additions & 0 deletions src/main/custom-electron-titlebar/browser/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Emitter, Event } from '../common/event';
import { IDisposable } from '../common/lifecycle';
import * as platform from '../common/platform';

class WindowManager {

public static readonly INSTANCE = new WindowManager();

// --- Zoom Level
private _zoomLevel: number = 0;
private _lastZoomLevelChangeTime: number = 0;
private readonly _onDidChangeZoomLevel = new Emitter<number>();

public readonly onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event;
public getZoomLevel(): number {
return this._zoomLevel;
}
public getTimeSinceLastZoomLevelChanged(): number {
return Date.now() - this._lastZoomLevelChangeTime;
}
public setZoomLevel(zoomLevel: number, isTrusted: boolean): void {
if (this._zoomLevel === zoomLevel) {
return;
}

this._zoomLevel = zoomLevel;
// See https://github.com/Microsoft/vscode/issues/26151
this._lastZoomLevelChangeTime = isTrusted ? 0 : Date.now();
this._onDidChangeZoomLevel.fire(this._zoomLevel);
}

// --- Zoom Factor
private _zoomFactor: number = 0;

public getZoomFactor(): number {
return this._zoomFactor;
}
public setZoomFactor(zoomFactor: number): void {
this._zoomFactor = zoomFactor;
}

// --- Pixel Ratio
public getPixelRatio(): number {
let ctx = document.createElement('canvas').getContext('2d');
let dpr = window.devicePixelRatio || 1;
let bsr = (<any>ctx).webkitBackingStorePixelRatio ||
(<any>ctx).mozBackingStorePixelRatio ||
(<any>ctx).msBackingStorePixelRatio ||
(<any>ctx).oBackingStorePixelRatio ||
(<any>ctx).backingStorePixelRatio || 1;
return dpr / bsr;
}

// --- Fullscreen
private _fullscreen: boolean;
private readonly _onDidChangeFullscreen = new Emitter<void>();

public readonly onDidChangeFullscreen: Event<void> = this._onDidChangeFullscreen.event;
public setFullscreen(fullscreen: boolean): void {
if (this._fullscreen === fullscreen) {
return;
}

this._fullscreen = fullscreen;
this._onDidChangeFullscreen.fire();
}
public isFullscreen(): boolean {
return this._fullscreen;
}

// --- Accessibility
private _accessibilitySupport = platform.AccessibilitySupport.Unknown;
private readonly _onDidChangeAccessibilitySupport = new Emitter<void>();

public readonly onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event;
public setAccessibilitySupport(accessibilitySupport: platform.AccessibilitySupport): void {
if (this._accessibilitySupport === accessibilitySupport) {
return;
}

this._accessibilitySupport = accessibilitySupport;
this._onDidChangeAccessibilitySupport.fire();
}
public getAccessibilitySupport(): platform.AccessibilitySupport {
return this._accessibilitySupport;
}
}

/** A zoom index, e.g. 1, 2, 3 */
export function setZoomLevel(zoomLevel: number, isTrusted: boolean): void {
WindowManager.INSTANCE.setZoomLevel(zoomLevel, isTrusted);
}
export function getZoomLevel(): number {
return WindowManager.INSTANCE.getZoomLevel();
}
/** Returns the time (in ms) since the zoom level was changed */
export function getTimeSinceLastZoomLevelChanged(): number {
return WindowManager.INSTANCE.getTimeSinceLastZoomLevelChanged();
}
export function onDidChangeZoomLevel(callback: (zoomLevel: number) => void): IDisposable {
return WindowManager.INSTANCE.onDidChangeZoomLevel(callback);
}

/** The zoom scale for an index, e.g. 1, 1.2, 1.4 */
export function getZoomFactor(): number {
return WindowManager.INSTANCE.getZoomFactor();
}
export function setZoomFactor(zoomFactor: number): void {
WindowManager.INSTANCE.setZoomFactor(zoomFactor);
}

export function getPixelRatio(): number {
return WindowManager.INSTANCE.getPixelRatio();
}

export function setFullscreen(fullscreen: boolean): void {
WindowManager.INSTANCE.setFullscreen(fullscreen);
}
export function isFullscreen(): boolean {
return WindowManager.INSTANCE.isFullscreen();
}
export const onDidChangeFullscreen = WindowManager.INSTANCE.onDidChangeFullscreen;

export function setAccessibilitySupport(accessibilitySupport: platform.AccessibilitySupport): void {
WindowManager.INSTANCE.setAccessibilitySupport(accessibilitySupport);
}
export function getAccessibilitySupport(): platform.AccessibilitySupport {
return WindowManager.INSTANCE.getAccessibilitySupport();
}
export function onDidChangeAccessibilitySupport(callback: () => void): IDisposable {
return WindowManager.INSTANCE.onDidChangeAccessibilitySupport(callback);
}

const userAgent = navigator.userAgent;

export const isIE = (userAgent.indexOf('Trident') >= 0);
export const isEdge = (userAgent.indexOf('Edge/') >= 0);
export const isEdgeOrIE = isIE || isEdge;

export const isOpera = (userAgent.indexOf('Opera') >= 0);
export const isFirefox = (userAgent.indexOf('Firefox') >= 0);
export const isWebKit = (userAgent.indexOf('AppleWebKit') >= 0);
export const isChrome = (userAgent.indexOf('Chrome') >= 0);
export const isSafari = (!isChrome && (userAgent.indexOf('Safari') >= 0));
export const isWebkitWebView = (!isChrome && !isSafari && isWebKit);
export const isIPad = (userAgent.indexOf('iPad') >= 0);
export const isEdgeWebView = isEdge && (userAgent.indexOf('WebView/') >= 0);

export function hasClipboardSupport() {
if (isIE) {
return false;
}

if (isEdge) {
let index = userAgent.indexOf('Edge/');
let version = parseInt(userAgent.substring(index + 5, userAgent.indexOf('.', index)), 10);

if (!version || (version >= 12 && version <= 16)) {
return false;
}
}

return true;
}
40 changes: 40 additions & 0 deletions src/main/custom-electron-titlebar/browser/event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Event, Emitter } from '../common/event';

export type EventHandler = HTMLElement | HTMLDocument | Window;

export interface IDomEvent {
<K extends keyof HTMLElementEventMap>(element: EventHandler, type: K, useCapture?: boolean): Event<HTMLElementEventMap[K]>;
(element: EventHandler, type: string, useCapture?: boolean): Event<any>;
}

export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?: boolean) => {
const fn = e => emitter.fire(e);
const emitter = new Emitter<any>({
onFirstListenerAdd: () => {
element.addEventListener(type, fn, useCapture);
},
onLastListenerRemove: () => {
element.removeEventListener(type, fn, useCapture);
}
});

return emitter.event;
};

export interface CancellableEvent {
preventDefault();
stopPropagation();
}

export function stop<T extends CancellableEvent>(event: Event<T>): Event<T> {
return Event.map(event, e => {
e.preventDefault();
e.stopPropagation();
return e;
});
}
134 changes: 134 additions & 0 deletions src/main/custom-electron-titlebar/browser/iframe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

/**
* Represents a window in a possible chain of iframes
*/
export interface IWindowChainElement {
/**
* The window object for it
*/
window: Window;
/**
* The iframe element inside the window.parent corresponding to window
*/
iframeElement: HTMLIFrameElement | null;
}

let hasDifferentOriginAncestorFlag: boolean = false;
let sameOriginWindowChainCache: IWindowChainElement[] | null = null;

function getParentWindowIfSameOrigin(w: Window): Window | null {
if (!w.parent || w.parent === w) {
return null;
}

// Cannot really tell if we have access to the parent window unless we try to access something in it
try {
let location = w.location;
let parentLocation = w.parent.location;
if (location.protocol !== parentLocation.protocol || location.hostname !== parentLocation.hostname || location.port !== parentLocation.port) {
hasDifferentOriginAncestorFlag = true;
return null;
}
} catch (e) {
hasDifferentOriginAncestorFlag = true;
return null;
}

return w.parent;
}

function findIframeElementInParentWindow(parentWindow: Window, childWindow: Window): HTMLIFrameElement | null {
let parentWindowIframes = parentWindow.document.getElementsByTagName('iframe');
let iframe: HTMLIFrameElement;
for (let i = 0, len = parentWindowIframes.length; i < len; i++) {
iframe = parentWindowIframes[i];
if (iframe.contentWindow === childWindow) {
return iframe;
}
}
return null;
}

export class IframeUtils {

/**
* Returns a chain of embedded windows with the same origin (which can be accessed programmatically).
* Having a chain of length 1 might mean that the current execution environment is running outside of an iframe or inside an iframe embedded in a window with a different origin.
* To distinguish if at one point the current execution environment is running inside a window with a different origin, see hasDifferentOriginAncestor()
*/
public static getSameOriginWindowChain(): IWindowChainElement[] {
if (!sameOriginWindowChainCache) {
sameOriginWindowChainCache = [];
let w: Window | null = window;
let parent: Window | null;
do {
parent = getParentWindowIfSameOrigin(w);
if (parent) {
sameOriginWindowChainCache.push({
window: w,
iframeElement: findIframeElementInParentWindow(parent, w)
});
} else {
sameOriginWindowChainCache.push({
window: w,
iframeElement: null
});
}
w = parent;
} while (w);
}
return sameOriginWindowChainCache.slice(0);
}

/**
* Returns true if the current execution environment is chained in a list of iframes which at one point ends in a window with a different origin.
* Returns false if the current execution environment is not running inside an iframe or if the entire chain of iframes have the same origin.
*/
public static hasDifferentOriginAncestor(): boolean {
if (!sameOriginWindowChainCache) {
this.getSameOriginWindowChain();
}
return hasDifferentOriginAncestorFlag;
}

/**
* Returns the position of `childWindow` relative to `ancestorWindow`
*/
public static getPositionOfChildWindowRelativeToAncestorWindow(childWindow: Window, ancestorWindow: any) {

if (!ancestorWindow || childWindow === ancestorWindow) {
return {
top: 0,
left: 0
};
}

let top = 0, left = 0;

let windowChain = this.getSameOriginWindowChain();

for (const windowChainEl of windowChain) {

if (windowChainEl.window === ancestorWindow) {
break;
}

if (!windowChainEl.iframeElement) {
break;
}

let boundingRect = windowChainEl.iframeElement.getBoundingClientRect();
top += boundingRect.top;
left += boundingRect.left;
}

return {
top: top,
left: left
};
}
}
Loading

0 comments on commit c2897a1

Please sign in to comment.