diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h
index 2d28ec9bc..316825f10 100644
--- a/src/include/86box/plat.h
+++ b/src/include/86box/plat.h
@@ -153,6 +153,7 @@ extern void plat_language_code_r(int id, char *outbuf, int len);
extern void plat_get_cpu_string(char *outbuf, uint8_t len);
extern void plat_set_thread_name(void *thread, const char *name);
extern void plat_break(void);
+extern void plat_send_to_clipboard(unsigned char *rgb, int width, int height);
/* Resource management. */
extern wchar_t *plat_get_string(int id);
diff --git a/src/include/86box/video.h b/src/include/86box/video.h
index b94bdf415..b7f86ac18 100644
--- a/src/include/86box/video.h
+++ b/src/include/86box/video.h
@@ -145,6 +145,9 @@ typedef struct monitor_t {
int mon_renderedframes;
atomic_int mon_actualrenderedframes;
atomic_int mon_screenshots;
+ atomic_int mon_screenshots_clipboard;
+ atomic_int mon_screenshots_raw;
+ atomic_int mon_screenshots_raw_clipboard;
uint32_t *mon_pal_lookup;
int *mon_cga_palette;
int mon_pal_lookup_static; /* Whether it should not be freed by the API. */
diff --git a/src/qt/icons/copy_raw_screenshot.ico b/src/qt/icons/copy_raw_screenshot.ico
new file mode 100644
index 000000000..80626be20
Binary files /dev/null and b/src/qt/icons/copy_raw_screenshot.ico differ
diff --git a/src/qt/icons/copy_screenshot.ico b/src/qt/icons/copy_screenshot.ico
new file mode 100644
index 000000000..5ea6bc705
Binary files /dev/null and b/src/qt/icons/copy_screenshot.ico differ
diff --git a/src/qt/icons/take_raw_screenshot.ico b/src/qt/icons/take_raw_screenshot.ico
new file mode 100644
index 000000000..b33735a83
Binary files /dev/null and b/src/qt/icons/take_raw_screenshot.ico differ
diff --git a/src/qt/icons/take_screenshot.ico b/src/qt/icons/take_screenshot.ico
new file mode 100644
index 000000000..66f83ebbd
Binary files /dev/null and b/src/qt/icons/take_screenshot.ico differ
diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po
index 75e0a593d..314b12e3e 100644
--- a/src/qt/languages/ca-ES.po
+++ b/src/qt/languages/ca-ES.po
@@ -210,6 +210,15 @@ msgstr "&Actualitza icones a la barra d'estat"
msgid "Take s&creenshot"
msgstr "Desa captura de &pantalla"
+msgid "Take &raw screenshot"
+msgstr "Desa captura en &brut de pantalla"
+
+msgid "C&opy screenshot"
+msgstr "C&opia captura de pantalla"
+
+msgid "Copy r&aw screenshot"
+msgstr "Copy captura en b&rut de pantalla"
+
msgid "S&ound"
msgstr "S&o"
diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po
index dbb0d2826..041992219 100644
--- a/src/qt/languages/cs-CZ.po
+++ b/src/qt/languages/cs-CZ.po
@@ -210,6 +210,15 @@ msgstr "&Aktualizovat ikony stavového řádku"
msgid "Take s&creenshot"
msgstr "Pořídit &screenshot"
+msgid "Take &raw screenshot"
+msgstr "Pořídit &surový screenshot"
+
+msgid "C&opy screenshot"
+msgstr "Z&kopírovát screenshot"
+
+msgid "Copy r&aw screenshot"
+msgstr "Zkopírovát s&urový screenshot"
+
msgid "S&ound"
msgstr "&Zvuk"
diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po
index e426d1e2d..634069dd7 100644
--- a/src/qt/languages/de-DE.po
+++ b/src/qt/languages/de-DE.po
@@ -210,6 +210,15 @@ msgstr "&Statusleistenicons aktualisieren"
msgid "Take s&creenshot"
msgstr "S&creenshot aufnehmen"
+msgid "Take &raw screenshot"
+msgstr "&Roh-Screenshot aufnehmen"
+
+msgid "C&opy screenshot"
+msgstr "Screenshot k&opieren"
+
+msgid "Copy r&aw screenshot"
+msgstr "R&oh-Screenshot kopieren"
+
msgid "S&ound"
msgstr "&Ton"
diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po
index 53bd643b2..de155cf7a 100644
--- a/src/qt/languages/es-ES.po
+++ b/src/qt/languages/es-ES.po
@@ -210,6 +210,15 @@ msgstr "&Actualizar iconos en barra de estado"
msgid "Take s&creenshot"
msgstr "Tomar cap&tura"
+msgid "Take &raw screenshot"
+msgstr "Tomar captura &plana"
+
+msgid "C&opy screenshot"
+msgstr "C&opiar captura"
+
+msgid "Copy r&aw screenshot"
+msgstr "Copiar captura p&lana"
+
msgid "S&ound"
msgstr "S&onido"
diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po
index 0db30bede..d43b70192 100644
--- a/src/qt/languages/fi-FI.po
+++ b/src/qt/languages/fi-FI.po
@@ -210,6 +210,15 @@ msgstr "&Päivitä tilapalkin kuvakkeita"
msgid "Take s&creenshot"
msgstr "Ota &kuvakaappaus"
+msgid "Take &raw screenshot"
+msgstr "Ota &raaka kuvakaapus"
+
+msgid "C&opy screenshot"
+msgstr "K&opia kuvakaapaus"
+
+msgid "Copy r&aw screenshot"
+msgstr "Kopia r&aaka kuvakaapaus"
+
msgid "S&ound"
msgstr "&Ääni"
diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po
index 6a5628f29..aa550e5f3 100644
--- a/src/qt/languages/fr-FR.po
+++ b/src/qt/languages/fr-FR.po
@@ -208,7 +208,16 @@ msgid "&Update status bar icons"
msgstr "Mettre à jour la barre de stat&us"
msgid "Take s&creenshot"
-msgstr "Copie d'é&cran"
+msgstr "Faire copie d'é&cran"
+
+msgid "Take &raw screenshot"
+msgstr "Faire copie &brute d'écran"
+
+msgid "C&opy screenshot"
+msgstr "C&opier copie d'écran"
+
+msgid "Copy r&aw screenshot"
+msgstr "Copier copie b&rute d'écran"
msgid "S&ound"
msgstr "S&on"
diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po
index 5261ab338..882da52b5 100644
--- a/src/qt/languages/hr-HR.po
+++ b/src/qt/languages/hr-HR.po
@@ -212,6 +212,15 @@ msgstr "&Ažuriraj ikone statusnog redka"
msgid "Take s&creenshot"
msgstr "Napravi &snimku zaslona"
+msgid "Take &raw screenshot"
+msgstr "Napravi &neobrađenu snimku zaslona"
+
+msgid "C&opy screenshot"
+msgstr "K&opiraj snimku zalsona"
+
+msgid "Copy r&aw screenshot"
+msgstr "Kopiraj n&eobrađenu snimku zaslona"
+
msgid "S&ound"
msgstr "&Zvuk"
diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po
index 67937b089..36621b840 100644
--- a/src/qt/languages/it-IT.po
+++ b/src/qt/languages/it-IT.po
@@ -210,6 +210,15 @@ msgstr "&Aggiorna icone della barra di stato"
msgid "Take s&creenshot"
msgstr "&Cattura schermata"
+msgid "Take &raw screenshot"
+msgstr "Cattura &grezza della schermata"
+
+msgid "C&opy screenshot"
+msgstr "C&opia cattura della schermata"
+
+msgid "Copy r&aw screenshot"
+msgstr "Copia cattura g&rezza della schermata"
+
msgid "S&ound"
msgstr "A&udio"
@@ -1420,7 +1429,7 @@ msgid "Don't overwrite"
msgstr "Non sovrascrivere"
msgid "Raw image"
-msgstr "Immagine RAW"
+msgstr "Immagine grezza"
msgid "HDI image"
msgstr "Immagine HDI"
diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po
index cfd44daba..d9eba2646 100644
--- a/src/qt/languages/ja-JP.po
+++ b/src/qt/languages/ja-JP.po
@@ -211,6 +211,15 @@ msgstr "ステータスバーのアイコンを更新(&U)"
msgid "Take s&creenshot"
msgstr "スクリーンショットを撮る(&C)"
+msgid "Take &raw screenshot"
+msgstr "生のスクリーンショットを撮る(&R)"
+
+msgid "C&opy screenshot"
+msgstr "スクリーンショットをコピーする(&O)"
+
+msgid "Copy r&aw screenshot"
+msgstr "生のスクリーンショットをコピーする(&A)"
+
msgid "S&ound"
msgstr "サウンド(&O)"
@@ -1421,7 +1430,7 @@ msgid "Don't overwrite"
msgstr "上書きしない"
msgid "Raw image"
-msgstr "Rawイメージ"
+msgstr "生のイメージ"
msgid "HDI image"
msgstr "HDIイメージ"
diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po
index e49476e40..51b77209d 100644
--- a/src/qt/languages/ko-KR.po
+++ b/src/qt/languages/ko-KR.po
@@ -204,6 +204,15 @@ msgstr "상태 바 아이콘 갱신하기(&U)"
msgid "Take s&creenshot"
msgstr "스크린샷 찍기(&C)"
+msgid "Take &raw screenshot"
+msgstr "원본 스크린샷 찍기(&R)"
+
+msgid "C&opy screenshot"
+msgstr "스크린샷 복사하세요(&O)"
+
+msgid "Copy r&aw screenshot"
+msgstr "원본 스크린샷 복사하세요(&A)"
+
msgid "S&ound"
msgstr "사운드(&O)"
@@ -1414,7 +1423,7 @@ msgid "Don't overwrite"
msgstr "덮어쓰지 않음"
msgid "Raw image"
-msgstr "Raw 이미지"
+msgstr "원본 이미지"
msgid "HDI image"
msgstr "HDI 이미지"
diff --git a/src/qt/languages/nb-NO.po b/src/qt/languages/nb-NO.po
index 5b2748210..4da9f6073 100644
--- a/src/qt/languages/nb-NO.po
+++ b/src/qt/languages/nb-NO.po
@@ -204,6 +204,15 @@ msgstr "&Oppdater statuslinjeikoner"
msgid "Take s&creenshot"
msgstr "Ta s&kjermbilde"
+msgid "Take &raw screenshot"
+msgstr "Ta &rå skjermbilde"
+
+msgid "C&opy screenshot"
+msgstr "K&opiera skjermbilde"
+
+msgid "Copy r&aw screenshot"
+msgstr "Kopiera r&å skjermbilde"
+
msgid "S&ound"
msgstr "L&yd"
diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po
index 88a0964ec..abaae4a98 100644
--- a/src/qt/languages/nl-NL.po
+++ b/src/qt/languages/nl-NL.po
@@ -202,7 +202,16 @@ msgid "&Update status bar icons"
msgstr "&Statusbalkpictogrammen bijwerken"
msgid "Take s&creenshot"
-msgstr "Maak een schermafbeelding"
+msgstr "Maak een s&chermafbeelding"
+
+msgid "Take &raw screenshot"
+msgstr "Maak een &ruw schermafbeelding"
+
+msgid "C&opy screenshot"
+msgstr "K&opieer een schermafbeelding"
+
+msgid "Copy r&aw screenshot"
+msgstr "Kopieer een r&uw schermafbeelding"
msgid "S&ound"
msgstr "&Geluid"
diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po
index 43b89a8da..02a24fa2c 100644
--- a/src/qt/languages/pl-PL.po
+++ b/src/qt/languages/pl-PL.po
@@ -211,6 +211,15 @@ msgstr "&Aktualizuj ikony na pasku statusu"
msgid "Take s&creenshot"
msgstr "Zrób &zrzut ekranu"
+msgid "Take &raw screenshot"
+msgstr "Zrób &surowy zrzut ekranu"
+
+msgid "C&opy screenshot"
+msgstr "S&kopiuj zrzut ekranu"
+
+msgid "Copy r&aw screenshot"
+msgstr "Skopiuj s&urowy zrzut ekranu"
+
msgid "S&ound"
msgstr "Dź&więk"
diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po
index 04b96c62d..02e13e571 100644
--- a/src/qt/languages/pt-BR.po
+++ b/src/qt/languages/pt-BR.po
@@ -204,6 +204,15 @@ msgstr "&Atualizar ícones da barra de status"
msgid "Take s&creenshot"
msgstr "Capturar &tela"
+msgid "Take &raw screenshot"
+msgstr "Fazer captura &bruta da tela"
+
+msgid "C&opy screenshot"
+msgstr "C&opiar captura da tela"
+
+msgid "Copy r&aw screenshot"
+msgstr "Copiar captura b&ruta da tela"
+
msgid "S&ound"
msgstr "&Som"
diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po
index f81d1ec94..5b3aaecec 100644
--- a/src/qt/languages/pt-PT.po
+++ b/src/qt/languages/pt-PT.po
@@ -211,6 +211,15 @@ msgstr "&Atualizar ícones da barra de estado"
msgid "Take s&creenshot"
msgstr "Gravar imagem de &ecrã"
+msgid "Take &raw screenshot"
+msgstr "Gravar imagem &bruta de ecrã"
+
+msgid "C&opy screenshot"
+msgstr "Copiar imagem de ecrã"
+
+msgid "Copy r&aw screenshot"
+msgstr "Copiar imagem b&ruta de ecrã"
+
msgid "S&ound"
msgstr "&Som"
diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po
index ce3fe75a3..9e16f6c28 100644
--- a/src/qt/languages/ru-RU.po
+++ b/src/qt/languages/ru-RU.po
@@ -211,6 +211,15 @@ msgstr "&Обновление значков строки состояния"
msgid "Take s&creenshot"
msgstr "Сделать с&криншот"
+msgid "Take &raw screenshot"
+msgstr "Сделать &сырой скриншот"
+
+msgid "C&opy screenshot"
+msgstr "С&копировать скриншот"
+
+msgid "Copy r&aw screenshot"
+msgstr "Скопировать с&ырой скриншот"
+
msgid "S&ound"
msgstr "&Звук"
@@ -1433,7 +1442,7 @@ msgid "Don't overwrite"
msgstr "Не перезаписывать"
msgid "Raw image"
-msgstr "RAW образ"
+msgstr "Сырой образ"
msgid "HDI image"
msgstr "Образ HDI"
diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po
index f049c3f48..0310f6938 100644
--- a/src/qt/languages/sk-SK.po
+++ b/src/qt/languages/sk-SK.po
@@ -210,6 +210,15 @@ msgstr "&Aktualizovať ikony na stavovom riadku"
msgid "Take s&creenshot"
msgstr "Urobiť snímku &obrazovky"
+msgid "Take &raw screenshot"
+msgstr "Urobiť &surovú snímku obrazovky"
+
+msgid "C&opy screenshot"
+msgstr "S&kopírovať snímku obrazovky"
+
+msgid "Copy r&aw screenshot"
+msgstr "Skopírovať s&urovú snímku obrazovky"
+
msgid "S&ound"
msgstr "&Zvuk"
diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po
index d6a4c20ea..4e31b36da 100644
--- a/src/qt/languages/sl-SI.po
+++ b/src/qt/languages/sl-SI.po
@@ -212,6 +212,15 @@ msgstr "&Posodabljaj ikone statusne vrstice"
msgid "Take s&creenshot"
msgstr "&Zajemi posnetek zaslona"
+msgid "Take &raw screenshot"
+msgstr "Zajemi &neobdelan posnetek zaslona"
+
+msgid "C&opy screenshot"
+msgstr "K&opiraj posnetek zaslona"
+
+msgid "Copy r&aw screenshot"
+msgstr "Kopriaj n&eobdelan posenetk zaslona"
+
msgid "S&ound"
msgstr "Z&vok"
diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po
index 4e626a47b..d937828f9 100644
--- a/src/qt/languages/sv-SE.po
+++ b/src/qt/languages/sv-SE.po
@@ -204,6 +204,15 @@ msgstr "&Uppdatera statusfältets ikoner"
msgid "Take s&creenshot"
msgstr "Tag s&kärmbild"
+msgid "Take &raw screenshot"
+msgstr "Tag &rå skärmbild"
+
+msgid "C&opy screenshot"
+msgstr "Kopiera skärmbild"
+
+msgid "Copy r&aw screenshot"
+msgstr "Kopera r&å skärmbild"
+
msgid "S&ound"
msgstr "L&jud"
diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po
index 91301e0b3..f2a21f5d2 100644
--- a/src/qt/languages/tr-TR.po
+++ b/src/qt/languages/tr-TR.po
@@ -204,6 +204,15 @@ msgstr "Durum &çubuğu simgelerini güncelle"
msgid "Take s&creenshot"
msgstr "&Ekran görüntüsü al"
+msgid "Take &raw screenshot"
+msgstr "Ekran &ham görüntüsü al"
+
+msgid "C&opy screenshot"
+msgstr "Ekran görüntüsü k&opyala"
+
+msgid "Copy r&aw screenshot"
+msgstr "Ekran h&am görüntüsü kopyala"
+
msgid "S&ound"
msgstr "&Ses"
diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po
index 49eac891c..f9ff3e467 100644
--- a/src/qt/languages/uk-UA.po
+++ b/src/qt/languages/uk-UA.po
@@ -212,6 +212,15 @@ msgstr "&Обновлення значків рядка стану"
msgid "Take s&creenshot"
msgstr "Зробити &знімок"
+msgid "Take &raw screenshot"
+msgstr "Зробити &сирий знімок"
+
+msgid "C&opy screenshot"
+msgstr "С&копійовати знімок"
+
+msgid "Copy r&aw screenshot"
+msgstr "Скопійовати с&ирий знімок"
+
msgid "S&ound"
msgstr "&Звук"
@@ -1422,7 +1431,7 @@ msgid "Don't overwrite"
msgstr "Не перезаписувати"
msgid "Raw image"
-msgstr "RAW образ"
+msgstr "Сирий образ"
msgid "HDI image"
msgstr "Образ HDI"
diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po
index 0471fa1f0..e4d7a806d 100644
--- a/src/qt/languages/vi-VN.po
+++ b/src/qt/languages/vi-VN.po
@@ -204,6 +204,15 @@ msgstr "Cậ&p nhật biểu tượng thanh trạng thái"
msgid "Take s&creenshot"
msgstr "Chụp &màn hình"
+msgid "Take &raw screenshot"
+msgstr "Chụp màn hình &thô"
+
+msgid "C&opy screenshot"
+msgstr "S&ao chép ảnh chụp màn hình"
+
+msgid "Copy r&aw screenshot"
+msgstr "Sao chép ảnh chụp màn hình t&hô"
+
msgid "S&ound"
msgstr "&Âm thanh"
diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po
index cf31d6975..cea569a6f 100644
--- a/src/qt/languages/zh-CN.po
+++ b/src/qt/languages/zh-CN.po
@@ -204,6 +204,15 @@ msgstr "更新状态栏图标(&U)"
msgid "Take s&creenshot"
msgstr "截图(&C)"
+msgid "Take &raw screenshot"
+msgstr "原始截图(&R)"
+
+msgid "C&opy screenshot"
+msgstr "复制截图(&O)"
+
+msgid "Copy r&aw screenshot"
+msgstr "复制原始截图(&A)"
+
msgid "S&ound"
msgstr "声音(&O)"
diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po
index 156dbb2fe..ddb879c8f 100644
--- a/src/qt/languages/zh-TW.po
+++ b/src/qt/languages/zh-TW.po
@@ -204,6 +204,15 @@ msgstr "更新狀態列圖示(&U)"
msgid "Take s&creenshot"
msgstr "擷圖(&C)"
+msgid "Take &raw screenshot"
+msgstr "原始擷圖(&R)"
+
+msgid "C&opy screenshot"
+msgstr "複製擷圖(&O)"
+
+msgid "Copy r&aw screenshot"
+msgstr "複製原始擷圖(&A)"
+
msgid "S&ound"
msgstr "聲音(&O)"
diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp
index cd7523985..cce6d9c95 100644
--- a/src/qt/qt_mainwindow.cpp
+++ b/src/qt/qt_mainwindow.cpp
@@ -2263,6 +2263,36 @@ MainWindow::on_actionTake_screenshot_triggered()
device_force_redraw();
}
+void
+MainWindow::on_actionTake_raw_screenshot_triggered()
+{
+ startblit();
+ for (auto &monitor : monitors)
+ ++monitor.mon_screenshots_raw;
+ endblit();
+ device_force_redraw();
+}
+
+void
+MainWindow::on_actionCopy_screenshot_triggered()
+{
+ startblit();
+ for (auto &monitor : monitors)
+ ++monitor.mon_screenshots_clipboard;
+ endblit();
+ device_force_redraw();
+}
+
+void
+MainWindow::on_actionCopy_raw_screenshot_triggered()
+{
+ startblit();
+ for (auto &monitor : monitors)
+ ++monitor.mon_screenshots_raw_clipboard;
+ endblit();
+ device_force_redraw();
+}
+
void
MainWindow::on_actionMute_Unmute_triggered()
{
diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp
index a31900767..e1c0c7409 100644
--- a/src/qt/qt_mainwindow.hpp
+++ b/src/qt/qt_mainwindow.hpp
@@ -132,6 +132,9 @@ private slots:
void on_actionHide_tool_bar_triggered();
void on_actionUpdate_status_bar_icons_triggered();
void on_actionTake_screenshot_triggered();
+ void on_actionTake_raw_screenshot_triggered();
+ void on_actionCopy_screenshot_triggered();
+ void on_actionCopy_raw_screenshot_triggered();
void toggleFullscreenUI();
void on_actionMute_Unmute_triggered();
void on_actionSound_gain_triggered();
diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui
index 777455d5b..27501d0b9 100644
--- a/src/qt/qt_mainwindow.ui
+++ b/src/qt/qt_mainwindow.ui
@@ -70,8 +70,6 @@
-
-
@@ -80,6 +78,8 @@
+
+
@@ -106,6 +106,10 @@
+
+
+
+
@@ -295,8 +299,6 @@
false
-
-
@@ -306,6 +308,13 @@
+
+
+
+
+
+
+
@@ -749,6 +758,37 @@
Ctrl+F11
+
+
+ :/menuicons/qt/icons/take_screenshot.ico:/menuicons/qt/icons/take_screenshot.ico
+
+
+
+
+ Take &raw screenshot
+
+
+
+ :/menuicons/qt/icons/take_raw_screenshot.ico:/menuicons/qt/icons/take_raw_screenshot.ico
+
+
+
+
+ C&opy screenshot
+
+
+
+ :/menuicons/qt/icons/copy_screenshot.ico:/menuicons/qt/icons/copy_screenshot.ico
+
+
+
+
+ Copy r&aw screenshot
+
+
+
+ :/menuicons/qt/icons/copy_raw_screenshot.ico:/menuicons/qt/icons/copy_raw_screenshot.ico
+
diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp
index 8e01bfe6c..22e400c65 100644
--- a/src/qt/qt_openglrenderer.cpp
+++ b/src/qt/qt_openglrenderer.cpp
@@ -26,6 +26,7 @@ extern MainWindow *main_window;
#include
#include
#include
+#include
#include
#include
#include
@@ -1147,6 +1148,8 @@ OpenGLRenderer::finalize()
isFinalized = true;
}
+extern void take_screenshot_clipboard_monitor(int sx, int sy, int sw, int sh, int i);
+
void
OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
{
@@ -1184,6 +1187,10 @@ OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
if (video_framerate == -1)
render();
+
+ if (monitors[r_monitor_index].mon_screenshots_raw_clipboard) {
+ take_screenshot_clipboard_monitor(x, y, w, h, r_monitor_index);
+ }
}
std::vector>
@@ -1725,6 +1732,20 @@ OpenGLRenderer::render()
monitors[r_monitor_index].mon_screenshots--;
free(rgb);
}
+ if (monitors[r_monitor_index].mon_screenshots_clipboard) {
+ int width = destination.width(), height = destination.height();
+
+ unsigned char *rgb = (unsigned char *) calloc(1, (size_t) width * height * 4);
+
+ glw.glFinish();
+ glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
+
+ QImage image((uchar*)rgb, width, height, width * 3, QImage::Format_RGB888);
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setImage(image.mirrored(false, true), QClipboard::Clipboard);
+ monitors[r_monitor_index].mon_screenshots_clipboard--;
+ free(rgb);
+ }
glw.glDisable(GL_FRAMEBUFFER_SRGB);
diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp
index 37653c5a3..9fd16d3f1 100644
--- a/src/qt/qt_platform.cpp
+++ b/src/qt/qt_platform.cpp
@@ -30,8 +30,11 @@
#include
+#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -978,3 +981,37 @@ plat_break(void)
raise(SIGTRAP);
#endif
}
+
+static unsigned char *rgb_ = NULL;
+static int width_ = 0;
+static int height_ = 0;
+static volatile int waiting = 0;
+
+static void
+send_to_clipboard(void)
+{
+ unsigned char *rgb = (unsigned char *) calloc(1, height_ * width_ * 4);
+ memcpy(rgb, rgb_, height_ * width_ * 3);
+ QImage image(rgb, width_, height_, width_ * 3, QImage::Format_RGB888);
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setImage(image, QClipboard::Clipboard);
+ free(rgb);
+ waiting = 0;
+}
+
+void
+plat_send_to_clipboard(unsigned char *rgb, int width, int height)
+{
+ rgb_ = rgb;
+ width_ = width;
+ height_ = height;
+ waiting = 1;
+
+ QTimer::singleShot(0, main_window, &send_to_clipboard);
+ while (waiting)
+ ;
+
+ height_ = 0;
+ width_ = 0;
+ rgb_ = NULL;
+}
diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp
index 41d17d897..99a6bf649 100644
--- a/src/qt/qt_rendererstack.cpp
+++ b/src/qt/qt_rendererstack.cpp
@@ -33,6 +33,9 @@
#include
#include
+#include
+#include
+
#include
#include
#ifdef TOUCH_PR
@@ -66,9 +69,12 @@
# include
#endif
+#include
+
extern "C" {
#include <86box/86box.h>
#include <86box/config.h>
+#include <86box/path.h>
#include <86box/plat.h>
#include <86box/video.h>
#include <86box/mouse.h>
@@ -87,6 +93,8 @@ extern MainWindow *main_window;
HWND rw_hwnd;
#endif
+static unsigned char *screenshot_rgb = NULL;
+
RendererStack::RendererStack(QWidget *parent, int monitor_index)
: QWidget(parent)
, boxLayout(new QBoxLayout(QBoxLayout::TopToBottom, this))
@@ -158,12 +166,20 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index)
if (monitor_index == 0)
mouse_set_raw(raw);
+
+ screenshot_rgb = (unsigned char *) calloc(1, (size_t) 2048 * 2048 * 4);
}
RendererStack::~RendererStack()
{
+ if (screenshot_rgb != NULL) {
+ free(screenshot_rgb);
+ screenshot_rgb = NULL;
+ }
+
while (QApplication::overrideCursor())
QApplication::restoreOverrideCursor();
+
delete ui;
}
@@ -372,11 +388,7 @@ RendererStack::createRenderer(Renderer renderer)
auto sw = new SoftwareRenderer(this);
rendererWindow = sw;
connect(this, &RendererStack::blitToRenderer, sw, &SoftwareRenderer::onBlit, Qt::QueuedConnection);
-#ifdef __HAIKU__
current.reset(sw);
-#else
- current.reset(this->createWindowContainer(sw));
-#endif
}
break;
case Renderer::OpenGL3:
@@ -460,6 +472,32 @@ RendererStack::createRenderer(Renderer renderer)
}
}
+uint32_t *screenshot_buf = NULL;
+
+void
+take_screenshot_clipboard_monitor(int sx, int sy, int sw, int sh, int i)
+{
+ uint32_t temp = 0x00000000;
+
+ for (int y = 0; y < sh; ++y) {
+ for (int x = 0; x < sw; ++x) {
+ if (screenshot_buf == NULL)
+ memset(&(screenshot_rgb[(y * sw * 3) + (x * 3)]), 0x00, 3);
+ else {
+ temp = screenshot_buf[((sy + y) * 2048) + sx + x];
+ screenshot_rgb[(y * sw * 3) + (x * 3)] = (temp >> 16) & 0xff;
+ screenshot_rgb[(y * sw * 3) + (x * 3) + 1] = (temp >> 8) & 0xff;
+ screenshot_rgb[(y * sw * 3) + (x * 3) + 2] = temp & 0xff;
+ }
+ }
+ }
+
+ QImage image(screenshot_rgb, sw, sh, sw * 3, QImage::Format_RGB888);
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setImage(image, QClipboard::Clipboard);
+ monitors[i].mon_screenshots_raw_clipboard--;
+}
+
// called from blitter thread
void
RendererStack::blit(int x, int y, int w, int h)
@@ -478,10 +516,11 @@ RendererStack::blit(int x, int y, int w, int h)
video_copy(scanline, &(monitors[m_monitor_index].target_buffer->line[y1][x]), w * 4);
}
- if (monitors[m_monitor_index].mon_screenshots && !rendererTakesScreenshots) {
+ if (monitors[m_monitor_index].mon_screenshots_raw) {
video_screenshot_monitor((uint32_t *) imagebits, x, y, 2048, m_monitor_index);
}
video_blit_complete_monitor(m_monitor_index);
+ screenshot_buf = (uint32_t *) imagebits;
emit blitToRenderer(currentBuf, sx, sy, sw, sh);
currentBuf = (currentBuf + 1) % imagebufs.size();
}
diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp
index 0a4492a3e..d9e217ed3 100644
--- a/src/qt/qt_softwarerenderer.cpp
+++ b/src/qt/qt_softwarerenderer.cpp
@@ -18,21 +18,19 @@
*/
#include "qt_softwarerenderer.hpp"
#include
+#include
#include
#include
extern "C" {
#include <86box/86box.h>
+#include <86box/path.h>
+#include <86box/plat.h>
#include <86box/video.h>
}
SoftwareRenderer::SoftwareRenderer(QWidget *parent)
-#ifdef __HAIKU__
: QWidget(parent)
-#else
- : QWindow(parent->windowHandle())
- , m_backingStore(new QBackingStore(this))
-#endif
{
RendererCommon::parentWidget = parent;
@@ -42,25 +40,23 @@ SoftwareRenderer::SoftwareRenderer(QWidget *parent)
buf_usage = std::vector(2);
buf_usage[0].clear();
buf_usage[1].clear();
-#ifdef __HAIKU__
this->setMouseTracking(true);
-#endif
}
-#ifdef __HAIKU__
void
SoftwareRenderer::paintEvent(QPaintEvent *event)
{
(void) event;
onPaint(this);
}
-#endif
void
SoftwareRenderer::render()
{
+#ifdef __HAIKU__
if (!isExposed())
return;
+#endif
QRect rect(0, 0, width(), height());
m_backingStore->beginPaint(rect);
@@ -78,6 +74,8 @@ SoftwareRenderer::exposeEvent(QExposeEvent *event)
render();
}
+extern void take_screenshot_clipboard_monitor(int sx, int sy, int sw, int sh, int i);
+
void
SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
{
@@ -94,24 +92,52 @@ SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
if (source != origSource)
onResize(this->width(), this->height());
-#ifdef __HAIKU__
+
update();
-#else
- render();
-#endif
+
+ if (monitors[r_monitor_index].mon_screenshots) {
+ char path[1024];
+ char fn[256];
+
+ memset(fn, 0, sizeof(fn));
+ memset(path, 0, sizeof(path));
+
+ path_append_filename(path, usr_path, SCREENSHOT_PATH);
+
+ if (!plat_dir_check(path))
+ plat_dir_create(path);
+
+ path_slash(path);
+ strcat(path, "Monitor_");
+ snprintf(&path[strlen(path)], 42, "%d_", r_monitor_index + 1);
+
+ plat_tempfile(fn, NULL, (char *) ".png");
+ strcat(path, fn);
+
+ QPixmap pixmap(RendererCommon::parentWidget->size());
+ RendererCommon::parentWidget->render(&pixmap);
+ QImage image = pixmap.toImage();
+ image.save(path, "png");
+ monitors[r_monitor_index].mon_screenshots--;
+ }
+ if (monitors[r_monitor_index].mon_screenshots_clipboard) {
+ QPixmap pixmap(RendererCommon::parentWidget->size());
+ RendererCommon::parentWidget->render(&pixmap);
+ QImage image = pixmap.toImage();
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setImage(image, QClipboard::Clipboard);
+ monitors[r_monitor_index].mon_screenshots_clipboard--;
+ }
+ if (monitors[r_monitor_index].mon_screenshots_raw_clipboard) {
+ take_screenshot_clipboard_monitor(x, y, w, h, r_monitor_index);
+ }
}
void
SoftwareRenderer::resizeEvent(QResizeEvent *event)
{
onResize(width(), height());
-#ifdef __HAIKU__
QWidget::resizeEvent(event);
-#else
- QWindow::resizeEvent(event);
- m_backingStore->resize(event->size());
- render();
-#endif
}
bool
@@ -119,11 +145,7 @@ SoftwareRenderer::event(QEvent *event)
{
bool res = false;
if (!eventDelegate(event, res))
-#ifdef __HAIKU__
return QWidget::event(event);
-#else
- return QWindow::event(event);
-#endif
return res;
}
@@ -142,9 +164,7 @@ SoftwareRenderer::onPaint(QPaintDevice *device)
#endif
painter.setCompositionMode(QPainter::CompositionMode_Plus);
painter.drawImage(destination, *images[cur_image], source);
-#ifndef __HAIKU__
painter.end();
-#endif
}
std::vector>
diff --git a/src/qt/qt_softwarerenderer.hpp b/src/qt/qt_softwarerenderer.hpp
index e80410956..a2b11c012 100644
--- a/src/qt/qt_softwarerenderer.hpp
+++ b/src/qt/qt_softwarerenderer.hpp
@@ -11,21 +11,19 @@
#include "qt_renderercommon.hpp"
class SoftwareRenderer :
-#ifdef __HAIKU__
public QWidget,
-#else
- public QWindow,
-#endif
public RendererCommon {
Q_OBJECT
public:
explicit SoftwareRenderer(QWidget *parent = nullptr);
-#ifdef __HAIKU__
void paintEvent(QPaintEvent *event) override;
-#endif
+#ifdef __HAIKU__
void exposeEvent(QExposeEvent *event) override;
+#else
+ void exposeEvent(QExposeEvent *event);
+#endif
std::vector> getBuffers() override;
diff --git a/src/qt/qt_vulkanwindowrenderer.cpp b/src/qt/qt_vulkanwindowrenderer.cpp
index 79dbc8f87..ce6b464ee 100644
--- a/src/qt/qt_vulkanwindowrenderer.cpp
+++ b/src/qt/qt_vulkanwindowrenderer.cpp
@@ -32,6 +32,8 @@
****************************************************************************/
#include "qt_vulkanwindowrenderer.hpp"
+#include
+#include
#include
#include
@@ -46,6 +48,8 @@
extern "C" {
# include <86box/86box.h>
+# include <86box/path.h>
+# include <86box/plat.h>
# include <86box/video.h>
}
# if 0
@@ -861,6 +865,8 @@ VulkanWindowRenderer::event(QEvent *event)
return res;
}
+extern void take_screenshot_clipboard_monitor(int sx, int sy, int sw, int sh, int i);
+
void
VulkanWindowRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
{
@@ -873,6 +879,39 @@ VulkanWindowRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
this->pixelRatio = devicePixelRatio();
onResize(this->width(), this->height());
}
+
+ if (monitors[r_monitor_index].mon_screenshots) {
+ char path[1024];
+ char fn[256];
+
+ memset(fn, 0, sizeof(fn));
+ memset(path, 0, sizeof(path));
+
+ path_append_filename(path, usr_path, SCREENSHOT_PATH);
+
+ if (!plat_dir_check(path))
+ plat_dir_create(path);
+
+ path_slash(path);
+ strcat(path, "Monitor_");
+ snprintf(&path[strlen(path)], 42, "%d_", r_monitor_index + 1);
+
+ plat_tempfile(fn, NULL, (char *) ".png");
+ strcat(path, fn);
+
+ QImage image = this->grab();
+ image.save(path, "png");
+ monitors[r_monitor_index].mon_screenshots--;
+ }
+ if (monitors[r_monitor_index].mon_screenshots_clipboard) {
+ QImage image = this->grab();
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setImage(image, QClipboard::Clipboard);
+ monitors[r_monitor_index].mon_screenshots_clipboard--;
+ }
+ if (monitors[r_monitor_index].mon_screenshots_raw_clipboard) {
+ take_screenshot_clipboard_monitor(x, y, w, h, r_monitor_index);
+ }
}
uint32_t
diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc
index dda79c0b3..4b069cb3f 100644
--- a/src/qt_resources.qrc
+++ b/src/qt_resources.qrc
@@ -71,6 +71,10 @@
qt/icons/interpreter.ico
qt/icons/recompiler.ico
qt/icons/new_vm.ico
+ qt/icons/take_screenshot.ico
+ qt/icons/take_raw_screenshot.ico
+ qt/icons/copy_screenshot.ico
+ qt/icons/copy_raw_screenshot.ico
qt/icons/warning.ico
diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c
index 8d3a71002..fdd31d901 100644
--- a/src/unix/unix_sdl.c
+++ b/src/unix/unix_sdl.c
@@ -156,7 +156,7 @@ sdl_blit_shim(int x, int y, int w, int h, int monitor_index)
for (int row = 0; row < h; ++row)
video_copy(&(((uint8_t *) pixeldata)[row * 2048 * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t));
- if (monitors[monitor_index].mon_screenshots)
+ if (monitors[monitor_index].mon_screenshots_raw)
video_screenshot((uint32_t *) pixeldata, 0, 0, 2048);
blitreq = 1;
diff --git a/src/video/video.c b/src/video/video.c
index 4c4256a89..c1d096270 100644
--- a/src/video/video.c
+++ b/src/video/video.c
@@ -376,7 +376,7 @@ video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, int row_len, i
video_take_screenshot_monitor((const char *) path, buf, start_x, start_y, row_len, monitor_index);
png_destroy_write_struct(&png_ptr[monitor_index], &info_ptr[monitor_index]);
- atomic_fetch_sub(&monitors[monitor_index].mon_screenshots, 1);
+ atomic_fetch_sub(&monitors[monitor_index].mon_screenshots_raw, 1);
}
void
@@ -814,6 +814,9 @@ video_monitor_init(int index)
monitors[index].mon_vid_type = VIDEO_FLAG_TYPE_NONE;
atomic_init(&doresize_monitors[index], 0);
atomic_init(&monitors[index].mon_screenshots, 0);
+ atomic_init(&monitors[index].mon_screenshots_clipboard, 0);
+ atomic_init(&monitors[index].mon_screenshots_raw, 0);
+ atomic_init(&monitors[index].mon_screenshots_raw_clipboard, 0);
if (index >= 1)
ui_init_monitor(index);
monitors[index].mon_blit_data_ptr->blit_thread = thread_create(blit_thread, monitors[index].mon_blit_data_ptr);