Skip to content
40 changes: 40 additions & 0 deletions packages/core/application/window-helper.windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,46 @@ export function getCurrentWindowScale(preferredElement?: FrameworkElementLike |
return 1;
}

const _appWindows = new WeakMap<object, any>();

function getAppWindow(xamlRoot: any): any {
const cached = _appWindows.get(xamlRoot);
if (cached) {
return cached;
}
let appWindow = null;
try {
const id = xamlRoot.ContentIslandEnvironment?.AppWindowId;
appWindow = id ? Microsoft.UI.Windowing.AppWindow.GetFromWindowId(id) : null;
} catch (_e) { }
appWindow ??= (getCurrentWindow() as any)?.AppWindow ?? null;
if (appWindow) {
_appWindows.set(xamlRoot, appWindow);
}
return appWindow;
}

export function getClientOriginOnScreen(xamlRoot: any): { x: number; y: number } | null {
if (!xamlRoot) {
return null;
}
const appWindow = getAppWindow(xamlRoot);
if (!appWindow) {
return null;
}
try {
const position = appWindow.Position;
const size = appWindow.Size;
const client = appWindow.ClientSize;
const border = Math.max(0, (size.Width - client.Width) / 2);
const top = Math.max(0, size.Height - client.Height - border);
const scale = getCurrentWindowScale();
return { x: (position.X + border) / scale, y: (position.Y + top) / scale };
} catch (_e) {
return null;
}
}

export function getCurrentWindowBounds(preferredElement?: FrameworkElementLike | null): { Width: number; Height: number } | null {
return getWindowBounds(resolveCurrentWindow() as unknown as Microsoft.UI.Xaml.Window, preferredElement);
}
Expand Down
34 changes: 33 additions & 1 deletion packages/core/ui/core/view/index.windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from '../properties';

import { ViewCommon, originXProperty, originYProperty } from './view-common';
import type { CoreTypes } from '../../../core-types';
import type { Point } from './view-interfaces';
import { visibilityProperty, opacityProperty, backgroundInternalProperty, translateXProperty, translateYProperty, scaleXProperty, scaleYProperty, rotateProperty, rotateXProperty, rotateYProperty, perspectiveProperty, horizontalAlignmentProperty, verticalAlignmentProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty } from '../../styling/style-properties';
import { LinearGradient } from '../../styling/linear-gradient';
import { widthProperty, heightProperty, minWidthProperty, minHeightProperty, marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty } from '../../styling/style-properties';
Expand All @@ -13,7 +14,7 @@ import { Background } from '../../styling/background';
import { BoxShadow } from '../../styling/box-shadow';
import { Color } from '../../../color';
import { hiddenProperty } from '../view-base';
import { getCurrentWindowBounds, getCurrentWindowContent, getWindowBounds } from '../../../application/window-helper.windows';
import { getClientOriginOnScreen, getCurrentWindowBounds, getCurrentWindowContent, getWindowBounds } from '../../../application/window-helper.windows';
import { ImageSource } from '../../../image-source';
import { ClipPathFunction } from '../../styling/clip-path-function';
import { nativeChildIndex, removeNativeChild } from './native-children.windows';
Expand Down Expand Up @@ -630,6 +631,11 @@ class CompositionBorderHandler {
}
}

let _zeroPoint: Windows.Foundation.Point | undefined;
function zeroPoint(): Windows.Foundation.Point {
return (_zeroPoint ??= Microsoft.UI.Xaml.PointHelper.FromCoordinates(0, 0));
}

export class View extends ViewCommon {
nativeViewProtected: Microsoft.UI.Xaml.FrameworkElement;

Expand Down Expand Up @@ -1178,6 +1184,32 @@ export class View extends ViewCommon {
}
}

private _originIn(target: Microsoft.UI.Xaml.UIElement | null): Point {
try {
const p = (this.nativeViewProtected as any).TransformToVisual(target).TransformPoint(zeroPoint());
return { x: p.X, y: p.Y };
} catch (_e) {
return undefined;
}
}

public getLocationInWindow(): Point {
return (this.nativeViewProtected as any)?.XamlRoot ? this._originIn(null) : undefined;
}

public getLocationOnScreen(): Point {
const root = (this.nativeViewProtected as any)?.XamlRoot;
const inWindow = root ? this._originIn(null) : undefined;
const client = inWindow ? getClientOriginOnScreen(root) : null;
return client ? { x: client.x + inWindow.x, y: client.y + inWindow.y } : undefined;
}

public getLocationRelativeTo(otherView: ViewCommon): Point {
const other = otherView?.nativeViewProtected as any;
const root = (this.nativeViewProtected as any)?.XamlRoot;
return root && other?.XamlRoot === root ? this._originIn(other) : undefined;
}

// Button-family controls override their template's brush resources. Probed on first need: most
// views never set a colour or background, and the probe is a WinRT call.
protected _nativeIsButton(): boolean {
Expand Down
Loading