@@ -33,7 +33,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
3333import { ThemeIcon } from 'vs/base/common/themables' ;
3434import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService' ;
3535import { getMenuBarVisibility , IFolderToOpen , INativeWindowConfiguration , IWindowSettings , IWorkspaceToOpen , MenuBarVisibility , hasNativeTitlebar , useNativeFullScreen , useWindowControlsOverlay } from 'vs/platform/window/common/window' ;
36- import { defaultBrowserWindowOptions , IWindowsMainService , OpenContext } from 'vs/platform/windows/electron-main/windows' ;
36+ import { defaultBrowserWindowOptions , IWindowsMainService , OpenContext , WindowStateValidator } from 'vs/platform/windows/electron-main/windows' ;
3737import { ISingleFolderWorkspaceIdentifier , IWorkspaceIdentifier , isSingleFolderWorkspaceIdentifier , isWorkspaceIdentifier , toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace' ;
3838import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService' ;
3939import { IWindowState , ICodeWindow , ILoadEvent , WindowMode , WindowError , LoadReason , defaultWindowState , IBaseWindow } from 'vs/platform/window/electron-main/window' ;
@@ -1259,7 +1259,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
12591259 const displays = screen . getAllDisplays ( ) ;
12601260 hasMultipleDisplays = displays . length > 1 ;
12611261
1262- state = this . validateWindowState ( state , displays ) ;
1262+ state = WindowStateValidator . validateWindowState ( this . logService , state , displays ) ;
12631263 } catch ( err ) {
12641264 this . logService . warn ( `Unexpected error validating window state: ${ err } \n${ err . stack } ` ) ; // somehow display API can be picky about the state to validate
12651265 }
@@ -1270,148 +1270,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
12701270 return [ state || defaultWindowState ( ) , hasMultipleDisplays ] ;
12711271 }
12721272
1273- private validateWindowState ( state : IWindowState , displays : Display [ ] ) : IWindowState | undefined {
1274- this . logService . trace ( `window#validateWindowState: validating window state on ${ displays . length } display(s)` , state ) ;
1275-
1276- if (
1277- typeof state . x !== 'number' ||
1278- typeof state . y !== 'number' ||
1279- typeof state . width !== 'number' ||
1280- typeof state . height !== 'number'
1281- ) {
1282- this . logService . trace ( 'window#validateWindowState: unexpected type of state values' ) ;
1283-
1284- return undefined ;
1285- }
1286-
1287- if ( state . width <= 0 || state . height <= 0 ) {
1288- this . logService . trace ( 'window#validateWindowState: unexpected negative values' ) ;
1289-
1290- return undefined ;
1291- }
1292-
1293- // Single Monitor: be strict about x/y positioning
1294- // macOS & Linux: these OS seem to be pretty good in ensuring that a window is never outside of it's bounds.
1295- // Windows: it is possible to have a window with a size that makes it fall out of the window. our strategy
1296- // is to try as much as possible to keep the window in the monitor bounds. we are not as strict as
1297- // macOS and Linux and allow the window to exceed the monitor bounds as long as the window is still
1298- // some pixels (128) visible on the screen for the user to drag it back.
1299- if ( displays . length === 1 ) {
1300- const displayWorkingArea = this . getWorkingArea ( displays [ 0 ] ) ;
1301- if ( displayWorkingArea ) {
1302- this . logService . trace ( 'window#validateWindowState: 1 monitor working area' , displayWorkingArea ) ;
1303-
1304- function ensureStateInDisplayWorkingArea ( ) : void {
1305- if ( ! state || typeof state . x !== 'number' || typeof state . y !== 'number' || ! displayWorkingArea ) {
1306- return ;
1307- }
1308-
1309- if ( state . x < displayWorkingArea . x ) {
1310- // prevent window from falling out of the screen to the left
1311- state . x = displayWorkingArea . x ;
1312- }
1313-
1314- if ( state . y < displayWorkingArea . y ) {
1315- // prevent window from falling out of the screen to the top
1316- state . y = displayWorkingArea . y ;
1317- }
1318- }
1319-
1320- // ensure state is not outside display working area (top, left)
1321- ensureStateInDisplayWorkingArea ( ) ;
1322-
1323- if ( state . width > displayWorkingArea . width ) {
1324- // prevent window from exceeding display bounds width
1325- state . width = displayWorkingArea . width ;
1326- }
1327-
1328- if ( state . height > displayWorkingArea . height ) {
1329- // prevent window from exceeding display bounds height
1330- state . height = displayWorkingArea . height ;
1331- }
1332-
1333- if ( state . x > ( displayWorkingArea . x + displayWorkingArea . width - 128 ) ) {
1334- // prevent window from falling out of the screen to the right with
1335- // 128px margin by positioning the window to the far right edge of
1336- // the screen
1337- state . x = displayWorkingArea . x + displayWorkingArea . width - state . width ;
1338- }
1339-
1340- if ( state . y > ( displayWorkingArea . y + displayWorkingArea . height - 128 ) ) {
1341- // prevent window from falling out of the screen to the bottom with
1342- // 128px margin by positioning the window to the far bottom edge of
1343- // the screen
1344- state . y = displayWorkingArea . y + displayWorkingArea . height - state . height ;
1345- }
1346-
1347- // again ensure state is not outside display working area
1348- // (it may have changed from the previous validation step)
1349- ensureStateInDisplayWorkingArea ( ) ;
1350- }
1351-
1352- return state ;
1353- }
1354-
1355- // Multi Montior (fullscreen): try to find the previously used display
1356- if ( state . display && state . mode === WindowMode . Fullscreen ) {
1357- const display = displays . find ( d => d . id === state . display ) ;
1358- if ( display && typeof display . bounds ?. x === 'number' && typeof display . bounds ?. y === 'number' ) {
1359- this . logService . trace ( 'window#validateWindowState: restoring fullscreen to previous display' ) ;
1360-
1361- const defaults = defaultWindowState ( WindowMode . Fullscreen ) ; // make sure we have good values when the user restores the window
1362- defaults . x = display . bounds . x ; // carefull to use displays x/y position so that the window ends up on the correct monitor
1363- defaults . y = display . bounds . y ;
1364-
1365- return defaults ;
1366- }
1367- }
1368-
1369- // Multi Monitor (non-fullscreen): ensure window is within display bounds
1370- let display : Display | undefined ;
1371- let displayWorkingArea : Rectangle | undefined ;
1372- try {
1373- display = screen . getDisplayMatching ( { x : state . x , y : state . y , width : state . width , height : state . height } ) ;
1374- displayWorkingArea = this . getWorkingArea ( display ) ;
1375- } catch ( error ) {
1376- // Electron has weird conditions under which it throws errors
1377- // e.g. https://github.com/microsoft/vscode/issues/100334 when
1378- // large numbers are passed in
1379- }
1380-
1381- if (
1382- display && // we have a display matching the desired bounds
1383- displayWorkingArea && // we have valid working area bounds
1384- state . x + state . width > displayWorkingArea . x && // prevent window from falling out of the screen to the left
1385- state . y + state . height > displayWorkingArea . y && // prevent window from falling out of the screen to the top
1386- state . x < displayWorkingArea . x + displayWorkingArea . width && // prevent window from falling out of the screen to the right
1387- state . y < displayWorkingArea . y + displayWorkingArea . height // prevent window from falling out of the screen to the bottom
1388- ) {
1389- this . logService . trace ( 'window#validateWindowState: multi-monitor working area' , displayWorkingArea ) ;
1390-
1391- return state ;
1392- }
1393-
1394- return undefined ;
1395- }
1396-
1397- private getWorkingArea ( display : Display ) : Rectangle | undefined {
1398-
1399- // Prefer the working area of the display to account for taskbars on the
1400- // desktop being positioned somewhere (https://github.com/microsoft/vscode/issues/50830).
1401- //
1402- // Linux X11 sessions sometimes report wrong display bounds, so we validate
1403- // the reported sizes are positive.
1404- if ( display . workArea . width > 0 && display . workArea . height > 0 ) {
1405- return display . workArea ;
1406- }
1407-
1408- if ( display . bounds . width > 0 && display . bounds . height > 0 ) {
1409- return display . bounds ;
1410- }
1411-
1412- return undefined ;
1413- }
1414-
14151273 getBounds ( ) : Rectangle {
14161274 const [ x , y ] = this . _win . getPosition ( ) ;
14171275 const [ width , height ] = this . _win . getSize ( ) ;
0 commit comments