@theia/core 1.67.0-next.59 → 1.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +165 -67
  3. package/i18n/nls.de.json +165 -67
  4. package/i18n/nls.es.json +165 -67
  5. package/i18n/nls.fr.json +165 -67
  6. package/i18n/nls.hu.json +165 -67
  7. package/i18n/nls.it.json +165 -67
  8. package/i18n/nls.ja.json +165 -67
  9. package/i18n/nls.json +178 -80
  10. package/i18n/nls.ko.json +165 -67
  11. package/i18n/nls.pl.json +165 -67
  12. package/i18n/nls.pt-br.json +165 -67
  13. package/i18n/nls.ru.json +165 -67
  14. package/i18n/nls.tr.json +165 -67
  15. package/i18n/nls.zh-cn.json +167 -69
  16. package/i18n/nls.zh-tw.json +167 -69
  17. package/lib/browser/catalog.json +248 -12
  18. package/lib/common/core-preferences.d.ts.map +1 -1
  19. package/lib/common/core-preferences.js +2 -1
  20. package/lib/common/core-preferences.js.map +1 -1
  21. package/lib/common/preferences/preference-provider.d.ts +4 -0
  22. package/lib/common/preferences/preference-provider.d.ts.map +1 -1
  23. package/lib/common/preferences/preference-provider.js.map +1 -1
  24. package/lib/common/preferences/preference-service.d.ts.map +1 -1
  25. package/lib/common/preferences/preference-service.js +4 -4
  26. package/lib/common/preferences/preference-service.js.map +1 -1
  27. package/lib/common/severity.js +2 -2
  28. package/lib/common/severity.js.map +1 -1
  29. package/lib/common/types.d.ts +3 -0
  30. package/lib/common/types.d.ts.map +1 -1
  31. package/lib/common/types.js.map +1 -1
  32. package/lib/electron-common/electron-window-preferences.d.ts.map +1 -1
  33. package/lib/electron-common/electron-window-preferences.js +1 -2
  34. package/lib/electron-common/electron-window-preferences.js.map +1 -1
  35. package/lib/electron-main/electron-main-application.d.ts +13 -0
  36. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  37. package/lib/electron-main/electron-main-application.js +48 -6
  38. package/lib/electron-main/electron-main-application.js.map +1 -1
  39. package/lib/node/application-server.d.ts.map +1 -1
  40. package/lib/node/application-server.js +2 -3
  41. package/lib/node/application-server.js.map +1 -1
  42. package/lib/node/backend-global.d.ts +15 -0
  43. package/lib/node/backend-global.d.ts.map +1 -0
  44. package/lib/node/backend-global.js +34 -0
  45. package/lib/node/backend-global.js.map +1 -0
  46. package/lib/node/index.d.ts +1 -0
  47. package/lib/node/index.d.ts.map +1 -1
  48. package/lib/node/index.js +1 -0
  49. package/lib/node/index.js.map +1 -1
  50. package/package.json +6 -6
  51. package/src/browser/style/index.css +5 -0
  52. package/src/common/core-preferences.ts +2 -1
  53. package/src/common/i18n/nls.metadata.json +7020 -1642
  54. package/src/common/preferences/preference-provider.ts +4 -0
  55. package/src/common/preferences/preference-service.ts +7 -3
  56. package/src/common/severity.ts +2 -2
  57. package/src/common/types.ts +6 -0
  58. package/src/electron-common/electron-window-preferences.ts +1 -2
  59. package/src/electron-main/electron-main-application.ts +53 -6
  60. package/src/node/application-server.ts +2 -3
  61. package/src/node/backend-global.ts +41 -0
  62. package/src/node/index.ts +1 -0
