diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index 087b7fe..cac6683 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -75,6 +75,9 @@ void fileIntBindingInit(); void journalBindingInit(); void wallpaperBindingInit(); +#ifdef __linux__ +void wallpaperBindingTerminate(); +#endif void nikoBindingInit(); void oneshotBindingInit(); void steamBindingInit(); @@ -621,6 +624,9 @@ static void mriBindingExecute() static void mriBindingTerminate() { rb_raise(rb_eSystemExit, " "); +#ifdef __linux__ + wallpaperBindingTerminate(); +#endif } static void mriBindingReset() diff --git a/binding-mri/oneshot-binding.cpp b/binding-mri/oneshot-binding.cpp index a420dec..b933a36 100644 --- a/binding-mri/oneshot-binding.cpp +++ b/binding-mri/oneshot-binding.cpp @@ -10,37 +10,36 @@ RB_METHOD(oneshotSetYesNo) { - RB_UNUSED_PARAM; - const char *yes; - const char *no; - rb_get_args(argc, argv, "zz", &yes, &no RB_ARG_END); - shState->oneshot().setYesNo(yes, no); - return Qnil; + RB_UNUSED_PARAM; + const char *yes; + const char *no; + rb_get_args(argc, argv, "zz", &yes, &no RB_ARG_END); + shState->oneshot().setYesNo(yes, no); + return Qnil; } RB_METHOD(oneshotMsgBox) { - RB_UNUSED_PARAM; - int type; - VALUE body; - VALUE title = Qnil; - rb_get_args(argc, argv, "iS|S", &type, &body, &title RB_ARG_END); + RB_UNUSED_PARAM; + int type; + VALUE body; + VALUE title = Qnil; + rb_get_args(argc, argv, "iS|S", &type, &body, &title RB_ARG_END); std::string bodyStr = std::string(RSTRING_PTR(body), RSTRING_LEN(body)); std::string titleStr = (title == Qnil) ? "" : std::string(RSTRING_PTR(title), RSTRING_LEN(title)); - return rb_bool_new(shState->oneshot().msgbox(type, bodyStr.c_str(), titleStr.c_str())); + return rb_bool_new(shState->oneshot().msgbox(type, bodyStr.c_str(), titleStr.c_str())); } RB_METHOD(oneshotTextInput) { - // const char* prompt, int char_limit, const char* font - RB_UNUSED_PARAM; - VALUE prompt; - int char_limit = 100; - VALUE font = Qnil; - rb_get_args(argc, argv, "S|iS", &prompt, &char_limit, &font RB_ARG_END); - std::string promptStr = std::string(RSTRING_PTR(prompt), RSTRING_LEN(prompt)); - std::string fontStr = (font == Qnil) ? "" : std::string(RSTRING_PTR(font), RSTRING_LEN(font)); - return rb_str_new2(shState->oneshot().textinput(promptStr.c_str(), char_limit, fontStr.c_str()).c_str()); + RB_UNUSED_PARAM; + VALUE prompt; + int char_limit = 100; + VALUE font = Qnil; + rb_get_args(argc, argv, "S|iS", &prompt, &char_limit, &font RB_ARG_END); + std::string promptStr = std::string(RSTRING_PTR(prompt), RSTRING_LEN(prompt)); + std::string fontStr = (font == Qnil) ? "" : std::string(RSTRING_PTR(font), RSTRING_LEN(font)); + return rb_str_new2(shState->oneshot().textinput(promptStr.c_str(), char_limit, fontStr.c_str()).c_str()); } RB_METHOD(oneshotResetObscured) @@ -67,11 +66,11 @@ RB_METHOD(oneshotAllowExit) RB_METHOD(oneshotExiting) { - RB_UNUSED_PARAM; - bool exiting; - rb_get_args(argc, argv, "b", &exiting RB_ARG_END); - shState->oneshot().setExiting(exiting); - return Qnil; + RB_UNUSED_PARAM; + bool exiting; + rb_get_args(argc, argv, "b", &exiting RB_ARG_END); + shState->oneshot().setExiting(exiting); + return Qnil; } RB_METHOD(oneshotShake) @@ -79,52 +78,54 @@ RB_METHOD(oneshotShake) RB_UNUSED_PARAM; int absx, absy; SDL_GetWindowPosition(shState->rtData().window, &absx, &absy); + int state; srand(time(NULL)); for (int i = 0; i < 60; ++i) { int max = 60 - i; int x = rand() % (max * 2) - max; int y = rand() % (max * 2) - max; SDL_SetWindowPosition(shState->rtData().window, absx + x, absy + y); + rb_eval_string_protect("sleep 0.02", &state); } return Qnil; } RB_METHOD(oneshotCRC32) { - RB_UNUSED_PARAM; - VALUE string; - boost::crc_32_type result; - rb_get_args(argc, argv, "S", &string RB_ARG_END); - std::string str = std::string(RSTRING_PTR(string), RSTRING_LEN(string)); - result.process_bytes(str.data(), str.length()); - return UINT2NUM(result.checksum()); + RB_UNUSED_PARAM; + VALUE string; + boost::crc_32_type result; + rb_get_args(argc, argv, "S", &string RB_ARG_END); + std::string str = std::string(RSTRING_PTR(string), RSTRING_LEN(string)); + result.process_bytes(str.data(), str.length()); + return UINT2NUM(result.checksum()); } void oneshotBindingInit() { - VALUE module = rb_define_module("Oneshot"); - VALUE msg = rb_define_module_under(module, "Msg"); + VALUE module = rb_define_module("Oneshot"); + VALUE msg = rb_define_module_under(module, "Msg"); - //Constants - 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())); + // Constants + 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())); rb_const_set(module, rb_intern("GAME_PATH"), rb_str_new2(shState->oneshot().gamePath().c_str())); rb_const_set(module, rb_intern("JOURNAL"), rb_str_new2(shState->oneshot().journal().c_str())); - rb_const_set(module, rb_intern("LANG"), rb_str_new2(shState->oneshot().lang().c_str())); - rb_const_set(msg, rb_intern("INFO"), INT2FIX(Oneshot::MSG_INFO)); - rb_const_set(msg, rb_intern("YESNO"), INT2FIX(Oneshot::MSG_YESNO)); - rb_const_set(msg, rb_intern("WARN"), INT2FIX(Oneshot::MSG_WARN)); - rb_const_set(msg, rb_intern("ERR"), INT2FIX(Oneshot::MSG_ERR)); + rb_const_set(module, rb_intern("LANG"), rb_str_new2(shState->oneshot().lang().c_str())); + rb_const_set(msg, rb_intern("INFO"), INT2FIX(Oneshot::MSG_INFO)); + rb_const_set(msg, rb_intern("YESNO"), INT2FIX(Oneshot::MSG_YESNO)); + rb_const_set(msg, rb_intern("WARN"), INT2FIX(Oneshot::MSG_WARN)); + rb_const_set(msg, rb_intern("ERR"), INT2FIX(Oneshot::MSG_ERR)); - //Functions - _rb_define_module_function(module, "set_yes_no", oneshotSetYesNo); - _rb_define_module_function(module, "msgbox", oneshotMsgBox); - _rb_define_module_function(module, "textinput", oneshotTextInput); + // Functions + _rb_define_module_function(module, "set_yes_no", oneshotSetYesNo); + _rb_define_module_function(module, "msgbox", oneshotMsgBox); + _rb_define_module_function(module, "textinput", oneshotTextInput); _rb_define_module_function(module, "reset_obscured", oneshotResetObscured); _rb_define_module_function(module, "obscured_cleared?", oneshotObscuredCleared); - _rb_define_module_function(module, "allow_exit", oneshotAllowExit); + _rb_define_module_function(module, "allow_exit", oneshotAllowExit); _rb_define_module_function(module, "exiting", oneshotExiting); - _rb_define_module_function(module, "shake", oneshotShake); + _rb_define_module_function(module, "shake", oneshotShake); _rb_define_module_function(module, "crc32", oneshotCRC32); } diff --git a/binding-mri/wallpaper-binding.cpp b/binding-mri/wallpaper-binding.cpp index 2b4013f..eec109e 100644 --- a/binding-mri/wallpaper-binding.cpp +++ b/binding-mri/wallpaper-binding.cpp @@ -5,8 +5,7 @@ #include "binding-util.h" #include "binding-types.h" #include "config.h" - -static bool isCached = false; +#include "oneshot.h" #ifdef _WIN32 #include @@ -18,42 +17,95 @@ static bool isCached = false; static DWORD szTileSize = sizeof(szTile) - 1; static bool setStyle = false; static bool setTile = false; + static bool isCached = false; #else #ifdef __APPLE__ #include "mac-desktop.h" + static bool isCached = false; #else #include + #include #include + #include + #include + #include #include - Glib::RefPtr bgsetting = Gio::Settings::create("org.gnome.desktop.background"); - std::string defPictureURI = bgsetting->get_string("picture-uri"); - std::string defPictureOptions = bgsetting->get_string("picture-options"); - std::string defPrimaryColor = bgsetting->get_string("primary-color"); + static std::string desktop = "uninitialized"; + // GNOME settings + static Glib::RefPtr bgsetting; + static std::string defPictureURI, defPictureOptions, defPrimaryColor, defColorShading; + // XFCE settings + static XfconfChannel* bgchannel; + static int defPictureStyle; + static int defColorStyle; + static GValue defColor = G_VALUE_INIT; + static bool defColorExists; + static std::string optionImage, optionColor, optionImageStyle, optionColorStyle; #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"); + } + 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); + } else { + // Configuration failed to initialize, we won't set the wallpaper + desktop = "xfce_error"; + g_error_free(xferror); + } + } +} +#endif + RB_METHOD(wallpaperSet) { RB_UNUSED_PARAM; - const char *iname; + const char *name; int color; - rb_get_args(argc, argv, "zi", &iname, &color RB_ARG_END); - std::string imageName = iname; - std::string imgname = shState->config().gameFolder + "/Wallpaper/" + imageName + ".bmp"; + rb_get_args(argc, argv, "zi", &name, &color RB_ARG_END); + std::string path; #ifdef _WIN32 - std::cout << "Setting wallpaper to " << imgname << std::endl; + path = shState->config().gameFolder + "\\Wallpaper\\" + name + ".bmp"; + std::cout << "Setting wallpaper to " << path << std::endl; // Crapify the slashes size_t index = 0; for (;;) { - index = imgname.find("/", index); + index = path.find("/", index); if (index == std::string::npos) break; - imgname.replace(index, 1, "\\"); + path.replace(index, 1, "\\"); index += 1; } WCHAR imgnameW[MAX_PATH]; WCHAR imgnameFull[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, imgname.c_str(), -1, imgnameW, MAX_PATH); + MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, imgnameW, MAX_PATH); GetFullPathNameW(imgnameW, MAX_PATH, imgnameFull, NULL); @@ -109,29 +161,87 @@ end: if (hKey) RegCloseKey(hKey); #else - std::size_t found = imageName.find("w32"); - if (found != std::string::npos) imageName.replace(imageName.end()-3, imageName.end(), "unix"); - imgname = shState->config().gameFolder + "/Wallpaper/" + imageName + ".png"; + std::string nameFix(name); + std::size_t found = nameFix.find("w32"); + if (found != std::string::npos) { + nameFix.replace(nameFix.end()-3, nameFix.end(), "unix"); + } + path = "/Wallpaper/" + nameFix + ".png"; - std::cout << "Setting wallpaper to " << imgname << std::endl; + std::cout << "Setting wallpaper to " << path << std::endl; #ifdef __APPLE__ if (!isCached) { MacDesktop::CacheCurrentBackground(); isCached = true; } - MacDesktop::ChangeBackground(imgname, ((color >> 16) & 0xFF) / 255.0, ((color >> 8) & 0xFF) / 255.0, ((color) & 0xFF) / 255.0); + MacDesktop::ChangeBackground(shState->config().gameFolder + path, ((color >> 16) & 0xFF) / 255.0, ((color >> 8) & 0xFF) / 255.0, (color & 0xFF) / 255.0); #else - char gameDir[1024]; - if (getcwd(gameDir, sizeof(gameDir)) != NULL) { - std::string gameDirStr(gameDir); - std::stringstream hexColor; - hexColor << "#" << std::hex << color; - bgsetting->set_string("picture-uri", "file://" + gameDirStr + "/Wallpaper/" + imageName + ".png"); + char gameDir[PATH_MAX]; + if (getcwd(gameDir, sizeof(gameDir)) == NULL) { + return Qnil; + } + std::string gameDirStr(gameDir); + desktopEnvironmentInit(); + if (desktop == "gnome" || desktop == "mate") { + std::stringstream hexColor; + hexColor << "#" << std::hex << color; + if (desktop == "gnome") { + bgsetting->set_string("picture-uri", "file://" + gameDirStr + path); + } else { + bgsetting->set_string("picture-filename", gameDirStr + path); + } bgsetting->set_string("picture-options", "scaled"); bgsetting->set_string("primary-color", hexColor.str()); - } else { - // Error handling? + bgsetting->set_string("color-shading-type", "solid"); + } else if (desktop == "xfce") { + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + unsigned int ur = r * 256 + r; + unsigned int ug = g * 256 + g; + unsigned int ub = b * 256 + b; + unsigned int alpha = 65535; + std::string concatPath(gameDirStr + path); + xfconf_channel_set_string(bgchannel, optionImage.c_str(), concatPath.c_str()); + xfconf_channel_set_int(bgchannel, optionColorStyle.c_str(), 0); + xfconf_channel_set_int(bgchannel, optionImageStyle.c_str(), 4); + GValue colorValue = G_VALUE_INIT; + GPtrArray *colorArr = g_ptr_array_sized_new(4); + GType colorArrType = g_type_from_name("GPtrArray_GValue_"); + if (!colorArrType) { + std::stringstream colorCommand; + colorCommand << "xfconf-query -c xfce4-desktop -n -p " << optionColor + << " -t uint -t uint -t uint -t uint -s " << ub + << " -s " << ug << " -s " << ub << " -s " << alpha; + int colorCommandRes = system(colorCommand.str().c_str()); + defColorExists = xfconf_channel_get_property(bgchannel, optionColor.c_str(), &defColor); + 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; + return Qnil; + } + } + g_value_init(&colorValue, colorArrType); + GValue *vr = g_new0(GValue, 1); + GValue *vg = g_new0(GValue, 1); + GValue *vb = g_new0(GValue, 1); + GValue *va = g_new0(GValue, 1); + g_value_init(vr, G_TYPE_UINT); + g_value_init(vg, G_TYPE_UINT); + g_value_init(vb, G_TYPE_UINT); + g_value_init(va, G_TYPE_UINT); + g_value_set_uint(vr, ur); + g_value_set_uint(vg, ug); + g_value_set_uint(vb, ub); + g_value_set_uint(va, alpha); + g_ptr_array_add(colorArr, vr); + g_ptr_array_add(colorArr, vg); + g_ptr_array_add(colorArr, vb); + g_ptr_array_add(colorArr, va); + g_value_set_boxed(&colorValue, colorArr); + xfconf_channel_set_property(bgchannel, optionColor.c_str(), &colorValue); } #endif #endif @@ -170,9 +280,38 @@ RB_METHOD(wallpaperReset) #ifdef __APPLE__ MacDesktop::ResetBackground(); #else - bgsetting->set_string("picture-uri", defPictureURI); - bgsetting->set_string("picture-options", defPictureOptions); - bgsetting->set_string("primary-color", defPrimaryColor); + desktopEnvironmentInit(); + if (desktop == "gnome" || desktop == "mate") { + if (desktop == "gnome") { + bgsetting->set_string("picture-uri", defPictureURI); + } else { + bgsetting->set_string("picture-filename", defPictureURI); + } + bgsetting->set_string("picture-options", defPictureOptions); + bgsetting->set_string("primary-color", defPrimaryColor); + bgsetting->set_string("color-shading-type", defColorShading); + } else if (desktop == "xfce") { + if (defColorExists) { + xfconf_channel_set_property(bgchannel, optionColor.c_str(), &defColor); + } else { + xfconf_channel_reset_property(bgchannel, optionColor.c_str(), false); + } + if (defPictureURI == "") { + xfconf_channel_reset_property(bgchannel, optionImage.c_str(), false); + } else { + xfconf_channel_set_string(bgchannel, optionImage.c_str(), defPictureURI.c_str()); + } + if (defPictureStyle == -1) { + xfconf_channel_reset_property(bgchannel, optionImageStyle.c_str(), false); + } else { + xfconf_channel_set_int(bgchannel, optionImageStyle.c_str(), defPictureStyle); + } + if (defColorStyle == -1) { + xfconf_channel_reset_property(bgchannel, optionColorStyle.c_str(), false); + } else { + xfconf_channel_set_int(bgchannel, optionColorStyle.c_str(), defColorStyle); + } + } #endif #endif return Qnil; @@ -186,3 +325,14 @@ void wallpaperBindingInit() _rb_define_module_function(module, "set", wallpaperSet); _rb_define_module_function(module, "reset", wallpaperReset); } + +#ifdef __linux__ +void wallpaperBindingTerminate() +{ + // Clean up + // We assume Gio::Settings destructor will be automatically called + if (desktop == "xfce") { + xfconf_shutdown(); + } +} +#endif diff --git a/mkxp.pro b/mkxp.pro index 33385c0..4d81a50 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -47,9 +47,9 @@ unix { SOURCES += src/mac-desktop.mm } !macx: { - PKGCONFIG += giomm-2.4 + QMAKE_CXXFLAGS += -g + PKGCONFIG += giomm-2.4 gtk+-3.0 gdk-3.0 libxfconf-0 INCLUDEPATH += /usr/include/AL /usr/local/include/AL - SOURCES += src/xdg-user-dir-lookup.c LIBS += -lX11 } } diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 1af1864..63bbf76 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -277,7 +277,7 @@ void EventThread::process(RGSSThreadData &rtData) #ifdef __APPLE__ case SDL_WINDOWEVENT_MOVED: - if (event.window.data1 && event.window.data2) + if (shState != NULL && event.window.data1 && event.window.data2) shState->oneshot().setWindowPos(event.window.data1, event.window.data2); break; #endif @@ -586,11 +586,11 @@ int EventThread::eventFilter(void *data, SDL_Event *event) Debug() << "SDL_APP_LOWMEMORY"; return 0; - /* Workaround for Windows pausing on drag */ + /* Workaround for Windows pausing on drag */ case SDL_WINDOWEVENT: if (event->window.event == SDL_WINDOWEVENT_MOVED) { - if (shState->rgssVersion > 0) + if (shState != NULL && shState->rgssVersion > 0) { shState->oneshot().setWindowPos(event->window.data1, event->window.data2); shState->graphics().update(false); diff --git a/src/oneshot.cpp b/src/oneshot.cpp index 9ab2449..98c350f 100644 --- a/src/oneshot.cpp +++ b/src/oneshot.cpp @@ -33,44 +33,11 @@ #define OS_OSX #else #define OS_LINUX - - class GtkWidget; - - typedef enum - { - GTK_MESSAGE_INFO, - GTK_MESSAGE_WARNING, - GTK_MESSAGE_QUESTION, - GTK_MESSAGE_ERROR - } GtkMessageType; - - typedef enum - { - GTK_BUTTONS_NONE, - GTK_BUTTONS_OK, - GTK_BUTTONS_CLOSE, - GTK_BUTTONS_CANCEL, - GTK_BUTTONS_YES_NO, - GTK_BUTTONS_OK_CANCEL - } GtkButtonsType; - - typedef enum - { - GTK_RESPONSE_NONE = -1, - GTK_RESPONSE_REJECT = -2, - GTK_RESPONSE_ACCEPT = -3, - GTK_RESPONSE_DELETE_EVENT = -4, - GTK_RESPONSE_OK = -5, - GTK_RESPONSE_CANCEL = -6, - GTK_RESPONSE_CLOSE = -7, - GTK_RESPONSE_YES = -8, - GTK_RESPONSE_NO = -9, - GTK_RESPONSE_APPLY = -10, - GTK_RESPONSE_HELP = -11 - } GtkResponseType; + #include + #include #endif #else - #error "Operating system not detected." + #error "Operating system not detected." #endif #define DEF_SCREEN_W 640 @@ -78,10 +45,10 @@ struct OneshotPrivate { - //Main SDL window + // Main SDL window SDL_Window *window; - //String data + // String data std::string lang; std::string userName; std::string savePath; @@ -89,49 +56,29 @@ struct OneshotPrivate std::string gamePath; std::string journal; - //Dialog text + // Dialog text std::string txtYes; std::string txtNo; bool exiting; bool allowExit; - //Alpha texture data for portions of window obscured by screen edges + // Alpha texture data for portions of window obscured by screen edges int winX, winY; SDL_mutex *winMutex; bool winPosChanged; std::vector obscuredMap; bool obscuredCleared; -#if defined OS_LINUX - //GTK+ - void *libgtk; - void (*gtk_init)(int *argc, char ***argv); - GtkWidget *(*gtk_message_dialog_new)(void *parent, int flags, GtkMessageType type, GtkButtonsType buttons, const char *message_format, ...); - void (*gtk_window_set_title)(GtkWidget *window, const char *title); - GtkResponseType (*gtk_dialog_run)(GtkWidget *dialog); - void (*gtk_widget_destroy)(GtkWidget *widget); - void (*gtk_main_quit)(); - void (*gtk_main)(); - unsigned int (*gdk_threads_add_idle)(int (*function)(void *data), void *data); -#endif - OneshotPrivate() : window(0), winMutex(SDL_CreateMutex()) -#if defined OS_LINUX - ,libgtk(0) -#endif { } ~OneshotPrivate() { SDL_DestroyMutex(winMutex); -#ifdef OS_LINUX - if (libgtk) - dlclose(libgtk); -#endif } }; @@ -139,53 +86,51 @@ struct OneshotPrivate #if defined OS_LINUX struct linux_DialogData { - //Input - OneshotPrivate *p; + // Input int type; const char *body; const char *title; - //Output + // Output bool result; }; static int linux_dialog(void *rawData) { linux_DialogData *data = reinterpret_cast(rawData); - OneshotPrivate *p = data->p; - //Determine correct flags + // Determine correct flags GtkMessageType gtktype; GtkButtonsType gtkbuttons = GTK_BUTTONS_OK; switch (data->type) { - case Oneshot::MSG_INFO: - gtktype = GTK_MESSAGE_INFO; - break; - case Oneshot::MSG_YESNO: - gtktype = GTK_MESSAGE_QUESTION; - gtkbuttons = GTK_BUTTONS_YES_NO; - break; - case Oneshot::MSG_WARN: - gtktype = GTK_MESSAGE_WARNING; - break; - case Oneshot::MSG_ERR: - gtktype = GTK_MESSAGE_ERROR; - break; - default: - p->gtk_main_quit(); - return 0; + case Oneshot::MSG_INFO: + gtktype = GTK_MESSAGE_INFO; + break; + case Oneshot::MSG_YESNO: + gtktype = GTK_MESSAGE_QUESTION; + gtkbuttons = GTK_BUTTONS_YES_NO; + break; + case Oneshot::MSG_WARN: + gtktype = GTK_MESSAGE_WARNING; + break; + case Oneshot::MSG_ERR: + gtktype = GTK_MESSAGE_ERROR; + break; + default: + gtk_main_quit(); + return 0; } - //Display dialog and get result - GtkWidget *dialog = p->gtk_message_dialog_new(0, 0, gtktype, gtkbuttons, data->body); - p->gtk_window_set_title(dialog, data->title); - int result = p->gtk_dialog_run(dialog); - p->gtk_widget_destroy(dialog); + // Display dialog and get result + GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, gtktype, gtkbuttons, data->body); + gtk_window_set_title(GTK_WINDOW(dialog), data->title); + int result = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); - //Interpret result and return + // Interpret result and return data->result = (result == GTK_RESPONSE_OK || result == GTK_RESPONSE_YES); - p->gtk_main_quit(); + gtk_main_quit(); return 0; } #elif defined OS_W32 @@ -225,130 +170,6 @@ static WCHAR *w32_toWide(const char *str) } #endif -LTexture::LTexture() { - //Initialize - mTexture = NULL; - mWidth = 0; - mHeight = 0; -} - -LTexture::~LTexture() { - //Deallocate - free(); -} - -bool LTexture::loadFromFile(std::string path, SDL_Renderer *gRenderer) { - //Get rid of preexisting texture - free(); - - //The final texture - SDL_Texture *newTexture = NULL; - - //Load image at specified path - SDL_Surface *loadedSurface = IMG_Load(path.c_str()); - if (loadedSurface == NULL) { - printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError()); - } else { - //Color key image - SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF)); - - //Create texture from surface pixels - newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface); - if (newTexture == NULL) { - printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError()); - } else { - //Get image dimensions - mWidth = loadedSurface->w; - mHeight = loadedSurface->h; - } - - //Get rid of old loaded surface - SDL_FreeSurface(loadedSurface); - } - - //Return success - mTexture = newTexture; - return mTexture != NULL; -} - -#ifdef _SDL_TTF_H -bool LTexture::loadFromRenderedText(std::string textureText, SDL_Color textColor, SDL_Renderer *gRenderer, TTF_Font *gFont) { - //Get rid of preexisting texture - free(); - - //Render text surface - SDL_Surface *textSurface = TTF_RenderText_Solid(gFont, textureText.c_str(), textColor); - if (textSurface != NULL) { - //Create texture from surface pixels - mTexture = SDL_CreateTextureFromSurface(gRenderer, textSurface); - if (mTexture == NULL) { - printf("Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError()); - } else { - //Get image dimensions - mWidth = textSurface->w; - mHeight = textSurface->h; - } - - //Get rid of old surface - SDL_FreeSurface(textSurface); - } else { - printf("Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError()); - } - - - //Return success - return mTexture != NULL; -} -#endif - -void LTexture::free() { - //Free texture if it exists - if (mTexture != NULL) { - SDL_DestroyTexture(mTexture); - mTexture = NULL; - mWidth = 0; - mHeight = 0; - } -} - -void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue) { - //Modulate texture rgb - SDL_SetTextureColorMod(mTexture, red, green, blue); -} - -void LTexture::setBlendMode(SDL_BlendMode blending) { - //Set blending function - SDL_SetTextureBlendMode(mTexture, blending); -} - -void LTexture::setAlpha(Uint8 alpha) { - //Modulate texture alpha - SDL_SetTextureAlphaMod(mTexture, alpha); -} - -void LTexture::render(SDL_Renderer *gRenderer, int x, int y, SDL_Rect *clip, double angle, SDL_Point *center, - SDL_RendererFlip flip) { - //Set rendering space and render to screen - SDL_Rect renderQuad = {x, y, mWidth, mHeight }; - - //Set clip rendering dimensions - if (clip != NULL) { - renderQuad.w = clip->w; - renderQuad.h = clip->h; - } - - //Render to screen - SDL_RenderCopyEx(gRenderer, mTexture, clip, &renderQuad, angle, center, flip); -} - -int LTexture::getWidth() { - return mWidth; -} - -int LTexture::getHeight() { - return mHeight; -} - Oneshot::Oneshot(RGSSThreadData &threadData) : threadData(threadData) { @@ -399,20 +220,20 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : } } - //Get documents path + // Get documents path WCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, path); p->docsPath = w32_fromWide(path); p->gamePath = p->docsPath+"\\My Games"; p->journal = "_______.exe"; #else - //Get language code + // Get language code const char *lc_all = getenv("LC_ALL"); const char *lang = getenv("LANG"); const char *code = (lc_all ? lc_all : lang); if (code) { - //find first dot, copy language code + // find first dot, copy language code int end = 0; for (; code[end] && code[end] != '.'; ++end) {} p->lang = std::string(code, end); @@ -420,7 +241,7 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : else p->lang = "en"; - //Get user's name + // Get user's name #ifdef OS_OSX struct passwd *pwd = getpwuid(geteuid()); #elif defined OS_LINUX @@ -428,8 +249,8 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : #endif if (pwd) { - if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',') - { + if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',') + { //Get the user's full name int comma = 0; for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {} @@ -439,7 +260,7 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : p->userName = pwd->pw_name; } - //Get documents path + // Get documents path std::string path = std::string(getenv("HOME")) + std::string("/Documents"); p->docsPath = path.c_str(); p->gamePath = path.c_str(); @@ -450,56 +271,24 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : #endif #endif - /********** - * MSGBOX - **********/ -#ifdef OS_LINUX -#define LOAD_FUNC(name) *reinterpret_cast(&p->name) = dlsym(p->libgtk, #name) - //Attempt to link to gtk (prefer gtk2 over gtk3 until I can figure that message box icon out) - static const char *gtklibs[] = - { - "libgtk-x11-2.0.so", - "libgtk-3.0.so", - }; - - for (size_t i = 0; i < ARRAY_SIZE(gtklibs); ++i) - { - if (!(p->libgtk = dlopen("libgtk-x11-2.0.so", RTLD_NOW))) - p->libgtk = dlopen("libgtk-3.0.so", RTLD_NOW); - if (p->libgtk) - { - //Load functions - LOAD_FUNC(gtk_init); - LOAD_FUNC(gtk_message_dialog_new); - LOAD_FUNC(gtk_window_set_title); - LOAD_FUNC(gtk_dialog_run); - LOAD_FUNC(gtk_widget_destroy); - LOAD_FUNC(gtk_main_quit); - LOAD_FUNC(gtk_main); - LOAD_FUNC(gdk_threads_add_idle); - - if (p->gtk_init - && p->gtk_message_dialog_new - && p->gtk_window_set_title - && p->gtk_dialog_run - && p->gtk_widget_destroy - && p->gtk_main_quit - && p->gtk_main - && p->gdk_threads_add_idle) - { - p->gtk_init(0, 0); - } - else - { - dlclose(p->libgtk); - p->libgtk = 0; - } - } - if (p->libgtk) - break; +#ifdef __linux__ + std::string desktop(getenv("XDG_CURRENT_DESKTOP")); + std::transform(desktop.begin(), desktop.end(), desktop.begin(), ::tolower); + if ( + desktop.find("cinnamon") != std::string::npos || + desktop.find("gnome") != std::string::npos || + desktop.find("unity") != std::string::npos + ) { + desktopEnv = "gnome"; + gtk_init(0, 0); + } else if (desktop.find("mate") != std::string::npos) { + desktopEnv = "mate"; + gtk_init(0, 0); + } else if (desktop.find("xfce") != std::string::npos) { + desktopEnv = "xfce"; } -#undef LOAD_FUNC #endif + /******** * MISC ********/ @@ -668,51 +457,13 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) { if (!title) title = ""; -#if 0 - //Get native window handle - SDL_SysWMinfo wminfo; - SDL_version version; - SDL_VERSION(&version); - wminfo.version = version; - SDL_GetWindowWMInfo(p->window, &wminfo); - HWND hwnd = wminfo.info.win.window; - - //Construct flags - UINT flags = 0; - switch (type) - { - case MSG_INFO: - flags = MB_ICONINFORMATION; - break; - case MSG_YESNO: - flags = MB_ICONQUESTION | MB_YESNO; - break; - case MSG_WARN: - flags = MB_ICONWARNING; - break; - case MSG_ERR: - flags = MB_ICONERROR; - break; - } - - //Create message box - WCHAR *wbody = w32_toWide(body); - WCHAR *wtitle = w32_toWide(title); - int result = MessageBoxW(N, wbody, wtitle, flags); - delete [] title; - delete [] body; - - //Interpret result - return (result == IDOK || result == IDYES); -#else #if defined OS_LINUX - if (p->libgtk) - { - linux_DialogData data = {p, type, body, title, 0}; - p->gdk_threads_add_idle(linux_dialog, &data); - p->gtk_main(); - return data.result; - } + if (desktopEnv == "gnome" || desktopEnv == "mate") { + linux_DialogData data = {type, body, title, 0}; + gdk_threads_add_idle(linux_dialog, &data); + gtk_main(); + return data.result; + } #endif //SDL message box @@ -749,7 +500,7 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) data.flags = SDL_MESSAGEBOX_WARNING; #ifdef OS_W32 sound = SND_ALIAS_SYSTEMEXCLAMATION; - #endif +#endif break; case MSG_ERR: data.flags = SDL_MESSAGEBOX_WARNING; @@ -782,31 +533,9 @@ bool Oneshot::msgbox(int type, const char *body, const char *title) int button; SDL_ShowMessageBox(&data, &button); return button ? true : false; -#endif } std::string Oneshot::textinput(const char* prompt, int char_limit, const char* fontName) { - // SDL_Color textColor = {0xFF, 0xFF, 0xFF, 0xFF}; //Set text color as black - // SDL_Renderer *gRenderer = SDL_CreateRenderer(threadData.window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - // // SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF); - // LTexture gPromptTextTexture; - // LTexture gInputTextTexture; - - // //Open the font - // TTF_Font *gFont = TTF_OpenFont("VL-Gothic-Regular.ttf", 18); // XXX Implement font changing - // if (gFont == NULL) { - // printf("Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError()); - // // success = false; - // } else { - // //Render the prompt - // if (!gPromptTextTexture.loadFromRenderedText(prompt, textColor, gRenderer, gFont)) { - // printf("Failed to render prompt text!\n"); - // // success = false; - // } - // } - - // gInputTextTexture.loadFromRenderedText(threadData.inputText.c_str(), textColor, gRenderer, gFont); - std::vector *fontNames = new std::vector(); fontNames->push_back(fontName); fontNames->push_back("VL Gothic"); @@ -826,31 +555,16 @@ std::string Oneshot::textinput(const char* prompt, int char_limit, const char* f threadData.inputText.clear(); SDL_StartTextInput(); - //Main loop + // Main loop while (threadData.acceptingTextInput) { if (inputTextPrev != threadData.inputText) { inputBmp->clear(); inputBmp->drawText(DEF_SCREEN_W / 2, DEF_SCREEN_H / 2, DEF_SCREEN_W, DEF_SCREEN_H, threadData.inputText.c_str(), 1); inputTextPrev = threadData.inputText; - // if (threadData.inputText.length() > 0) gInputTextTexture.loadFromRenderedText(threadData.inputText.c_str(), textColor, gRenderer, gFont); - // else gInputTextTexture.loadFromRenderedText(" ", textColor, gRenderer, gFont); } - - // //Clear screen - // // SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF); - // SDL_RenderClear(gRenderer); - - // //Render text textures - // gPromptTextTexture.render(gRenderer, (DEF_SCREEN_W - gPromptTextTexture.getWidth()) / 2, - // (DEF_SCREEN_H / 2) - gPromptTextTexture.getHeight()); - // gInputTextTexture.render(gRenderer, (DEF_SCREEN_W - gInputTextTexture.getWidth()) / 2, - // (DEF_SCREEN_H / 2)); - - // //Update screen - // SDL_RenderPresent(gRenderer); } - //Disable text input + // Disable text input SDL_StopTextInput(); // //Free loaded images diff --git a/src/oneshot.h b/src/oneshot.h index 98a25d6..bc40a9a 100644 --- a/src/oneshot.h +++ b/src/oneshot.h @@ -11,52 +11,6 @@ struct OneshotPrivate; struct RGSSThreadData; -//Texture wrapper class -class LTexture { - public: - //Initializes variables - LTexture(); - - //Deallocates memory - ~LTexture(); - - //Loads image at specified path - bool loadFromFile(std::string path, SDL_Renderer *gRenderer); - - #ifdef _SDL_TTF_H - //Creates image from font string - bool loadFromRenderedText(std::string textureText, SDL_Color textColor, SDL_Renderer *gRenderer, TTF_Font *gFont); - #endif - - //Deallocates texture - void free(); - - //Set color modulation - void setColor(Uint8 red, Uint8 green, Uint8 blue); - - //Set blending - void setBlendMode(SDL_BlendMode blending); - - //Set alpha modulation - void setAlpha(Uint8 alpha); - - //Renders texture at given point - void render(SDL_Renderer *gRenderer, int x, int y, SDL_Rect *clip = NULL, double angle = 0.0, SDL_Point *center = NULL, - SDL_RendererFlip flip = SDL_FLIP_NONE); - - //Gets image dimensions - int getWidth(); - int getHeight(); - - private: - //The actual hardware texture - SDL_Texture *mTexture; - - //Image dimensions - int mWidth; - int mHeight; -}; - class Oneshot { public: @@ -120,6 +74,10 @@ public: //Dirty flag for obscured texture bool obscuredDirty; +#ifdef __linux__ + std::string desktopEnv; +#endif + private: OneshotPrivate *p; RGSSThreadData &threadData;