diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h index 4f23867..ed8830e 100644 --- a/binding-mri/binding-util.h +++ b/binding-mri/binding-util.h @@ -91,7 +91,12 @@ raiseRbExc(const Exception &exc); template static VALUE classAllocate(VALUE klass) { +/* 2.3 has changed the name of this function */ +#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 3 return rb_data_typed_object_wrap(klass, 0, rbType); +#else + return rb_data_typed_object_alloc(klass, 0, rbType); +#endif } template diff --git a/binding-mri/journal-binding.cpp b/binding-mri/journal-binding.cpp index 25bb4fe..a577a14 100644 --- a/binding-mri/journal-binding.cpp +++ b/binding-mri/journal-binding.cpp @@ -48,13 +48,19 @@ int server_thread(void *data) } CloseHandle(pipe); #else - if (FILE *file = fopen(PIPE_PATH, "r")) { + if (FILE *file = fopen(PIPE_PATH, "r")) + { fclose(file); out_pipe = open(PIPE_PATH, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); SDL_LockMutex(mutex); active = true; if (message_len > 0) - write(out_pipe, (char*)message_buffer, message_len); + { + if (write(out_pipe, (char*)message_buffer, message_len) == -1) + { + Debug() << "Failure writing to journal's pipe!"; + } + } SDL_UnlockMutex(mutex); } return 0; diff --git a/binding-mri/niko-binding.cpp b/binding-mri/niko-binding.cpp index 288e737..5b7a47c 100644 --- a/binding-mri/niko-binding.cpp +++ b/binding-mri/niko-binding.cpp @@ -80,7 +80,12 @@ int niko_server_thread(void *data) SDL_LockMutex(mutex); active = true; if (message_len > 0) - write(out_pipe, (char*)message_buffer, message_len); + { + if (write(out_pipe, (char*)message_buffer, message_len) == -1) + { + Debug() << "Failed to write to pipe!"; + } + } SDL_UnlockMutex(mutex); } return 0; @@ -89,6 +94,8 @@ int niko_server_thread(void *data) RB_METHOD(nikoPrepare) { + RB_UNUSED_PARAM; + // Prime native window info syswm::SDL_SysWMinfo syswindow; SDL_VERSION(&syswindow.version); @@ -99,12 +106,14 @@ RB_METHOD(nikoPrepare) std::string journal; // Get current path - getcwd(path, sizeof(path)); + if (getcwd(path, sizeof(path)) == NULL) { + return Qnil; + } #ifdef OS_OSX - journal = std::string(path) + std::string("/_______.app/Contents/MacOS/_______"); + journal = std::string(path) + "/_______.app/Contents/MacOS/_______"; #else - journal = std::string(path) + std::string("_______"); + journal = std::string(path) + "_______"; #endif // Run the binary diff --git a/binding-mri/oneshot-binding.cpp b/binding-mri/oneshot-binding.cpp index fc253a6..b305dc9 100644 --- a/binding-mri/oneshot-binding.cpp +++ b/binding-mri/oneshot-binding.cpp @@ -108,6 +108,9 @@ void oneshotBindingInit() // Constants rb_const_set(module, rb_intern("OS"), rb_str_new2(shState->oneshot().os().c_str())); + #ifdef __linux__ + rb_const_set(module, rb_intern("DE"), rb_str_new2(shState->oneshot().desktopEnv.c_str())); + #endif rb_const_set(module, rb_intern("USER_NAME"), rb_str_new2(shState->oneshot().userName().c_str())); rb_const_set(module, rb_intern("SAVE_PATH"), rb_str_new2(shState->oneshot().savePath().c_str())); rb_const_set(module, rb_intern("DOCS_PATH"), rb_str_new2(shState->oneshot().docsPath().c_str())); diff --git a/binding-mri/wallpaper-binding.cpp b/binding-mri/wallpaper-binding.cpp index eec109e..f21b14f 100644 --- a/binding-mri/wallpaper-binding.cpp +++ b/binding-mri/wallpaper-binding.cpp @@ -1,4 +1,10 @@ +#include #include +#include +#include +#include + +#include #include "etc.h" #include "sharedstate.h" @@ -6,6 +12,7 @@ #include "binding-types.h" #include "config.h" #include "oneshot.h" +#include "debugwriter.h" #ifdef _WIN32 #include @@ -23,7 +30,7 @@ #include "mac-desktop.h" static bool isCached = false; #else - #include + #include #include #include #include @@ -32,7 +39,7 @@ #include static std::string desktop = "uninitialized"; // GNOME settings - static Glib::RefPtr bgsetting; + static GSettings *bgsetting; static std::string defPictureURI, defPictureOptions, defPrimaryColor, defColorShading; // XFCE settings static XfconfChannel* bgchannel; @@ -41,47 +48,122 @@ static GValue defColor = G_VALUE_INIT; static bool defColorExists; static std::string optionImage, optionColor, optionImageStyle, optionColorStyle; + // KDE settings + static std::map defPlugins, defPictures, defColors, defModes; + static std::map defBlurs; + // Fallback settings + static std::string fallbackPath; #endif #endif #ifdef __linux__ -void desktopEnvironmentInit() -{ - if (desktop != "uninitialized") { - return; - } - desktop = shState->oneshot().desktopEnv; - if (desktop == "gnome" || desktop == "mate") { - if (desktop == "gnome") { - bgsetting = Gio::Settings::create("org.gnome.desktop.background"); - defPictureURI = bgsetting->get_string("picture-uri"); - } else { - bgsetting = Gio::Settings::create("org.mate.background"); - defPictureURI = bgsetting->get_string("picture-filename"); + void desktopEnvironmentInit() + { + if (desktop != "uninitialized") { + return; } - defPictureOptions = bgsetting->get_string("picture-options"); - defPrimaryColor = bgsetting->get_string("primary-color"); - defColorShading = bgsetting->get_string("color-shading-type"); - } else if (desktop == "xfce") { - GError *xferror = NULL; - if (xfconf_init(&xferror)) { - bgchannel = xfconf_channel_get("xfce4-desktop"); - std::string optionPrefix = "/backdrop/screen0/monitor0/workspace0/"; - optionImage = optionPrefix + "last-image"; - optionColor = optionPrefix + "color1"; - optionImageStyle = optionPrefix + "image-style"; - optionColorStyle = optionPrefix + "color-style"; - defPictureURI = xfconf_channel_get_string(bgchannel, optionImage.c_str(), ""); - defPictureStyle = xfconf_channel_get_int(bgchannel, optionImageStyle.c_str(), -1); - defColorExists = xfconf_channel_get_property(bgchannel, optionColor.c_str(), &defColor); - defColorStyle = xfconf_channel_get_int(bgchannel, optionColorStyle.c_str(), -1); + desktop = shState->oneshot().desktopEnv; + if (desktop == "cinnamon" || desktop == "gnome" || desktop == "mate" || desktop == "deepin") { + if (desktop == "cinnamon" || desktop == "gnome" || desktop == "deepin") { + if (desktop == "cinnamon") bgsetting = g_settings_new("org.cinnamon.desktop.background"); + else if (desktop == "deepin") bgsetting = g_settings_new("com.deepin.wrap.gnome.desktop.background"); + else bgsetting = g_settings_new("org.gnome.desktop.background"); + defPictureURI = g_settings_get_string(bgsetting, "picture-uri"); + } else { + bgsetting = g_settings_new("org.mate.background"); + defPictureURI = g_settings_get_string(bgsetting, "picture-filename"); + } + defPictureOptions = g_settings_get_string(bgsetting, "picture-options"); + defPrimaryColor = g_settings_get_string(bgsetting, "primary-color"); + defColorShading = g_settings_get_string(bgsetting, "color-shading-type"); + } else if (desktop == "xfce") { + GError *xferror = NULL; + if (xfconf_init(&xferror)) { + bgchannel = xfconf_channel_get("xfce4-desktop"); + std::string optionPrefix = "/backdrop/screen0/monitor0/workspace0/"; + optionImage = optionPrefix + "last-image"; + optionColor = optionPrefix + "color1"; + optionImageStyle = optionPrefix + "image-style"; + optionColorStyle = optionPrefix + "color-style"; + defPictureURI = xfconf_channel_get_string(bgchannel, optionImage.c_str(), ""); + defPictureStyle = xfconf_channel_get_int(bgchannel, optionImageStyle.c_str(), -1); + defColorExists = xfconf_channel_get_property(bgchannel, optionColor.c_str(), &defColor); + defColorStyle = xfconf_channel_get_int(bgchannel, optionColorStyle.c_str(), -1); + } else { + // Configuration failed to initialize, we won't set the wallpaper + desktop = "xfce_error"; + g_error_free(xferror); + } + } else if (desktop == "kde") { + std::ifstream configFile; + configFile.open(std::string(getenv("HOME")) + "/.config/plasma-org.kde.plasma.desktop-appletsrc", std::ios::in); + if (configFile.is_open()) { + std::string line; + std::vector sections; + std::size_t undefined = 999999999; + bool readPlugin = false, readOther = false; + std::string containment; + while (getline(configFile, line)) { + std::size_t index = undefined, lastIndex = undefined; + if (line.size() == 0) { + readPlugin = false; + readOther = false; + } else if (readPlugin) { + index = line.find('='); + if (line.substr(0, index) == "wallpaperplugin") { + defPlugins[containment] = line.substr(index + 1); + } + } else if (readOther) { + index = line.find('='); + std::string key = line.substr(0, index); + std::string val = line.substr(index + 1); + if (key == "Image") { + defPictures[containment] = val; + } else if (key == "Color") { + defColors[containment] = val; + } else if (key == "FillMode") { + defModes[containment] = val; + } else if (key == "Blur") { + defBlurs[containment] = (val == "true"); + } + } else if (line.at(0) == '[') { + sections.clear(); + while (true) { + index = line.find(lastIndex == undefined ? '[' : ']', index == undefined ? 0 : index); + if (index == std::string::npos) { + break; + } + if (lastIndex == undefined) { + lastIndex = index; + } else { + sections.push_back(line.substr(lastIndex + 1, index - lastIndex - 1)); + lastIndex = undefined; + } + } + if (sections.size() == 2 && sections[0] == "Containments") { + readPlugin = true; + containment = sections[1]; + } else if ( + sections.size() == 5 && + sections[0] == "Containments" && + sections[2] == "Wallpaper" && + sections[3] == "org.kde.image" && + sections[4] == "General" + ) { + readOther = true; + containment = sections[1]; + } + } + } + configFile.close(); + } else { + Debug() << "FATAL: Cannot find desktop configuration!"; + desktop = "kde_error"; + } } else { - // Configuration failed to initialize, we won't set the wallpaper - desktop = "xfce_error"; - g_error_free(xferror); + fallbackPath = std::string(getenv("HOME")) + "/Desktop/hint.png"; } } -} #endif RB_METHOD(wallpaperSet) @@ -93,7 +175,7 @@ RB_METHOD(wallpaperSet) std::string path; #ifdef _WIN32 path = shState->config().gameFolder + "\\Wallpaper\\" + name + ".bmp"; - std::cout << "Setting wallpaper to " << path << std::endl; + Debug() << "Setting wallpaper to" << path; // Crapify the slashes size_t index = 0; for (;;) { @@ -168,7 +250,7 @@ end: } path = "/Wallpaper/" + nameFix + ".png"; - std::cout << "Setting wallpaper to " << path << std::endl; + Debug() << "Setting wallpaper to " << path; #ifdef __APPLE__ if (!isCached) { @@ -183,17 +265,17 @@ end: } std::string gameDirStr(gameDir); desktopEnvironmentInit(); - if (desktop == "gnome" || desktop == "mate") { + if (desktop == "cinnamon" || desktop == "gnome" || desktop == "mate" || desktop == "deepin") { std::stringstream hexColor; hexColor << "#" << std::hex << color; - if (desktop == "gnome") { - bgsetting->set_string("picture-uri", "file://" + gameDirStr + path); + g_settings_set_string(bgsetting, "picture-options", "scaled"); + g_settings_set_string(bgsetting, "primary-color", hexColor.str().c_str()); + g_settings_set_string(bgsetting, "color-shading-type", "solid"); + if (desktop == "cinnamon" || desktop == "gnome" || desktop == "deepin") { + g_settings_set_string(bgsetting, "picture-uri", ("file://" + gameDirStr + path).c_str()); } else { - bgsetting->set_string("picture-filename", gameDirStr + path); + g_settings_set_string(bgsetting, "picture-filename", (gameDirStr + path).c_str()); } - bgsetting->set_string("picture-options", "scaled"); - bgsetting->set_string("primary-color", hexColor.str()); - bgsetting->set_string("color-shading-type", "solid"); } else if (desktop == "xfce") { int r = (color >> 16) & 0xFF; int g = (color >> 8) & 0xFF; @@ -219,7 +301,7 @@ end: colorArrType = g_type_from_name("GPtrArray_GValue_"); if (!colorArrType) { // Let's do some debug output here and skip changing the color - std::cout << "WALLPAPER ERROR: xfconf-query call returned" << colorCommandRes; + Debug() << "WALLPAPER ERROR: xfconf-query call returned" << colorCommandRes; return Qnil; } } @@ -242,6 +324,35 @@ end: g_ptr_array_add(colorArr, va); g_value_set_boxed(&colorValue, colorArr); xfconf_channel_set_property(bgchannel, optionColor.c_str(), &colorValue); + } else if (desktop == "kde") { + std::stringstream command; + std::string concatPath(gameDirStr + path); + boost::replace_all(concatPath, "\\", "\\\\"); + boost::replace_all(concatPath, "\"", "\\\""); + boost::replace_all(concatPath, "'", "\\x27"); + command << "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string:" << + "var allDesktops = desktops();" << + "for (var i = 0, l = allDesktops.length; i < l; ++i) {" << + "var d = allDesktops[i];" << + "d.wallpaperPlugin = \"org.kde.image\";" << + "d.currentConfigGroup = [\"Wallpaper\", \"org.kde.image\", \"General\"];" << + "d.writeConfig(\"Image\", \"file://" << concatPath << "\");" << + "d.writeConfig(\"FillMode\", \"6\");" << + "d.writeConfig(\"Blur\", false);" << + "d.writeConfig(\"Color\", [\"" << + std::to_string((color >> 16) & 0xFF) << "\", \"" << + std::to_string((color >> 8) & 0xFF) << "\", \"" << + std::to_string(color & 0xFF) << + "\"]);" << + "}" << + "'"; + Debug() << "Wallpaper command:" << command.str(); + int result = system(command.str().c_str()); + Debug() << "Result:" << result; + } else { + std::ifstream srcHint(gameDirStr + path); + std::ofstream dstHint(fallbackPath); + dstHint << srcHint.rdbuf(); } #endif #endif @@ -281,15 +392,15 @@ RB_METHOD(wallpaperReset) MacDesktop::ResetBackground(); #else desktopEnvironmentInit(); - if (desktop == "gnome" || desktop == "mate") { - if (desktop == "gnome") { - bgsetting->set_string("picture-uri", defPictureURI); + if (desktop == "cinnamon" || desktop == "gnome" || desktop == "mate" || desktop == "deepin") { + if (desktop == "cinnamon" || desktop == "gnome" || desktop == "deepin") { + g_settings_set_string(bgsetting, "picture-uri", defPictureURI.c_str()); } else { - bgsetting->set_string("picture-filename", defPictureURI); + g_settings_set_string(bgsetting, "picture-filename", defPictureURI.c_str()); } - bgsetting->set_string("picture-options", defPictureOptions); - bgsetting->set_string("primary-color", defPrimaryColor); - bgsetting->set_string("color-shading-type", defColorShading); + g_settings_set_string(bgsetting, "picture-options", defPictureOptions.c_str()); + g_settings_set_string(bgsetting, "primary-color", defPrimaryColor.c_str()); + g_settings_set_string(bgsetting, "color-shading-type", defColorShading.c_str()); } else if (desktop == "xfce") { if (defColorExists) { xfconf_channel_set_property(bgchannel, optionColor.c_str(), &defColor); @@ -311,6 +422,60 @@ RB_METHOD(wallpaperReset) } else { xfconf_channel_set_int(bgchannel, optionColorStyle.c_str(), defColorStyle); } + } else if (desktop == "kde") { + std::stringstream command; + command << "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string:" << + "var allDesktops = desktops();" << + "var data = {"; + // Plugin, picture, color, mode, blur + for (auto const& x : defPlugins) { + command << "\"" + x.first + "\": {" + << "plugin: \"" << x.second << "\""; + if (defPictures.find(x.first) != defPictures.end()) { + std::string picture = defPictures[x.first]; + boost::replace_all(picture, "\\", "\\\\"); + boost::replace_all(picture, "\"", "\\\""); + boost::replace_all(picture, "'", "\\x27"); + command << ", picture: \"" << picture << "\""; + } + if (defColors.find(x.first) != defColors.end()) { + command << ", color: \"" << defColors[x.first] << "\""; + } + if (defModes.find(x.first) != defModes.end()) { + command << ", mode: \"" << defModes[x.first] << "\""; + } + if (defBlurs.find(x.first) != defBlurs.end() && defBlurs[x.first]) { + command << ", blur: true"; + } + command << "},"; + } + command << "\"no\": {}};" << + "for (var i = 0, l = allDesktops.length; i < l; ++i) {" << + "var d = allDesktops[i];" << + "var dat = data[d.id];" << + "d.wallpaperPlugin = dat.plugin;" << + "d.currentConfigGroup = [\"Wallpaper\", \"org.kde.image\", \"General\"];" << + "if (dat.picture) {" << + "d.writeConfig(\"Image\", dat.picture);" << + "}" << + "if (dat.color) {" << + "d.writeConfig(\"Color\", dat.color.split(\",\"));" << + "}" << + "if (dat.mode) {" << + "d.writeConfig(\"FillMode\", dat.mode);" << + "}" << + "if (dat.blur) {" << + "d.writeConfig(\"Blur\", dat.blur);" << + "}" << + "}" << + "'"; + Debug() << "Reset wallpaper command:" << command.str(); + int result = system(command.str().c_str()); + Debug() << "Reset result:" << result; + } else { + if (remove(fallbackPath.c_str()) != 0) { + Debug() << "Failed to delete hint.png!"; + } } #endif #endif diff --git a/journal/unix/images/icon.png b/journal/unix/images/icon.png new file mode 100644 index 0000000..41a1cfd Binary files /dev/null and b/journal/unix/images/icon.png differ diff --git a/make-oneshot-linux.sh b/make-oneshot-linux.sh index 93ea5bc..a6e8ce7 100755 --- a/make-oneshot-linux.sh +++ b/make-oneshot-linux.sh @@ -19,7 +19,7 @@ echo "${white}Compiling ${bold}SyngleChance v${linux_version} ${white}engine for # Generate makefile and build main + journal echo "-> ${cyan}Generate makefile...${color_reset}" -qmake +qmake -qt=5 echo "-> ${cyan}Compile engine...${color_reset}" make -j${make_threads} echo "-> ${cyan}Compile steamshim...${color_reset}" diff --git a/mkxp.pro b/mkxp.pro index 4d81a50..b1223db 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -48,7 +48,7 @@ unix { } !macx: { QMAKE_CXXFLAGS += -g - PKGCONFIG += giomm-2.4 gtk+-3.0 gdk-3.0 libxfconf-0 + PKGCONFIG += gtk+-3.0 gdk-3.0 libxfconf-0 INCLUDEPATH += /usr/include/AL /usr/local/include/AL LIBS += -lX11 } diff --git a/scripts/Script.rb b/scripts/Script.rb index f3bbc5f..1426470 100644 --- a/scripts/Script.rb +++ b/scripts/Script.rb @@ -2,6 +2,8 @@ PROTO_TEXT = "put me in the big portal" CEDRIC_TEXT = "put me in the big portal" RUE_TEXT = "put me in the big portal" +SUPPORTED_DE = ["cinnamon", "gnome", "mate", "kde", "xfce"] + module Script def self.px logpos($game_player.x, $game_player.real_x, $game_player.direction == 6) @@ -373,26 +375,43 @@ module Script end def self.copy_journal + # If the required directories don't exist, create them Dir.mkdir(Oneshot::GAME_PATH) unless File.exists?(Oneshot::GAME_PATH) Dir.mkdir(Oneshot::GAME_PATH + "/Oneshot") unless File.exists?(Oneshot::GAME_PATH + "/Oneshot") - begin - if File.file?(Oneshot::JOURNAL) - File.open(Oneshot::JOURNAL, "rb") do |input| - File.open(Oneshot::GAME_PATH + "/Oneshot/" + Oneshot::JOURNAL, "wb") do |output| - while buff = input.read(4096) - output.write(buff) + begin + # If we're on a supported Linux DE, make a .desktop file + # so the clover icon can be properly shown + if Oneshot::OS == "linux" and SUPPORTED_DE.include? Oneshot::DE + path = "#{Oneshot::GAME_PATH}/Oneshot/#{Oneshot::JOURNAL}.desktop" + File.open(path, "wb") do |output| + output.write("[Desktop Entry]\n") + output.write("Comment=...\n") + output.write("Terminal=false\n") + output.write("Name=_______\n") + output.write("Exec=#{Dir.pwd}/#{Oneshot::JOURNAL}\n") + output.write("Type=Application\n") + output.write("Icon=#{Dir.pwd}/images/icon.png\n") + end + File.chmod(0777, path) + # If the journal is a file, copy it to Documents + elsif File.file?(Oneshot::JOURNAL) + File.open(Oneshot::JOURNAL, "rb") do |input| + File.open("#{Oneshot::GAME_PATH}/Oneshot/#{Oneshot::JOURNAL}", "wb") do |output| + while buff = input.read(4096) + output.write(buff) + end end end + # If the journal isn't a file, symlink it + else + File.symlink "#{Dir.pwd}/#{Oneshot::JOURNAL}", "#{Oneshot::GAME_PATH}/Oneshot/#{Oneshot::JOURNAL}" end - else - File.symlink Dir.pwd + "/" + Oneshot::JOURNAL, Oneshot::GAME_PATH + "/Oneshot/" + Oneshot::JOURNAL + rescue Errno::EACCES => e + # this probably means the clover.exe already exists and is running, so no need to create it again + rescue Errno::EEXIST => e + # this means that the journal file already exists, so no need to create it again end - rescue Errno::EACCES => e - #this probably means the clover.exe already exists and is running, so no need to create it again - rescue Errno::EEXIST => e - #this means that the journal file already exists, so no need to create it again - end - if File.exists?("README.txt") + if File.exists?("README.txt") File.open("README.txt", "rb") do |input| File.open(Oneshot::GAME_PATH + "/Oneshot/README.txt","wb") do |output| while buff = input.read(4096) @@ -400,7 +419,7 @@ module Script end end end - end + end end def self.create_boxes diff --git a/src/alstream.cpp b/src/alstream.cpp index d423953..9746061 100644 --- a/src/alstream.cpp +++ b/src/alstream.cpp @@ -78,9 +78,11 @@ void ALStream::close() case Playing: case Paused: stopStream(); + /* falls through */ case Stopped: closeSource(); state = Closed; + /* falls through */ case Closed: return; } @@ -95,8 +97,10 @@ void ALStream::open(const std::string &filename) case Playing: case Paused: stopStream(); + /* falls through */ case Stopped: closeSource(); + /* falls through */ case Closed: openSource(filename); } diff --git a/src/audiostream.cpp b/src/audiostream.cpp index 5302497..72b9642 100644 --- a/src/audiostream.cpp +++ b/src/audiostream.cpp @@ -119,9 +119,11 @@ void AudioStream::play(const std::string &filename, case ALStream::Paused : case ALStream::Playing : stream.stop(); + /* falls through */ case ALStream::Stopped : if (diffFile) stream.close(); + /* falls through */ case ALStream::Closed : if (diffFile) { diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 63bbf76..400cdd0 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -166,7 +166,6 @@ void EventThread::process(RGSSThreadData &rtData) char buffer[128]; char pendingTitle[128]; - bool havePendingTitle = false; bool resetting = false; @@ -330,8 +329,6 @@ void EventThread::process(RGSSThreadData &rtData) /* Prevent fullscreen flicker */ strncpy(pendingTitle, rtData.config.windowTitle.c_str(), sizeof(pendingTitle)); - havePendingTitle = true; - break; } @@ -458,6 +455,7 @@ void EventThread::process(RGSSThreadData &rtData) case SDL_FINGERDOWN : i = event.tfinger.fingerId; touchState.fingers[i].down = true; + /* falls through */ case SDL_FINGERMOTION : i = event.tfinger.fingerId; @@ -510,8 +508,6 @@ void EventThread::process(RGSSThreadData &rtData) if (fullscreen) { strncpy(pendingTitle, buffer, sizeof(pendingTitle)); - havePendingTitle = true; - break; } @@ -598,14 +594,6 @@ int EventThread::eventFilter(void *data, SDL_Event *event) return 0; } return 1; - -// case SDL_RENDER_TARGETS_RESET : -// Debug() << "****** SDL_RENDER_TARGETS_RESET"; -// return 0; - -// case SDL_RENDER_DEVICE_RESET : -// Debug() << "****** SDL_RENDER_DEVICE_RESET"; -// return 0; } return 1; diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 0ffd3a6..3165d0a 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -503,26 +503,6 @@ fontSetEnumCB (void *data, const char *dir, const char *fname) return PHYSFS_ENUM_OK; } -/* Basically just a case-insensitive search - * for the folder "Fonts"... */ -static PHYSFS_EnumerateCallbackResult -findFontsFolderCB(void *data, const char *, const char *fname) -{ - size_t i = 0; - char buffer[512]; - const char *s = fname; - - while (*s && i < sizeof(buffer)) - buffer[i++] = tolower(*s++); - - buffer[i] = '\0'; - - if (strcmp(buffer, "fonts") == 0) - PHYSFS_enumerate(fname, fontSetEnumCB, data); - - return PHYSFS_ENUM_OK; -} - void FileSystem::initFontSets(SharedFontState &sfs) { FontSetsCBData d = { p, &sfs }; diff --git a/src/i18n.cpp b/src/i18n.cpp index f293c87..f882162 100644 --- a/src/i18n.cpp +++ b/src/i18n.cpp @@ -1,8 +1,7 @@ /* - Really hacked-together naiive implementation of gettext + Really hacked-together naiive implementation of gettext */ #include "i18n.h" -#include "debugwriter.h" #include #include @@ -13,74 +12,76 @@ const char* LOC_HEADER = "ONELOC\x10"; char** strdict = 0; unsigned int nStr = 0; int family = LOCALE_FAMILY_LATIN; +size_t readSize; int getLocaleFamily() { - Debug() << "Get family:" << family; - return family; + return family; } const char* findtext(unsigned int msgid, const char* fallback) { - Debug() << "Looking for msg" << msgid << fallback; - if (msgid >= nStr) { - return fallback; - } else { - Debug() << "found" << strdict[msgid]; - return strdict[msgid]; - } + if (msgid >= nStr) { + return fallback; + } else { + return strdict[msgid]; + } } void unloadLocale() { - for (unsigned int i = 0; i < nStr; i++) { - free(strdict[i]); - } - free(strdict); - strdict = 0; - nStr = 0; + for (unsigned int i = 0; i < nStr; i++) { + free(strdict[i]); + } + free(strdict); + strdict = 0; + nStr = 0; } void _setLocaleFamily(const char* locale) { - if (!strcmp(locale, "ja") - || !strcmp(locale, "ko") - || !strcmp(locale, "zh_CN")) { - family = LOCALE_FAMILY_ASIAN; - } else { - family = LOCALE_FAMILY_LATIN; - } + if (!strcmp(locale, "ja") + || !strcmp(locale, "ko") + || !strcmp(locale, "zh_CN")) { + family = LOCALE_FAMILY_ASIAN; + } else { + family = LOCALE_FAMILY_LATIN; + } +} + +void _read(void * ptr, size_t size, size_t count, FILE * stream) { + readSize = fread(ptr, size, count, stream); + if (readSize != count) { + } } void loadLocale(const char* locale) { - Debug() << "Load locale:" << locale; - char pathbuf[100]; - FILE* locfile; - char header[8]; - unsigned int i; - int strSize = 0; + char pathbuf[100]; + FILE* locfile; + char header[8]; + unsigned int i; + int strSize = 0; - unloadLocale(); + unloadLocale(); - _setLocaleFamily(locale); + _setLocaleFamily(locale); - sprintf(pathbuf, "Languages/internal/%s.loc", locale); - locfile = fopen(pathbuf, "rb"); - if (locfile) { - fread(header, 1, 8, locfile); - if (!strcmp(header, LOC_HEADER)) { - //read number of strs in this file - fread(&nStr, 4, 1, locfile); - strdict = (char**)malloc(sizeof(char*) * nStr); - for (i = 0; i < nStr; i++) { - //read the size of the next string - fread(&strSize, 4, 1, locfile); - strdict[i] = (char*)malloc(strSize+1); - if (strSize > 0) { - //read the contents of the next string - fread(strdict[i], 1, strSize, locfile); - strdict[i][strSize] = 0; - Debug() << "localization #" << i << " : " << strdict[i] << "|" << strSize; - } - strdict[i][strSize] = 0; - } - } - fclose(locfile); - } + sprintf(pathbuf, "Languages/internal/%s.loc", locale); + locfile = fopen(pathbuf, "rb"); + if (locfile) { + _read(header, 1, 8, locfile); + if (!strcmp(header, LOC_HEADER)) { + // Read number of strs in this file + _read(&nStr, 4, 1, locfile); + strdict = (char**)malloc(sizeof(char*) * nStr); + for (i = 0; i < nStr; i++) { + // Read the size of the next string + _read(&strSize, 4, 1, locfile); + strdict[i] = (char*)malloc(strSize+1); + if (strSize > 0) { + // Read the contents of the next string + _read(strdict[i], 1, strSize, locfile); + strdict[i][strSize] = 0; + } + strdict[i][strSize] = 0; + } + } + fclose(locfile); + } } diff --git a/src/main.cpp b/src/main.cpp index 0533e0a..f60552c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -200,6 +200,7 @@ int main(int argc, char *argv[]) SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1"); + SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); /* initialize SDL first */ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) diff --git a/src/oneshot.cpp b/src/oneshot.cpp index 01e56fd..9824f06 100644 --- a/src/oneshot.cpp +++ b/src/oneshot.cpp @@ -13,7 +13,7 @@ #include #include -//OS-Specific code +// OS-Specific code #if defined _WIN32 #define OS_W32 #define WIN32_LEAN_AND_MEAN @@ -124,7 +124,7 @@ static int linux_dialog(void *rawData) } // Display dialog and get result - GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, gtktype, gtkbuttons, data->body); + GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, gtktype, gtkbuttons, "%s", data->body); gtk_window_set_title(GTK_WINDOW(dialog), data->title); int result = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); @@ -269,7 +269,7 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : } // Get documents path - std::string path = std::string(getenv("HOME")) + std::string("/Documents"); + std::string path = std::string(getenv("HOME")) + "/Documents"; p->docsPath = path.c_str(); p->gamePath = path.c_str(); #ifdef OS_OSX @@ -279,11 +279,13 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : #endif #endif -#ifdef __linux__ +#ifdef OS_LINUX std::string desktop(getenv("XDG_CURRENT_DESKTOP")); std::transform(desktop.begin(), desktop.end(), desktop.begin(), ::tolower); - if ( - desktop.find("cinnamon") != std::string::npos || + if (desktop.find("cinnamon") != std::string::npos) { + desktopEnv = "cinnamon"; + gtk_init(0, 0); + } else if ( desktop.find("gnome") != std::string::npos || desktop.find("unity") != std::string::npos ) { @@ -294,6 +296,13 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : gtk_init(0, 0); } else if (desktop.find("xfce") != std::string::npos) { desktopEnv = "xfce"; + gtk_init(0, 0); + } else if (desktop.find("kde") != std::string::npos) { + desktopEnv = "kde"; + } else if (desktop.find("lxde") != std::string::npos) { + desktopEnv = "lxde"; + } else if (desktop.find("deepin") != std::string::npos) { + desktopEnv = "deepin"; } #endif @@ -471,7 +480,12 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) if (!title) title = ""; #if defined OS_LINUX - if (desktopEnv == "gnome" || desktopEnv == "mate") { + if ( + desktopEnv == "gnome" || + desktopEnv == "mate" || + desktopEnv == "cinnamon" || + desktopEnv == "xfce" + ) { linux_DialogData data = {type, body, title, 0}; gdk_threads_add_idle(linux_dialog, &data); gtk_main(); @@ -479,16 +493,15 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) } #endif - //SDL message box - - //Button data + // SDL message box + // Button data static const SDL_MessageBoxButtonData buttonOk = {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "OK"}; static const SDL_MessageBoxButtonData buttonsOk[] = {buttonOk}; SDL_MessageBoxButtonData buttonYes = {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, p->txtYes.c_str()}; SDL_MessageBoxButtonData buttonNo = {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, p->txtNo.c_str()}; SDL_MessageBoxButtonData buttonsYesNo[] = {buttonNo, buttonYes}; - //Messagebox data + // Messagebox data SDL_MessageBoxData data; data.window = NULL;//p->window; data.colorScheme = 0; @@ -523,7 +536,7 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) break; } - //Set buttons + // Set buttons switch (type) { case MSG_INFO: @@ -539,7 +552,7 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) break; } - //Show messagebox + // Show messagebox #ifdef OS_W32 PlaySoundW((LPCWSTR)sound, NULL, SND_ALIAS_ID | SND_ASYNC); #endif @@ -580,20 +593,6 @@ std::string Oneshot::textinput(const char* prompt, int char_limit, const char* f // Disable text input SDL_StopTextInput(); - // //Free loaded images - // gPromptTextTexture.free(); - // gInputTextTexture.free(); - - // //Free global font - // TTF_CloseFont(gFont); - // gFont = NULL; - - // //Destroy renderer - // SDL_DestroyRenderer(gRenderer); - // gRenderer = NULL; - // delete promptBmp; - // delete inputBmp; - return threadData.inputText; } diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index d889f03..4489690 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -35,7 +35,6 @@ #include "util.h" #include "sharedstate.h" #include "i18n.h" -#include "debugwriter.h" #include @@ -539,7 +538,6 @@ struct SettingsMenuPrivate int x, int y, int alignW, Justification just, SDL_Color c, bool bold = false) { - Debug() << "draw text:" << str; SDL_Surface *txt = createTextSurface(str, c, bold); if (txt) { blitTextSurf(surf, x, y, alignW, txt, just); diff --git a/steamshim/steamshim_child.c b/steamshim/steamshim_child.c index eb2fd3c..7f9ce6e 100644 --- a/steamshim/steamshim_child.c +++ b/steamshim/steamshim_child.c @@ -28,7 +28,9 @@ typedef int PipeType; #ifdef STEAMSHIM_DEBUG #define dbgpipe printf #else -static inline void dbgpipe(const char *fmt, ...) {} +static inline void dbgpipe(const char *fmt, ...) { + (void)fmt; +} #endif static int writePipe(PipeType fd, const void *buf, const unsigned int _len); diff --git a/steamshim_parent/Makefile b/steamshim_parent/Makefile index ed7a476..0b0c355 100644 --- a/steamshim_parent/Makefile +++ b/steamshim_parent/Makefile @@ -20,7 +20,7 @@ FLAGS += -lsteam_api ifeq ($(DEBUG),1) FLAGS += -DSTEAMSHIM_DEBUG -else +else ifeq ($(HOST),w32) FLAGS += -mwindows endif diff --git a/steamshim_parent/README.md b/steamshim_parent/README.md new file mode 100644 index 0000000..5bda2c5 --- /dev/null +++ b/steamshim_parent/README.md @@ -0,0 +1,22 @@ +# Steamshim parent +OneShot uses [steamshim](https://hg.icculus.org/icculus/steamshim/) for GNU GPL v3 and Steam interoperability. There are five components that OneShot uses to communicate with Steam, in order: +1. Steamworks SDK (that can be obtained from [here](https://partner.steamgames.com)) that is used for directly communicating with Steam. It is closed-source, and because of license compatibility issues steamshim must be used as a layer between OneShot and Steamworks SDK to communicate with Steam. +2. steamshim parent (whose source is within this folder) is a separate application that will start up the main OneShot application and can communicate with the Steamworks SDK. +3. steamshim child (whose source is inside the `steamshim` folder) is the client used to communicate with the steamshim parent from the OneShot application through pipes. +4. Steam controller inside OneShot application (`src/steam.cpp`) controls the communication between OneShot and steamshim components. +5. Steam binding (`binding-mri/steam-binding.cpp`) creates Ruby objects so Steam functionalities (like achievements) can be controlled from the game's scripts/events and passes on the handling to the Steam controller + +## Building +Download Steamworks SDK from [here](https://partner.steamgames.com) and run +```console +$ export LD_LIBRARY_PATH=/path/to/steamworks/sdk/redistributable_bin/platform +$ STEAMWORKS=/path/to/steamworks/sdk HOST=platform make +``` +inside this directory, where `platform` can be `win64`, `osx32`, `linux64` or `linux32` + +If you need debug output from the steamshim parent, compile with `DEBUG=1` in command-line arguments for `make`. + +## Running +After building the steamshim parent, place it in the same directory as the OneShot application. Note that the OneShot application **must be named "oneshot"**. Changing the case ("OneShot") will make the game not launch. + +To run the game with the Steam wrapper, run the steamshim parent. diff --git a/steamshim_parent/steamshim_parent.cpp b/steamshim_parent/steamshim_parent.cpp index d6550bb..b4baee3 100644 --- a/steamshim_parent/steamshim_parent.cpp +++ b/steamshim_parent/steamshim_parent.cpp @@ -30,7 +30,9 @@ typedef int PipeType; #ifdef STEAMSHIM_DEBUG #define dbgpipe printf #else -static inline void dbgpipe(const char *fmt, ...) {} +static inline void dbgpipe(const char *fmt, ...) { + (void)fmt; +} #endif /* platform-specific mainline calls this. */ @@ -245,6 +247,7 @@ static bool launchChild(ProcessType *pid) // we're the child. GArgv[0] = strdup("./" GAME_LAUNCH_NAME); + dbgpipe("Starting %s\n", GArgv[0]); execvp(GArgv[0], GArgv); // still here? It failed! Terminate, closing child's ends of the pipes. _exit(1);