@@ -27,6 +27,10 @@ export interface PreferenceProviderDataChange {
27
27
  readonly preferenceName: string;
28
28
  /**
29
29
  * The new value of the changed preference.
30
+ * Can be `undefined` for multiple reasons:
31
+ * - The preference has been reset to its default value.
32
+ * - The preference has been reset and has no value explicitly stored.
33
+ * If `undefined`, use the preference service to determine the effective new value if needed.
30
34
  */
31
35
  readonly newValue?: JSONValue;
32
36
  /**
@@ -16,7 +16,7 @@
16
16
 
17
17
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
18
 
19
- import { JSONExt, JSONValue } from '@lumino/coreutils';
19
+ import { JSONValue } from '@lumino/coreutils';
20
20
  import { inject, injectable, postConstruct } from 'inversify';
21
21
  import { Disposable, DisposableCollection, Emitter, Event, deepFreeze, unreachable } from '../../common';
22
22
  import { Deferred } from '../../common/promise-util';
@@ -538,14 +538,18 @@ export class PreferenceServiceImpl implements PreferenceService {
538
538
  if (inspection) {
539
539
  const scopesToChange = this.getScopesToChange(inspection, value);
540
540
  const isDeletion = value === undefined
541
- || (scopesToChange.length === 1 && scopesToChange[0] === PreferenceScope.User && JSONExt.deepEqual(value, inspection.defaultValue));
541
+ || (
542
+ scopesToChange.length === 1
543
+ && scopesToChange[0] === PreferenceScope.User
544
+ && PreferenceUtils.deepEqual(value, inspection.defaultValue)
545
+ );
542
546
  const effectiveValue = isDeletion ? undefined : value;
543
547
  await Promise.all(scopesToChange.map(scope => this.set(preferenceName, effectiveValue, scope, resourceUri)));
544
548
  }
545
549
  }
546
550
 
547
551
  protected getScopesToChange(inspection: PreferenceInspection<any>, intendedValue: any): PreferenceScope[] {
548
- if (JSONExt.deepEqual(inspection.value, intendedValue)) {
552
+ if (PreferenceUtils.deepEqual(inspection.value, intendedValue)) {
549
553
  return [];
550
554
  }
551
555
 
@@ -93,9 +93,9 @@ export namespace Severity {
93
93
 
94
94
  export function toLocaleString(severity: string | Severity): string {
95
95
  if (severity === Severity.Error || severity === error) {
96
- return nls.localize('theia/core/severity/errors', 'Errors');
96
+ return nls.localizeByDefault('Errors');
97
97
  } else if (severity === Severity.Warning || severity === warning) {
98
- return nls.localize('theia/core/severity/warnings', 'Warnings');
98
+ return nls.localizeByDefault('Warnings');
99
99
  } else if (severity === Severity.Info || severity === info) {
100
100
  return nls.localizeByDefault('Info');
101
101
  } else if (severity === Severity.Log || severity === log) {
@@ -30,6 +30,12 @@ export type RecursivePartial<T> = {
30
30
  ? RecursivePartial<I>[]
31
31
  : RecursivePartial<T[P]>;
32
32
  };
33
+ export type RecursiveReadonly<T> = {
34
+ readonly [P in keyof T]: T[P] extends Array<infer I>
35
+ ? RecursiveReadonly<I>[]
36
+ : T[P] extends object ? RecursiveReadonly<T[P]>
37
+ : T[P];
38
+ };
33
39
 
34
40
  export function isBoolean(value: unknown): value is boolean {
35
41
  return value === true || value === false;
@@ -45,8 +45,7 @@ export const electronWindowPreferencesSchema: PreferenceSchema = {
45
45
  enum: ['native', 'custom'],
46
46
  default: isWindows ? 'custom' : 'native',
47
47
  scope: PreferenceScope.User,
48
- // eslint-disable-next-line max-len
49
- description: nls.localizeByDefault('Adjust the appearance of the window title bar to be native by the OS or custom. On Linux and Windows, this setting also affects the application and context menu appearances. Changes require a full restart to apply.'),
48
+ description: nls.localizeByDefault('Adjust the appearance of the window title bar to be native by the OS or custom. Changes require a full restart to apply.'),
50
49
  included: !isOSX
51
50
  },
52
51
  }
@@ -43,6 +43,7 @@ import { TheiaRendererAPI } from './electron-api-main';
43
43
  import { StopReason } from '../common/frontend-application-state';
44
44
  import { dynamicRequire } from '../node/dynamic-require';
45
45
  import { ThemeMode } from '../common/theme';
46
+ import { backendGlobal } from '../node/backend-global';
46
47
 
47
48
  export { ElectronMainApplicationGlobals };
48
49
 
@@ -590,11 +591,9 @@ export class ElectronMainApplication {
590
591
  }
591
592
 
592
593
  protected getDefaultTheiaWindowBounds(): TheiaBrowserWindowOptions {
593
- // The `screen` API must be required when the application is ready.
594
- // See: https://electronjs.org/docs/api/screen#screen
594
+ const { bounds } = this.getDisplayForNewWindow();
595
595
  // We must center by hand because `browserWindow.center()` fails on multi-screen setups
596
596
  // See: https://github.com/electron/electron/issues/3490
597
- const { bounds } = screen.getDisplayNearestPoint(screen.getCursorScreenPoint());
598
597
  const height = Math.round(bounds.height * (2 / 3));
599
598
  const width = Math.round(bounds.width * (2 / 3));
600
599
  const y = Math.round(bounds.y + (bounds.height - height) / 2);
@@ -607,6 +606,52 @@ export class ElectronMainApplication {
607
606
  };
608
607
  }
609
608
 
609
+ /**
610
+ * Returns the display where a new window should be opened.
611
+ * Attempts to use the display nearest to the cursor position for multi-monitor setups.
612
+ * Falls back to the primary display if cursor position cannot be determined
613
+ * (e.g., on Wayland before any window is opened).
614
+ * See: https://github.com/eclipse-theia/theia/issues/16582
615
+ */
616
+ protected getDisplayForNewWindow(): Electron.Display {
617
+ // On Wayland, screen.getCursorScreenPoint() causes a native crash (SIGSEGV)
618
+ // before any window is opened. Detect Wayland and use primary display instead.
619
+ if (this.isWaylandSession()) {
620
+ console.debug('Running under Wayland, using primary display for new window.');
621
+ return screen.getPrimaryDisplay();
622
+ }
623
+ try {
624
+ return screen.getDisplayNearestPoint(screen.getCursorScreenPoint());
625
+ } catch (error) {
626
+ console.warn('Failed to get cursor screen point, falling back to primary display.', error);
627
+ return screen.getPrimaryDisplay();
628
+ }
629
+ }
630
+
631
+ /**
632
+ * Detects if the current session is running natively under Wayland
633
+ * (i.e., not using X11 fallback/XWayland).
634
+ */
635
+ protected isWaylandSession(): boolean {
636
+ if (process.platform !== 'linux') {
637
+ return false;
638
+ }
639
+
640
+ // Primary check: WAYLAND_DISPLAY is set when a Wayland compositor is running
641
+ const hasWaylandDisplay = !!process.env.WAYLAND_DISPLAY;
642
+
643
+ // Secondary check: XDG_SESSION_TYPE explicitly set to 'wayland'
644
+ const isWaylandSession = process.env.XDG_SESSION_TYPE === 'wayland';
645
+
646
+ // Check whether X11 fallback is in use
647
+ const usingX11Fallback =
648
+ process.env.GDK_BACKEND?.includes('x11') ||
649
+ process.env.ELECTRON_OZONE_PLATFORM_HINT === 'x11' ||
650
+ process.argv.includes('--ozone-platform=x11');
651
+
652
+ return (hasWaylandDisplay || isWaylandSession) && !usingX11Fallback;
653
+ }
654
+
610
655
  /**
611
656
  * Save the window geometry state on every change.
612
657
  */
@@ -675,10 +720,12 @@ export class ElectronMainApplication {
675
720
  process.env.THEIA_ELECTRON_VERSION = process.versions.electron;
676
721
  if (noBackendFork) {
677
722
  process.env[ElectronSecurityToken] = JSON.stringify(this.electronSecurityToken);
678
- // The backend server main file is supposed to export a promise resolving with the port used by the http(s) server.
723
+ // The backend server main file is supposed put a promise resolving with the port used by the http(s) server into the global object.
679
724
  dynamicRequire(this.globals.THEIA_BACKEND_MAIN_PATH);
680
- // @ts-expect-error
681
- const address: AddressInfo = await globalThis.serverAddress;
725
+ const address = await backendGlobal.serverAddress;
726
+ if (!address) {
727
+ throw new Error('The backend server did not start correctly.');
728
+ }
682
729
  return address.port;
683
730
  } else {
684
731
  const backendProcess = fork(
@@ -18,6 +18,7 @@ import { injectable, inject } from 'inversify';
18
18
  import { ApplicationServer, ExtensionInfo, ApplicationInfo } from '../common/application-protocol';
19
19
  import { ApplicationPackage } from '@theia/application-package';
20
20
  import { OS } from '../common/os';
21
+ import { backendGlobal } from './backend-global';
21
22
 
22
23
  @injectable()
23
24
  export class ApplicationServerImpl implements ApplicationServer {
@@ -26,9 +27,7 @@ export class ApplicationServerImpl implements ApplicationServer {
26
27
  protected readonly applicationPackage: ApplicationPackage;
27
28
 
28
29
  getExtensionsInfos(): Promise<ExtensionInfo[]> {
29
- // @ts-expect-error
30
- const appInfo: ExtensionInfo[] = globalThis.extensionInfo;
31
- return Promise.resolve(appInfo);
30
+ return Promise.resolve(backendGlobal.extensionInfo);
32
31
  }
33
32
 
34
33
  getApplicationInfo(): Promise<ApplicationInfo | undefined> {
@@ -0,0 +1,41 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 TypeFox and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import type { AddressInfo } from 'net';
18
+ import type { ExtensionInfo } from '../common/application-protocol';
19
+ import { isPromise } from 'util/types';
20
+
21
+ export interface BackendGlobal {
22
+ serverAddress?: Promise<AddressInfo>;
23
+ extensionInfo: ExtensionInfo[];
24
+ }
25
+
26
+ /**
27
+ * The global object for the backend application.
28
+ * Used to store application-wide information.
29
+ *
30
+ * See {@link BackendGlobal} for more details.
31
+ */
32
+ export const backendGlobal: BackendGlobal = globalThis as unknown as BackendGlobal;
33
+
34
+ if (backendGlobal.serverAddress !== undefined && !isPromise(backendGlobal.serverAddress)) {
35
+ console.error('globalThis.serverAddress should be a `Promise<AddressInfo>` if defined.');
36
+ }
37
+
38
+ if (!Array.isArray(backendGlobal.extensionInfo)) {
39
+ // Initialize to an empty array if not already set
40
+ backendGlobal.extensionInfo = [];
41
+ }
package/src/node/index.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  export * from './backend-application';
18
+ export * from './backend-global';
18
19
  export * from './debug';
19
20
  export * from '../common/file-uri';
20
21
  export * from './messaging';