Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

English (US) release notes, mirroring CHANGELOG.md (Brazilian Portuguese). Before publishing a version, add a `## [VERSION]` section to **both** files: the workflow publishes the section matching the tag from each one and fails if either is missing.

## [Unreleased]
## [1.6.0-alpha.3]
### What's new
- Session menu: a pinned panel at the top of the side column with the **File explorer (ControlFS)**, the team's open-source, controller-first file manager. One press opens ControlFS on top, always full screen on the session screen (or brings it to the front if already open); if it isn't installed, its download page opens. Console Mode only calls it through its own `--start` flag, never closes it, and never sends F11 to another window if Windows denies focus. (#122)
- Session menu (the controller shortcut, Select + Y in the suggestion) redesigned like Steam's overlay (Shift + Tab): it covers the whole screen, the game dims and blurs behind it, a side panel gathers the options (volume with a gauge, resolution, audio, FPS, HDR) and the **open windows** are always visible in the middle, an in-menu Alt + Tab: the D-pad picks, A brings the window to the front, X closes it and B goes back to the game (switching windows does not end the session). The frosted glass only shows when Windows' transparency effects are on (otherwise the panel is dark and solid, and it changes live if you flip the setting), and in high contrast it uses the system colours. It has a focus that grows, sounds and animations (the panel slides in, the rows follow one after another and closing fades it out). In this alpha it also opens **outside a session**, as a preview with a badge on top, so it can be tried without turning on console mode (in it the FPS limit is hidden and "Back to the PC" becomes "Close menu"). (#120)
- Redesigned Console interface, made to feel like a console: a top bar with three tabs (Home, Session and System) you switch with LB/RB (L1/R1 on PlayStation) with a slide animation, screen tiles that show what will happen to each monitor, quick settings with icons and a focus that grows as you move over it. Home brings the Play now banner and a summary of the current setup (game screen, audio, launcher and HDR/VRR), each opening its choices. (#117)
- Console background: by default, a collage of the covers of your installed Steam games under a dark gradient (the app only reads images Steam already downloaded; nothing is bundled). You can switch to just the gradient or to a picture of your own, in System → Background. (#117)
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

Notas em português do Brasil; a versão em inglês (Estados Unidos) fica em `CHANGELOG.en-US.md`. Antes de publicar uma versão, adicione uma seção `## [VERSÃO]` com o changelog daquela versão **nos dois arquivos**. O workflow publica as duas seções correspondentes à tag na mesma release e falha se faltar alguma.

## [Unreleased]
## [1.6.0-alpha.3]
### Novidades
- Menu da sessão: painel fixo no topo da lateral com o **Explorador de arquivos (ControlFS)**, o gerenciador de arquivos de código aberto da equipe, feito para o controle. Um toque abre o ControlFS por cima, sempre em tela cheia na tela da sessão (ou o traz para a frente se já estiver aberto); se não estiver instalado, abre a página de download. O Console Mode só o chama pelo `--start` dele, não o encerra nem envia F11 a outra janela se o Windows negar o foco. (#122)
- Menu da sessão (o atalho do controle, Select + Y na sugestão) redesenhado como o overlay do Steam (Shift+Tab): cobre a tela inteira, o jogo escurece e desfoca por trás, um painel lateral reúne as opções (volume com medidor, resolução, áudio, FPS, HDR) e no meio ficam sempre visíveis as **janelas abertas**, um ALT+TAB interno: o direcional escolhe, A traz a janela para a frente, X a fecha e B volta ao jogo (trocar de janela não encerra a sessão). O vidro fosco só aparece se os efeitos de transparência do Windows estiverem ligados (senão o painel fica escuro e sólido, e muda ao vivo se você trocar a configuração), e em alto contraste usa as cores do sistema. Tem foco que cresce, sons e animações (o painel entra deslizando, as linhas vêm em cascata e ao fechar ele some suavemente). Nesta alpha ele abre também **fora da sessão**, como prévia com um selo no topo, para testar sem ligar o modo console (nela o limite de FPS não aparece e "Voltar ao PC" vira "Fechar menu"). (#120)
- Interface Console redesenhada, com cara de console: barra no topo com três abas (Início, Sessão e Sistema) que você troca com LB/RB (L1/R1 no PlayStation) com uma animação de deslize, blocos das telas que mostram o que vai acontecer com cada monitor, ajustes rápidos com ícones e foco que cresce ao passar. Início traz o banner com Jogar agora e um resumo do setup atual (tela de jogo, áudio, iniciador e HDR/VRR), que abre cada escolha. (#117)
- Plano de fundo do modo Console: por padrão, uma colagem com as capas dos seus jogos instalados na Steam sob um gradiente escuro (o app só lê as imagens que a Steam já baixou; nada é embutido). Dá para trocar por só o gradiente ou por uma imagem sua, em Sistema → Plano de fundo. (#117)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Get **[1.5.1](https://github.com/lippdev/consolemode/releases/tag/v1.5.1)**, the
- **`ConsoleMode-Setup-x64.exe`** (recommended): per-user install, no admin, updates itself.
- **`ConsoleMode-Portable-x64.exe`**: a single exe that keeps its data next to it.

Want to help test what comes next? **[1.6.0-alpha.2](https://github.com/lippdev/consolemode/releases/tag/v1.6.0-alpha.2)** is an early alpha of 1.6 that no longer bundles any third-party tool for displays and audio. It is not verified on many setups yet: keep 1.5.1 if you need it to just work, or turn on Settings → "Receive test versions" in 1.5.1 to get it from the app.
Want to help test what comes next? **[1.6.0-alpha.3](https://github.com/lippdev/consolemode/releases/tag/v1.6.0-alpha.3)** is an early alpha of 1.6 that no longer bundles any third-party tool for displays and audio. It is not verified on many setups yet: keep 1.5.1 if you need it to just work, or turn on Settings → "Receive test versions" in 1.5.1 to get it from the app.

On 1.4.0? The app offers the update. If it fails with a timeout, download the installer once; your settings are kept.

Expand Down
2 changes: 1 addition & 1 deletion README.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Baixe a **[1.5.1](https://github.com/lippdev/consolemode/releases/tag/v1.5.1)**,
- **`ConsoleMode-Setup-x64.exe`** (recomendado): instala por usuário, sem admin, e se atualiza sozinho.
- **`ConsoleMode-Portable-x64.exe`**: um único exe que guarda os dados ao lado dele.

Quer ajudar a testar o que vem aí? A **[1.6.0-alpha.2](https://github.com/lippdev/consolemode/releases/tag/v1.6.0-alpha.2)** é uma alpha da 1.6 que não embute mais nenhuma ferramenta de terceiros para telas e áudio. Ela ainda não foi validada em muitos setups: fique na 1.5.1 se precisa que funcione sem surpresas, ou ligue Ajustes → "Receber versões de teste" na 1.5.1 para recebê-la pelo app.
Quer ajudar a testar o que vem aí? A **[1.6.0-alpha.3](https://github.com/lippdev/consolemode/releases/tag/v1.6.0-alpha.3)** é uma alpha da 1.6 que não embute mais nenhuma ferramenta de terceiros para telas e áudio. Ela ainda não foi validada em muitos setups: fique na 1.5.1 se precisa que funcione sem surpresas, ou ligue Ajustes → "Receber versões de teste" na 1.5.1 para recebê-la pelo app.

Está na 1.4.0? O app oferece a atualização. Se ela falhar por tempo esgotado, baixe o instalador uma vez; as configurações são mantidas.

Expand Down
16 changes: 16 additions & 0 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ Pré-condições: sessão ativa com Big Picture (ou jogo borderless) na tela; co
- [ ] Jogo em **tela cheia exclusiva**: o menu não aparece por cima (limitação documentada); Select + Y não quebra nada. Resultado: ______
- [ ] `start consolemode://menu` no cmd abre o menu; fora da sessão, não faz nada. Resultado: ______

## 1d. Explorador de arquivos (ControlFS) no menu da sessão

Pré-condição: ControlFS instalado (https://github.com/nextestudios/ControlFS).

- [ ] Select + Y: no topo da lateral esquerda, fora da lista que rola, há o painel "Explorador de arquivos (ControlFS)"; o restante das opções rola por baixo dele. Resultado: ______
- [ ] Direcional para cima a partir de "Voltar ao jogo" chega nele; A abre o ControlFS em tela cheia na TV, por cima do jogo/Big Picture, e o menu fecha. Resultado: ______
- [ ] O ControlFS abre **sempre em tela cheia** na tela da sessão (a TV), cobrindo-a por inteiro, mesmo que ele estivesse em janela ou maximizado; se já estava em tela cheia, nada muda. Resultado: ______
- [ ] Se outra aplicação permanecer em primeiro plano porque o Windows negou o foco ao ControlFS, o F11 não é enviado a ela; a janela de outra aplicação não muda de estado. Resultado: ______
- [ ] Abrir de novo com o ControlFS já aberto só o traz para a frente (continua um processo só no Gerenciador de Tarefas). Resultado: ______
- [ ] O ControlFS responde ao controle logo de cara (o foco do controle fica com ele, sem o Console Mode reagir aos botões). Resultado: ______
- [ ] Com o ControlFS já aberto: A só o traz para a frente (não abre uma segunda instância). Resultado: ______
- [ ] A sessão **não** termina nem restaura a mesa enquanto o ControlFS está na frente; ao sair dele (Menu do ControlFS → Sair) volta-se ao jogo. Resultado: ______
- [ ] Select + Y com o ControlFS na frente abre o menu por cima dele (saída de emergência). Resultado: ______
- [ ] Sem o ControlFS instalado: a linha diz "Não instalado · aperte para baixar" e A abre a página de releases no navegador. Resultado: ______
- [ ] Fora da sessão (prévia do menu) o painel funciona igual. Resultado: ______

## 2. Links `consolemode://`

- [ ] `start consolemode://start` no `cmd` com o app **fechado**: abre e entra no modo console. Resultado: ______
Expand Down
4 changes: 2 additions & 2 deletions src/ConsoleMode/ConsoleMode.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<Version>1.6.0-alpha.2</Version>
<Version>1.6.0-alpha.3</Version>
<AssemblyVersion>1.6.0.0</AssemblyVersion>
<FileVersion>1.6.0.0</FileVersion>
<InformationalVersion>1.6.0-alpha.2</InformationalVersion>
<InformationalVersion>1.6.0-alpha.3</InformationalVersion>
<AssemblyTitle>Console Mode</AssemblyTitle>
<Product>Console Mode</Product>
<Authors>lippdev</Authors>
Expand Down
15 changes: 15 additions & 0 deletions src/ConsoleMode/Native/NativeWindows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,21 @@ public static WindowMatch[] GetAllVisibleWindows()
return [.. list];
}

/// <summary>A plain F11 to the window in front (ControlFS uses it for full screen).</summary>
public static void SendF11()
{
keybd_event(VK_F11, 0, 0, UIntPtr.Zero);
keybd_event(VK_F11, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
}

public static bool TryGetWindowRect(nint hWnd, out int left, out int top, out int width, out int height)
{
left = top = width = height = 0;
if (hWnd == 0 || !GetWindowRect(hWnd, out var r)) return false;
left = r.Left; top = r.Top; width = r.Right - r.Left; height = r.Bottom - r.Top;
return true;
}

public static void SendWinF11()
{
keybd_event(VK_LWIN, 0, 0, UIntPtr.Zero);
Expand Down
4 changes: 4 additions & 0 deletions src/ConsoleMode/Resources/Strings.en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@
"ConsoleSettingsHint": "Press A on a row to change its value. Everything is saved right away.",
"BackToPc": "Back to the PC",
"CloseMenu": "Close menu",
"ControlFsCard": "File explorer (ControlFS)",
"ControlFsOpen": "Browse your files with the controller",
"ControlFsMissing": "Not installed · press to get it",
"ControlFsMissingNote": "ControlFS is not installed. Opening its download page in the browser.",
"SessionWindowsCard": "Windows",
"SessionWindowsCount": "{0} open",
"SwitcherEmpty": "No open windows",
Expand Down
4 changes: 4 additions & 0 deletions src/ConsoleMode/Resources/Strings.es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@
"ConsoleSettingsHint": "Pulsa A en una fila para cambiar su valor. Todo se guarda al momento.",
"BackToPc": "Volver al PC",
"CloseMenu": "Cerrar menú",
"ControlFsCard": "Explorador de archivos (ControlFS)",
"ControlFsOpen": "Explora tus archivos con el mando",
"ControlFsMissing": "No instalado · pulsa para descargarlo",
"ControlFsMissingNote": "ControlFS no está instalado. Abriendo su página de descarga en el navegador.",
"SessionWindowsCard": "Ventanas",
"SessionWindowsCount": "{0} abiertas",
"SwitcherEmpty": "No hay ventanas abiertas",
Expand Down
4 changes: 4 additions & 0 deletions src/ConsoleMode/Resources/Strings.pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@
"ConsoleSettingsHint": "Aperte A numa linha para trocar o valor. Tudo é salvo na hora.",
"BackToPc": "Voltar ao PC",
"CloseMenu": "Fechar menu",
"ControlFsCard": "Explorador de arquivos (ControlFS)",
"ControlFsOpen": "Navegue pelos seus arquivos com o controle",
"ControlFsMissing": "Não instalado · aperte para baixar",
"ControlFsMissingNote": "O ControlFS não está instalado. Abrindo a página de download no navegador.",
"SessionWindowsCard": "Janelas",
"SessionWindowsCount": "{0} abertas",
"SwitcherEmpty": "Nenhuma janela aberta",
Expand Down
47 changes: 47 additions & 0 deletions src/ConsoleMode/Services/ControlFsLocator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace ConsoleMode.Services;

/// <summary>
/// Where ControlFS (the controller-first file explorer from the same team) is installed. Pure: the registry and
/// the disk are passed in, so the order of preference is testable.
/// </summary>
public static class ControlFsLocator
{
public const string ExeName = "ControlFS.exe";
public const string ReleasesUrl = "https://github.com/nextestudios/ControlFS/releases/latest";

/// <summary>Folders to look in, most reliable first, without blanks or repeats.</summary>
public static IReadOnlyList<string> Folders(string? registryInstallLocation, string? localAppData, string? programFiles)
{
var folders = new List<string>();
void Add(string? path)
{
if (string.IsNullOrWhiteSpace(path)) return;
var clean = path.Trim().Trim('"').TrimEnd('\\', '/');
if (clean.Length > 0 && !folders.Contains(clean, StringComparer.OrdinalIgnoreCase)) folders.Add(clean);
}
Add(registryInstallLocation);
if (!string.IsNullOrWhiteSpace(localAppData)) Add(Path.Combine(localAppData, "Programs", "ControlFS"));
if (!string.IsNullOrWhiteSpace(programFiles)) Add(Path.Combine(programFiles, "ControlFS"));
return folders;
}

/// <summary>
/// Full screen means the window is exactly the screen. A maximized window is about 16 px bigger (its frame hangs
/// over the edges), so it is not counted; a pixel of tolerance covers rounding.
/// </summary>
public static bool IsFullScreen(int left, int top, int width, int height, int screenX, int screenY, int screenWidth, int screenHeight) =>
screenWidth > 0 && screenHeight > 0
&& Math.Abs(left - screenX) <= 1 && Math.Abs(top - screenY) <= 1
&& Math.Abs(width - screenWidth) <= 1 && Math.Abs(height - screenHeight) <= 1;

/// <summary>The first folder that really has ControlFS.exe, or null (not installed).</summary>
public static string? Resolve(IEnumerable<string> folders, Func<string, bool> fileExists)
{
foreach (var folder in folders)
{
var exe = Path.Combine(folder, ExeName);
if (fileExists(exe)) return exe;
}
return null;
}
}
Loading
Loading