Skip to content

Commit 445b0af

Browse files
author
Tom Lally
authored
Better screenshot error handling (#552)
1 parent c1afa4c commit 445b0af

File tree

1 file changed

+69
-41
lines changed

1 file changed

+69
-41
lines changed

src/Cafe/HW/Latte/Renderer/Renderer.cpp

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <wx/image.h>
1414
#include <wx/dataobj.h>
1515
#include <wx/clipbrd.h>
16+
#include <wx/log.h>
1617

1718
std::unique_ptr<Renderer> g_renderer;
1819

@@ -81,7 +82,7 @@ uint8 Renderer::RGBComponentToSRGB(uint8 cli)
8182
return (uint8)(cs * 255.0f);
8283
}
8384

84-
fs::path _GenerateScreenshotFilename(bool isDRC)
85+
static std::optional<fs::path> GenerateScreenshotFilename(bool isDRC)
8586
{
8687
fs::path screendir = ActiveSettings::GetUserDataPath("screenshots");
8788
// build screenshot name with format Screenshot_YYYY-MM-DD_HH-MM-SS[_GamePad].png
@@ -101,60 +102,87 @@ fs::path _GenerateScreenshotFilename(bool isDRC)
101102
screenshotPath.append(fmt::format("{}.png", screenshotFileName));
102103
else
103104
screenshotPath.append(fmt::format("{}_{}.png", screenshotFileName, i + 1));
105+
104106
std::error_code ec;
105-
if (!fs::exists(screenshotPath))
107+
bool exists = fs::exists(screenshotPath, ec);
108+
109+
if (!ec && !exists)
106110
return screenshotPath;
107111
}
108-
return screenshotPath; // if all exist checks fail, return the last path we tried
112+
return std::nullopt;
109113
}
110114

111115
std::mutex s_clipboardMutex;
112116

113-
void Renderer::SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int height, bool mainWindow) const
117+
static bool SaveScreenshotToClipboard(const wxImage &image)
118+
{
119+
bool success = false;
120+
121+
s_clipboardMutex.lock();
122+
if (wxTheClipboard->Open())
123+
{
124+
wxTheClipboard->SetData(new wxImageDataObject(image));
125+
wxTheClipboard->Close();
126+
success = true;
127+
}
128+
s_clipboardMutex.unlock();
129+
130+
return success;
131+
}
132+
133+
static bool SaveScreenshotToFile(const wxImage &image, bool mainWindow)
134+
{
135+
auto path = GenerateScreenshotFilename(!mainWindow);
136+
if (!path) return false;
137+
138+
std::error_code ec;
139+
fs::create_directories(path->parent_path(), ec);
140+
if (ec) return false;
141+
142+
// suspend wxWidgets logging for the lifetime this object, to prevent a message box if wxImage::SaveFile fails
143+
wxLogNull _logNo;
144+
return image.SaveFile(path->wstring());
145+
}
146+
147+
static void ScreenshotThread(std::vector<uint8> data, bool save_screenshot, int width, int height, bool mainWindow)
114148
{
115-
const bool save_screenshot = GetConfig().save_screenshot;
116-
std::thread([](std::vector<uint8> data, bool save_screenshot, int width, int height, bool mainWindow)
117-
{
118149
#if BOOST_OS_WINDOWS
119-
// on Windows wxWidgets uses OLE API for the clipboard
120-
// to make this work we need to call OleInitialize() on the same thread
121-
OleInitialize(nullptr);
150+
// on Windows wxWidgets uses OLE API for the clipboard
151+
// to make this work we need to call OleInitialize() on the same thread
152+
OleInitialize(nullptr);
122153
#endif
154+
155+
wxImage image(width, height, data.data(), true);
123156

124-
wxImage image(width, height, data.data(), true);
125-
126-
if (mainWindow)
157+
if (mainWindow)
158+
{
159+
if(SaveScreenshotToClipboard(image))
127160
{
128-
s_clipboardMutex.lock();
129-
if (wxTheClipboard->Open())
130-
{
131-
wxTheClipboard->SetData(new wxImageDataObject(image));
132-
wxTheClipboard->Close();
133-
if(!save_screenshot && mainWindow)
134-
LatteOverlay_pushNotification("Screenshot saved to clipboard", 2500);
135-
}
136-
else
137-
{
138-
LatteOverlay_pushNotification("Failed to open clipboard", 2500);
139-
}
140-
s_clipboardMutex.unlock();
161+
if (!save_screenshot)
162+
LatteOverlay_pushNotification("Screenshot saved to clipboard", 2500);
141163
}
164+
else
165+
{
166+
LatteOverlay_pushNotification("Failed to open clipboard", 2500);
167+
}
168+
}
142169

143-
// save to png file
144-
if (save_screenshot)
170+
if (save_screenshot)
171+
{
172+
if (SaveScreenshotToFile(image, mainWindow))
145173
{
146-
fs::path screendir = _GenerateScreenshotFilename(!mainWindow);
147-
if (!fs::exists(screendir.parent_path()))
148-
fs::create_directories(screendir.parent_path());
149-
if (image.SaveFile(screendir.wstring()))
150-
{
151-
if(mainWindow)
152-
LatteOverlay_pushNotification("Screenshot saved", 2500);
153-
}
154-
else
155-
{
156-
LatteOverlay_pushNotification("Failed to save screenshot to file", 2500);
157-
}
174+
if (mainWindow)
175+
LatteOverlay_pushNotification("Screenshot saved", 2500);
158176
}
159-
}, rgb_data, save_screenshot, width, height, mainWindow).detach();
177+
else
178+
{
179+
LatteOverlay_pushNotification("Failed to save screenshot to file", 2500);
180+
}
181+
}
182+
}
183+
184+
void Renderer::SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int height, bool mainWindow) const
185+
{
186+
const bool save_screenshot = GetConfig().save_screenshot;
187+
std::thread(ScreenshotThread, rgb_data, save_screenshot, width, height, mainWindow).detach();
160188
}

0 commit comments

Comments
 (0)