Maksymalizacja okna oraz tryb wideo — same problemy

Maksymalizacja okna oraz tryb wideo — same problemy
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:9 minut
  • Lokalizacja:Tuchów
  • Postów:12171
1

Odkryłem pewien fenomen już jakiś czas temu, ale do dziś nie ogarniam dlaczego on występuje. Podczas pisania Fairtrisa zauważyłem, że włączenie ekskluzywnego tryb wideo wtedy gdy okno jest zmaksymalizowane, powoduje, że rozmiar okna w trybie okienkowym zostaje zmodyfikowany i po wyjściu z trybu wideo, okno przybiera niepoprawne rozmiary. Czasem jest tak, że wyłączenie trybu wideo ustawia okno z powtorem jako zmaksymalizowane (czyli poprawnie), ale okno jest mniejsze od pulpitu lub jego belka znajduje się pod paskiem zadań (mam pasek u góry). Natomiast jeśli użyję przycisku restore (czyli wyłączę maksymalizację), okno zostaje przywrócone, ale nadal ma rozmiar zgodny z rozmiarem okna zmaksymalizowanego. To się dzieje gdy używam SDL-a, w dowolnej wersji.

Dodam też, że dokładnie to samo zaobserwowałem w przypadku gry Nuclear Throne, która jest zrobiona w GameMaker Studio. Wygląda to tak — odpalam grę, ta startuje w małym oknie:

screenshot-20220515205552.png

Teraz maksymalizuję okno, używając przycisku na jego belce:

screenshot-20220515205628.png

Teraz wchodzę w ekskluzywny tryb wideo za pomocą Alt+Enter:

screenshot-20220515205701.png

Następnie wyłączm tryb wideo tym samym skrótem, przywracając okno zmaksymalizowane. No i efekt jest taki:

screenshot-20220515205745.png

Pozycja okna jest zła — belka częściowo chowa się pod paskiem zadań, a okno nie jest zmaksymalizowane, bo widać przycisk do maksymalizacji, nie do przywracania. Czyli okno nie jest zmaksymalizowane (jest zwyczajny tryb okienkowy), z nadpisanymi poprzednimi rozmiarami — okno powinno być malutkie, takie jak na pierwszym zrzucie.

Dokładnie to samo mi się dzieje w dowolnej mojej aplikacji pisanej z użyciem SDL2, jeśli włączę tryb wideo gdy okno jest zmaksymalizowane.


Czy ktoś wie o co w tym chodzi? Dlaczego tryb wideo psuje zapamiętany rozmiar małego okna? Czy to systemowy menedżer okien (czy po prostu system) nie ogarnia tego czy backend pokroju Direct3D/OpenGL nie potrafi poprawnie obsłużyć takiej sytuacji?

Na razie w ramach zabezpieczenia, za pomocą WinAPI zablokowałem przycisk maksymalizacji oraz napisałem sobie kod, który zapamiętuje rozmiar okna w trybie okienkowym, tak aby można było go przywrócić w dowolnej chwili. Ale wolałbym, aby maksymalizacja była jednak wspierana.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
katakrowa
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 2 lata
  • Lokalizacja:Chorzów
  • Postów:1670
0

Trochę nie rozumiem problemu.
Czy po alt+enter nie dostajesz któregoś z komunikatów WM_MAX* WM_MIN*?


Projektowanie i programowanie. Hobbystycznie elektronika i audio oszołom.
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:9 minut
  • Lokalizacja:Tuchów
  • Postów:12171
0

Sam nie muszę w ogóle operować na zdarzeniach (a tym bardziej na komunikatach) — wystarczy że stworzę okno SdL_WINDOW_RESIZEABLE i dodam sobie linijkę, która mi włączy lub wyłączy tryb wideo, czyli odpali funkcję SDL_SetWindowFullscreen z flagą SDL_WINDOW_FULLSCREEN. Tym jak się okno ma zachowywać w takich przypadkach steruje system oraz menedżer okien SDL-a — ja się niczym przejmować nie muszę.

Tzn. muszę, bo coś daje ciała i gubi poprzednie wymiary okna (gdy to było wyświetlone w formie niezmaksymalizowanej, jako zwykłe, małe okienko). I najwyraźniej nie jest to problem SDL-a, bo inne gry też tak mają, choć są stworzone w innych technologiach.

FCEUX np. też ma problemy z taką sekwencją jaką opisałem w pierwszym poście, ale zachowuje sie nieco inaczej — po wyłączeniu trybu wideo, okno zostaje poprawnie ustawione jako zmaksymalizowane, ale jego restore ustawia je jako małe w pozycji 0,0, a nie w poprzedniej, czyli np. mniej więcej na środku ekranu. Czyli rozmiar okna zostaje przywrócony, ale pozycja nie.

