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);