The game window remembers where you put it too
RP412MFDLAYOUT already kept the exploded view's display panes where they
were dragged. The main window is the one people move most, and it was
still being placed fresh every launch, so it joins them.
MFDSplitView_LoadLayout/SaveLayout become RPWindowLayout_Load/Save, with
Register/Forget taking any HWND rather than the module reaching into a
pane registry. Same file, same format, one more line in it.
What comes back depends on the window, so Register takes it as a flag:
display panes position only, as before. A pane's size follows its
content and its button banks, so an old size from a
different build must not distort it.
the game window position and size in the cockpit view. Nothing
derives that size - the cockpit fits itself to
whatever client area it is given - so a window sized
to suit a monitor should come back that way, and
half-restoring it would be the strange behaviour. In
the exploded view its size IS the render resolution
-res asked for, so there only the position returns.
Registered after the CockpitShellProc subclass is installed, on purpose:
the restore's WM_SIZE then runs LayoutCockpit again and the canvas
re-fits the restored client area. -fit does not register at all - it
owns the whole monitor, so there is no placement of the player's to
keep.
CockpitShellProc gained the WM_EXITSIZEMOVE hook the panes already had,
so dragging or resizing the shell writes the file immediately rather
than waiting for teardown.
Two hazards the panes were small enough to get away with and the game
window is not:
- Save reads rcNormalPosition rather than GetWindowRect. A minimised
window reports a nonsense rect and a maximised one reports the
screen; since the file is rewritten whole, either would have
replaced a good line with a useless one. rcNormalPosition is the
restored placement whatever state the window is in.
- Load drops any placement that intersects none of the monitors
currently plugged in. Restoring the game window onto a display that
is no longer there would leave nothing to drag back.
Verified by round trip in both views. Cockpit: dragged and resized to
240,120 1000x620, the file took it, a fresh launch in load mode came up
exactly there with a 984x581 client - and a screenshot confirms the
canvas re-fit it, displays at the corners and the map centred at the
bottom, nothing spilling. Exploded: the shell came back at 60,60 still
1280x720 from -res while Map came back at 777,333, which is the
size-flag split doing its job.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -40,8 +40,9 @@ ipch/
|
||||
*.log
|
||||
rpl4.log
|
||||
|
||||
# Where the exploded view's panes were last dragged to (RP412MFDLAYOUT).
|
||||
# Per-machine by nature - it is screen coordinates on somebody's desk.
|
||||
# Where the game window and the exploded view's panes were last dragged
|
||||
# to (RP412MFDLAYOUT). Per-machine by nature - it is screen coordinates
|
||||
# on somebody's desk.
|
||||
mfd_layout.cfg
|
||||
|
||||
# Build-output static libs that land in lib/ (the two committed dependency
|
||||
|
||||
+146
-51
@@ -18,10 +18,16 @@ namespace
|
||||
|
||||
const char layoutFileName[] = "mfd_layout.cfg";
|
||||
|
||||
// the panes that own a desktop window, so Save can walk them
|
||||
enum { maxLayoutPanes = 8 };
|
||||
MFDSplitView *layoutPanes[maxLayoutPanes];
|
||||
int layoutPaneCount = 0;
|
||||
// every window taking part, so Save can walk them
|
||||
enum { maxLayoutWindows = 12 };
|
||||
struct LayoutWindow
|
||||
{
|
||||
void *window;
|
||||
const char *title;
|
||||
Logical withSize;
|
||||
};
|
||||
LayoutWindow layoutWindows[maxLayoutWindows];
|
||||
int layoutWindowCount = 0;
|
||||
|
||||
int LayoutMode()
|
||||
{
|
||||
@@ -160,7 +166,7 @@ namespace
|
||||
// than trusting teardown, so a hard kill still leaves the
|
||||
// layout that was on screen. No-op unless the mode is save.
|
||||
//
|
||||
MFDSplitView_SaveLayout();
|
||||
RPWindowLayout_Save();
|
||||
return 0;
|
||||
|
||||
case WM_CLOSE:
|
||||
@@ -289,10 +295,11 @@ MFDSplitView::MFDSplitView(
|
||||
ShowWindow((HWND) window, SW_SHOWNOACTIVATE);
|
||||
|
||||
// only the exploded view's own windows can be dragged, so only
|
||||
// those have a position worth remembering
|
||||
if (ownWindow && layoutPaneCount < maxLayoutPanes)
|
||||
// those have a placement worth remembering. Position only - see
|
||||
// RPWindowLayout_Register.
|
||||
if (ownWindow)
|
||||
{
|
||||
layoutPanes[layoutPaneCount++] = this;
|
||||
RPWindowLayout_Register(window, paneTitle, False);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -306,15 +313,7 @@ MFDSplitView::~MFDSplitView()
|
||||
Check_Pointer(this);
|
||||
|
||||
// out of the layout registry before the window goes
|
||||
for (int i = 0; i < layoutPaneCount; ++i)
|
||||
{
|
||||
if (layoutPanes[i] == this)
|
||||
{
|
||||
layoutPanes[i] = layoutPanes[--layoutPaneCount];
|
||||
layoutPanes[layoutPaneCount] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RPWindowLayout_Forget(window);
|
||||
|
||||
if (window != NULL)
|
||||
{
|
||||
@@ -335,18 +334,61 @@ Logical
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Sticky placement: restore saved positions over the computed ones.
|
||||
//
|
||||
// Called after the exploded view has built and placed every pane, so a
|
||||
// pane the file does not mention simply keeps where the layout put it.
|
||||
// Position only - the saved size is read and discarded, because a pane's
|
||||
// size comes from its content and its button banks, and letting an old
|
||||
// w,h back in would misshape it after any geometry change.
|
||||
// Join the saved layout. Registering twice just refreshes the entry, so
|
||||
// a window re-registering after being rebuilt is harmless.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
void
|
||||
MFDSplitView_LoadLayout()
|
||||
RPWindowLayout_Register(void *window, const char *title, Logical with_size)
|
||||
{
|
||||
if (LayoutMode() == LayoutOff || layoutPaneCount == 0)
|
||||
if (window == NULL || title == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < layoutWindowCount; ++i)
|
||||
{
|
||||
if (layoutWindows[i].window == window)
|
||||
{
|
||||
layoutWindows[i].title = title;
|
||||
layoutWindows[i].withSize = with_size;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (layoutWindowCount >= maxLayoutWindows)
|
||||
{
|
||||
return;
|
||||
}
|
||||
layoutWindows[layoutWindowCount].window = window;
|
||||
layoutWindows[layoutWindowCount].title = title;
|
||||
layoutWindows[layoutWindowCount].withSize = with_size;
|
||||
++layoutWindowCount;
|
||||
}
|
||||
|
||||
void
|
||||
RPWindowLayout_Forget(void *window)
|
||||
{
|
||||
for (int i = 0; i < layoutWindowCount; ++i)
|
||||
{
|
||||
if (layoutWindows[i].window == window)
|
||||
{
|
||||
layoutWindows[i] = layoutWindows[--layoutWindowCount];
|
||||
layoutWindows[layoutWindowCount].window = NULL;
|
||||
layoutWindows[layoutWindowCount].title = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Sticky placement: restore the saved placement over the computed one.
|
||||
//
|
||||
// Called once everything has been built and placed, so a window the file
|
||||
// does not mention simply keeps where it was put. Size comes back only
|
||||
// for windows registered with it - see the header.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
void
|
||||
RPWindowLayout_Load()
|
||||
{
|
||||
if (LayoutMode() == LayoutOff || layoutWindowCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -393,33 +435,75 @@ void
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < layoutPaneCount; ++i)
|
||||
for (int i = 0; i < layoutWindowCount; ++i)
|
||||
{
|
||||
MFDSplitView *pane = layoutPanes[i];
|
||||
if (pane != NULL && pane->Title() != NULL &&
|
||||
!strcmp(pane->Title(), cursor))
|
||||
LayoutWindow &entry = layoutWindows[i];
|
||||
if (entry.title == NULL || strcmp(entry.title, cursor) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
HWND target = (HWND) entry.window;
|
||||
if (target == NULL || !IsWindow(target))
|
||||
{
|
||||
pane->SetPosition(x, y);
|
||||
++restored;
|
||||
break;
|
||||
}
|
||||
|
||||
// a saved size of nothing is a corrupt line, not an instruction
|
||||
Logical size_it = (entry.withSize && w > 0 && h > 0) ? True : False;
|
||||
|
||||
//
|
||||
// Saved coordinates belong to whatever monitors were plugged
|
||||
// in that day. If the placement lands on none of today's, drop
|
||||
// it and keep the computed one - restoring the game window
|
||||
// somewhere invisible would leave nothing to drag back.
|
||||
//
|
||||
RECT landing;
|
||||
landing.left = x;
|
||||
landing.top = y;
|
||||
if (size_it)
|
||||
{
|
||||
landing.right = x + w;
|
||||
landing.bottom = y + h;
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT current;
|
||||
if (!GetWindowRect(target, ¤t))
|
||||
{
|
||||
break;
|
||||
}
|
||||
landing.right = x + (current.right - current.left);
|
||||
landing.bottom = y + (current.bottom - current.top);
|
||||
}
|
||||
if (MonitorFromRect(&landing, MONITOR_DEFAULTTONULL) == NULL)
|
||||
{
|
||||
DEBUG_STREAM << "MFDLayout: " << cursor << " was saved at "
|
||||
<< x << "," << y << " - off every monitor now, ignoring\n"
|
||||
<< std::flush;
|
||||
break;
|
||||
}
|
||||
|
||||
SetWindowPos(target, NULL, x, y, w, h,
|
||||
SWP_NOZORDER | SWP_NOACTIVATE | (size_it ? 0 : SWP_NOSIZE));
|
||||
++restored;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
DEBUG_STREAM << "MFDLayout: restored " << restored << " pane position(s) from "
|
||||
DEBUG_STREAM << "MFDLayout: restored " << restored << " window placement(s) from "
|
||||
<< layoutFileName << "\n" << std::flush;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Write where every open pane currently is. The whole file each time - it
|
||||
// is a handful of lines, and a rewrite leaves nothing half-written for a
|
||||
// hard kill to catch.
|
||||
// Write where every registered window currently is. The whole file each
|
||||
// time - it is a handful of lines, and a rewrite leaves nothing
|
||||
// half-written for a hard kill to catch.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
void
|
||||
MFDSplitView_SaveLayout()
|
||||
RPWindowLayout_Save()
|
||||
{
|
||||
if (LayoutMode() != LayoutSave || layoutPaneCount == 0)
|
||||
if (LayoutMode() != LayoutSave || layoutWindowCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -432,30 +516,41 @@ void
|
||||
return;
|
||||
}
|
||||
|
||||
fputs("# RP412 exploded-view pane placement. RP412MFDLAYOUT=save writes\n"
|
||||
"# this on each finished drag and on exit; =load restores it.\n"
|
||||
"# <title>=<x>,<y>,<w>,<h> - the size is written for reference and\n"
|
||||
"# ignored on load.\n", file);
|
||||
fputs("# RP412 window placement. RP412MFDLAYOUT=save writes this on each\n"
|
||||
"# finished drag and on exit; =load restores it.\n"
|
||||
"# <title>=<x>,<y>,<w>,<h>. The game window gets its size back too;\n"
|
||||
"# for the display panes the size is reference only, since theirs\n"
|
||||
"# follows their content.\n", file);
|
||||
|
||||
int wrote = 0;
|
||||
for (int i = 0; i < layoutPaneCount; ++i)
|
||||
for (int i = 0; i < layoutWindowCount; ++i)
|
||||
{
|
||||
MFDSplitView *pane = layoutPanes[i];
|
||||
if (pane == NULL || pane->Title() == NULL)
|
||||
LayoutWindow &entry = layoutWindows[i];
|
||||
if (entry.title == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
HWND pane_window = (HWND) pane->Window();
|
||||
if (pane_window == NULL || !IsWindow(pane_window))
|
||||
HWND entry_window = (HWND) entry.window;
|
||||
if (entry_window == NULL || !IsWindow(entry_window))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
RECT bounds;
|
||||
if (!GetWindowRect(pane_window, &bounds))
|
||||
//
|
||||
// rcNormalPosition rather than GetWindowRect: a minimised window
|
||||
// reports a nonsense rect and a maximised one reports the screen,
|
||||
// and neither is what to come back to. This is the restored
|
||||
// placement whatever state the window is in, so quitting from
|
||||
// maximised still records where the window will reappear.
|
||||
//
|
||||
WINDOWPLACEMENT placement;
|
||||
memset(&placement, 0, sizeof(placement));
|
||||
placement.length = sizeof(placement);
|
||||
if (!GetWindowPlacement(entry_window, &placement))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fprintf(file, "%s=%ld,%ld,%ld,%ld\n", pane->Title(),
|
||||
RECT bounds = placement.rcNormalPosition;
|
||||
fprintf(file, "%s=%ld,%ld,%ld,%ld\n", entry.title,
|
||||
(long) bounds.left, (long) bounds.top,
|
||||
(long) (bounds.right - bounds.left),
|
||||
(long) (bounds.bottom - bounds.top));
|
||||
@@ -463,7 +558,7 @@ void
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
DEBUG_STREAM << "MFDLayout: saved " << wrote << " pane position(s) to "
|
||||
DEBUG_STREAM << "MFDLayout: saved " << wrote << " window placement(s) to "
|
||||
<< layoutFileName << "\n" << std::flush;
|
||||
}
|
||||
|
||||
|
||||
+43
-15
@@ -167,30 +167,58 @@ protected:
|
||||
};
|
||||
|
||||
//########################################################################
|
||||
// Sticky window placement for the exploded view (L4MFDSPLIT=2).
|
||||
// Sticky window placement.
|
||||
//
|
||||
// Those panes are draggable desktop windows, but the arrangement is
|
||||
// recomputed on every launch, so dragging one somewhere useful never
|
||||
// survived the menu-race-menu loop. RP412MFDLAYOUT persists it to
|
||||
// mfd_layout.cfg beside bindings.txt:
|
||||
// The game window and, in the exploded view, each display pane are all
|
||||
// draggable, but their placement is recomputed on every launch - so
|
||||
// putting a window somewhere useful never survived the menu-race-menu
|
||||
// loop. RP412MFDLAYOUT remembers it, in mfd_layout.cfg beside
|
||||
// bindings.txt:
|
||||
//
|
||||
// off / 0 / unset computed arrangement only, no file (default)
|
||||
// load / restore restore saved positions at startup, never write
|
||||
// off / 0 / unset computed placement only, no file (default)
|
||||
// load / restore restore saved placement at startup, never write
|
||||
// save / adjust restore, then rewrite on each finished drag and
|
||||
// on teardown - the round trip
|
||||
//
|
||||
// One "<title>=x,y,w,h" line per pane. Position is restored and size
|
||||
// ignored: a pane's size follows its content and its button banks, so an
|
||||
// old w,h from a different build must not distort it.
|
||||
// One "<title>=x,y,w,h" line per window.
|
||||
//
|
||||
// Whether the size comes back depends on the window, which is why
|
||||
// Register takes it as a flag:
|
||||
//
|
||||
// display panes position only. A pane's size follows its content and
|
||||
// its button banks, so an old size from a different
|
||||
// build must not distort it.
|
||||
// the game window position, and size in the cockpit view. Nothing
|
||||
// derives that size - the cockpit fits itself to
|
||||
// whatever client area it is given - so a window sized
|
||||
// to suit a monitor should come back that way, and
|
||||
// half-restoring it would be the strange behaviour. In
|
||||
// the exploded view its size IS the render resolution
|
||||
// -res asked for, so there only the position returns.
|
||||
//
|
||||
// A placement that lands on none of the monitors currently plugged in is
|
||||
// ignored rather than applied - restoring the game window off screen
|
||||
// would leave nothing to drag back.
|
||||
//
|
||||
// Lives here because the display panes were the first to need it; the
|
||||
// game window joined later rather than grow a second copy of the same
|
||||
// file format.
|
||||
//
|
||||
// Ported from BT411's BT_GLASS_LAYOUT.
|
||||
//########################################################################
|
||||
|
||||
// Apply saved positions over the computed ones. Call after the panes are
|
||||
// built and placed.
|
||||
// Take part in the saved layout. title is the key in the file and must
|
||||
// outlive the window (the callers pass string literals).
|
||||
void
|
||||
MFDSplitView_LoadLayout();
|
||||
RPWindowLayout_Register(void *window, const char *title, Logical with_size);
|
||||
void
|
||||
RPWindowLayout_Forget(void *window);
|
||||
|
||||
// Write every open pane's position. No-op unless the mode is save.
|
||||
// Apply the saved placement over the computed one. Call once everything
|
||||
// has been built and placed.
|
||||
void
|
||||
MFDSplitView_SaveLayout();
|
||||
RPWindowLayout_Load();
|
||||
|
||||
// Write every registered window's placement. No-op unless mode is save.
|
||||
void
|
||||
RPWindowLayout_Save();
|
||||
|
||||
+47
-8
@@ -3839,6 +3839,15 @@ static LRESULT CALLBACK
|
||||
cockpit->LayoutCockpit(LOWORD(lParam), HIWORD(lParam));
|
||||
}
|
||||
}
|
||||
else if (message == WM_EXITSIZEMOVE)
|
||||
{
|
||||
//
|
||||
// The shell was just dragged or resized. Write the arrangement now
|
||||
// rather than trusting teardown, so a hard kill still leaves what
|
||||
// was on screen. No-op unless RP412MFDLAYOUT is save.
|
||||
//
|
||||
RPWindowLayout_Save();
|
||||
}
|
||||
return CallWindowProcA(gCockpitBaseProc, hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
@@ -4459,11 +4468,24 @@ SVGA16::SVGA16(
|
||||
splitView[SplitMap]->SetPosition(work.left + map_x, work.top + map_y);
|
||||
|
||||
//
|
||||
// ...and then let RP412MFDLAYOUT put back anywhere they were
|
||||
// dragged to last time. Panes the file does not mention keep the
|
||||
// The game window joins them, position only: here its size is the
|
||||
// render resolution -res asked for, so restoring an old one would
|
||||
// leave a stretched back buffer in a window the wrong size.
|
||||
//
|
||||
{
|
||||
HWND shell = ApplicationManager::GetCurrentManager()->GetHWnd();
|
||||
if (shell != NULL)
|
||||
{
|
||||
RPWindowLayout_Register(shell, "RPL4", False);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ...and then let RP412MFDLAYOUT put everything back where it was
|
||||
// dragged to last time. Windows the file does not mention keep the
|
||||
// arrangement just computed above.
|
||||
//
|
||||
MFDSplitView_LoadLayout();
|
||||
RPWindowLayout_Load();
|
||||
}
|
||||
else if (splitViews)
|
||||
{
|
||||
@@ -4675,6 +4697,23 @@ SVGA16::SVGA16(
|
||||
// catch maximise / restore / drag-resize and re-fit
|
||||
gCockpitBaseProc = (WNDPROC) SetWindowLongPtrA(
|
||||
cockpit, GWLP_WNDPROC, (LONG_PTR) CockpitShellProc);
|
||||
|
||||
//
|
||||
// Sticky placement for the shell. Position AND size: nothing
|
||||
// derives that size here - -res only decides how sharp the
|
||||
// scene is - so a window sized to suit a monitor should come
|
||||
// back that way. Registered after the subclass on purpose, so
|
||||
// the restore's WM_SIZE runs LayoutCockpit again and the
|
||||
// canvas re-fits the restored client area.
|
||||
//
|
||||
// -fit sits it borderless over the whole monitor, so there is
|
||||
// no placement of the player's to remember.
|
||||
//
|
||||
if (!fit_display)
|
||||
{
|
||||
RPWindowLayout_Register(cockpit, "RPL4", True);
|
||||
RPWindowLayout_Load();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4871,12 +4910,12 @@ SVGA16::~SVGA16()
|
||||
//SVGASetSplitterClock(False);
|
||||
|
||||
//
|
||||
// Backstop for the sticky exploded-view placement: every finished drag
|
||||
// has already been written, but a pane moved and then closed straight
|
||||
// away would otherwise be missed. Must run before the panes go - it
|
||||
// reads their live window rects.
|
||||
// Backstop for the sticky placement: every finished drag has already
|
||||
// been written, but a window moved and then closed straight away would
|
||||
// otherwise be missed. Must run before the panes go - it reads their
|
||||
// live window rects, and the game window's.
|
||||
//
|
||||
MFDSplitView_SaveLayout();
|
||||
RPWindowLayout_Save();
|
||||
|
||||
for (int view = 0; view < SplitViewCount; ++view)
|
||||
{
|
||||
|
||||
+11
-9
@@ -166,16 +166,18 @@ L4PLASMA=SCREEN
|
||||
# 480x640 - decoded exactly as the pod's VDB split them, no downscale).
|
||||
L4MFDSPLIT=1
|
||||
|
||||
# In the exploded view (L4MFDSPLIT=2) each display is a window you can
|
||||
# drag, but the arrangement is recomputed every launch, so moving one
|
||||
# somewhere useful never survived the menu-race-menu loop. This remembers
|
||||
# it, in mfd_layout.cfg beside this file:
|
||||
# off / 0 / unset computed arrangement only, no file (default)
|
||||
# load put the panes back where they were saved
|
||||
# The game window - and in the exploded view (L4MFDSPLIT=2) each display
|
||||
# window - is placed fresh every launch, so moving one somewhere useful
|
||||
# never survived the menu-race-menu loop. This remembers where you put
|
||||
# them, in mfd_layout.cfg beside this file:
|
||||
# off / 0 / unset computed placement only, no file (default)
|
||||
# load put the windows back where they were saved
|
||||
# save the same, and re-save on every finished drag
|
||||
# Only positions are remembered - a pane's size follows its content and
|
||||
# its button banks, so an old size is never restored over it. Drag the
|
||||
# displays where you want them once with save, then leave it on load.
|
||||
# The game window gets its size back too, so you can size the cockpit to
|
||||
# suit your monitor once and keep it. The display windows get position
|
||||
# only: their size follows their content and their button banks, so an
|
||||
# old one is never restored over them. Arrange everything once with
|
||||
# save, then leave it on load.
|
||||
#RP412MFDLAYOUT=off
|
||||
|
||||
# Size of the six secondary displays in the glass cockpit, as a
|
||||
|
||||
Reference in New Issue
Block a user