I teraz nie wiem czy to sam system nie ogarnia okien, czy SDL, czy coś jeszcze innego — i to chciałbym się dowiedzieć. W przeciwnym razie będę musiał zablokować możliwość maksymalizacji okna, jednocześnie dając możliwość jego rozciągania.

BTW: ja sobie swój kod załatałem i dodalem zapamiętywanie rozmiaru okna gdy było małe oraz wywaliłem opcję maksymalizacji (oczywićie gołym WinAPI, bo SDL tego nie umie), więc nie dość że ten problem nie istnieje, to przy okazji mam zawsze dostęp do tych wymiarów i mogę je sobie zapisać do konfiga (nawet jeśli grę zamknę gdy jest aktywny inny tryb niż okienkowy). No ale to trochę do bani, bo nie rozwiązałem problemu.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 6x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:9 minut
  • Lokalizacja:Tuchów
  • Postów:12171
3

Dobra, panowie — właśnie rozwiązałem problem błędów w obsłudze maksymalizacji okna. Kosztowało mnie to sporo gimnastyki, ale efekt końcowy jest taki, że maksymalizacja/tryb wideo ani nie rozwala mi już układu okna, ani też nie powoduje przybierania przez niego nieprawidłowych wymiarów.

Teraz mogę spokojnie włączać ekskluzywny tryb wideo gdy okno jest zmaksymalizowane, a potem wyłączyć tryb wideo i okno zostaje z powrotem ustawione jako zmaksymalizowane, równo do obszaru ekranu (z uwzględnieniem obszaru zajmowanego przez pasek zadań). Natomiast wyłączenie maksymalizacji (czy to własnym kodem czy przyciskiem na belce okna) pozwala przywrócić prawidłowe wymiary i położenie okna — bez takich cudów jak pokazałem w poprzednim poście.

Podsumowując, moja gra jednak będzie pozwalała na wsparcie maksymalizacji, dzięki czemu nie muszę już blokować przycisku na belce funkcjami WinAPI. Mam obecnie dodane cztery style:

  • okienkowy — małe okienko, mniejsze niż ekran,
  • maksymalizacja — okno zmaksymalizowane na cały ekran, z uwzględnieniem paska zadań,
  • fullscreen — okno bez obramowania, rozciągnięte na cały ekran (przykrywając pasek zadań),
  • wideo — ekskluzywny tryb wideo ze zmianą rozdzielczości (lub bez).

Program testowy na razie nie wykazuje problemów — mogę dowolnie przełączać styl okna (pomiędzy powyższymi) i działa to bezbłędnie. Nie dość że prawidłowe rozmiary stylu okienkowego nigdy się nie gubią, to w dodatku zmiana stylu działa prawidłowo dla dowolnego ekranu (głównego oraz dodatkowego). Tak więc mój problem został rozwiązany, co mnie cholernie cieszy — opór się opłacił. :]


Niestety nadal nie wiem dlaczego włączenie trybu wideo gdy okno jest zmaksymalizowane powoduje nadpisanie rozmiarów okna i ustawienie wymiarów zgodnych z wymiarami okna zmaksymalizowanego. Przez to po wyłączeniu trybu wideo, okno już nie pamięta jakie miało wymiary i przycisk restore na belce nie zmienia wymiarów i położenia okna.

Sam niestety nie mam żadnych sensownych gier, ale jeśli macie jakieś u siebie to możecie sami wykonać test:

  1. Włączcie grę,
  2. Wyłączcie tryb wideo/fullscreen, tak aby okno było małe (dużo mniejsze od powierzchni ekranu),
  3. Zmaksymalizujcie okno przyciskiem na belce,
  4. Włączcie ekskluzywny tryb wideo (koniecznie ekskluzywny),
  5. Wyłączcie ekskluzywny tryb wideo — okno powinno zostać ustawione jako zmaksymalizowane,
  6. Wyłączcie maksymalizację przyciskiem na belce — powinno przyjąć rozmiary takie jak w pukcie 2.

Jeśli coś pójdzie nie tak i któryś punkt nie został spełniony, to znaczy, że testowana gra również ma problemy z maksymalizacją. A to by oznaczało, że problem leży gdzieś głebiej, być może w samym systemie. No bo ekskluzywny tryb wideo jest ustawiany przez system (są do tego odpowiednie funkcje w Windows API), a nie samodzielnie przez jakieś biblioteki, bez wiedzy i kontroli systemu.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 9x, ostatnio: flowCRANE

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.