diff options
Diffstat (limited to 'platform/x11')
-rw-r--r-- | platform/x11/SCsub | 13 | ||||
-rw-r--r-- | platform/x11/crash_handler_x11.cpp | 136 | ||||
-rw-r--r-- | platform/x11/crash_handler_x11.h | 47 | ||||
-rw-r--r-- | platform/x11/detect.py | 1 | ||||
-rw-r--r-- | platform/x11/export/export.cpp | 1 | ||||
-rw-r--r-- | platform/x11/joypad_linux.cpp | 1 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 63 | ||||
-rw-r--r-- | platform/x11/os_x11.h | 18 | ||||
-rw-r--r-- | platform/x11/power_x11.cpp | 42 | ||||
-rw-r--r-- | platform/x11/power_x11.h | 6 |
10 files changed, 254 insertions, 74 deletions
diff --git a/platform/x11/SCsub b/platform/x11/SCsub index fc9208c563..62717f3221 100644 --- a/platform/x11/SCsub +++ b/platform/x11/SCsub @@ -3,12 +3,13 @@ Import('env') -common_x11 = [\ - "context_gl_x11.cpp",\ - "os_x11.cpp",\ - "key_mapping_x11.cpp",\ - "joypad_linux.cpp",\ - "power_x11.cpp",\ +common_x11 = [ + "context_gl_x11.cpp", + "crash_handler_x11.cpp", + "os_x11.cpp", + "key_mapping_x11.cpp", + "joypad_linux.cpp", + "power_x11.cpp", ] env.Program('#bin/godot', ['godot_x11.cpp'] + common_x11) diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp new file mode 100644 index 0000000000..3c54d5cbc2 --- /dev/null +++ b/platform/x11/crash_handler_x11.cpp @@ -0,0 +1,136 @@ +/*************************************************************************/ +/* crash_handler_x11.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef DEBUG_ENABLED +#define CRASH_HANDLER_ENABLED 1 +#endif + +#include "main/main.h" +#include "os_x11.h" + +#ifdef CRASH_HANDLER_ENABLED +#include <cxxabi.h> +#include <dlfcn.h> +#include <execinfo.h> +#include <signal.h> +#include <stdlib.h> + +static void handle_crash(int sig) { + if (OS::get_singleton() == NULL) + return; + + void *bt_buffer[256]; + size_t size = backtrace(bt_buffer, 256); + String _execpath = OS::get_singleton()->get_executable_path(); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); + + // Dump the backtrace to stderr with a message to the user + fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); + fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str()); + char **strings = backtrace_symbols(bt_buffer, size); + if (strings) { + for (size_t i = 1; i < size; i++) { + char fname[1024]; + Dl_info info; + + snprintf(fname, 1024, "%s", strings[i]); + + // Try to demangle the function name to provide a more readable one + if (dladdr(bt_buffer[i], &info) && info.dli_sname) { + if (info.dli_sname[0] == '_') { + int status; + char *demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status); + + if (status == 0 && demangled) { + snprintf(fname, 1024, "%s", demangled); + } + + if (demangled) + free(demangled); + } + } + + List<String> args; + + char str[1024]; + snprintf(str, 1024, "%p", bt_buffer[i]); + args.push_back(str); + args.push_back("-e"); + args.push_back(_execpath); + + String output = ""; + + // Try to get the file/line number using addr2line + if (OS::get_singleton()) { + int ret; + Error err = OS::get_singleton()->execute(String("addr2line"), args, true, NULL, &output, &ret); + if (err == OK) { + output.erase(output.length() - 1, 1); + } + } + + fprintf(stderr, "[%ld] %s (%ls)\n", i, fname, output.c_str()); + } + + free(strings); + } + fprintf(stderr, "-- END OF BACKTRACE --\n"); + + // Abort to pass the error to the OS + abort(); +} +#endif + +CrashHandler::CrashHandler() { + disabled = false; +} + +CrashHandler::~CrashHandler() { +} + +void CrashHandler::disable() { + if (disabled) + return; + +#ifdef CRASH_HANDLER_ENABLED + signal(SIGSEGV, NULL); + signal(SIGFPE, NULL); + signal(SIGILL, NULL); +#endif + + disabled = true; +} + +void CrashHandler::initialize() { +#ifdef CRASH_HANDLER_ENABLED + signal(SIGSEGV, handle_crash); + signal(SIGFPE, handle_crash); + signal(SIGILL, handle_crash); +#endif +} diff --git a/platform/x11/crash_handler_x11.h b/platform/x11/crash_handler_x11.h new file mode 100644 index 0000000000..e01334cbf2 --- /dev/null +++ b/platform/x11/crash_handler_x11.h @@ -0,0 +1,47 @@ +/*************************************************************************/ +/* crash_handler_x11.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef CRASH_HANDLER_X11_H +#define CRASH_HANDLER_X11_H + +class CrashHandler { + + bool disabled; + +public: + void initialize(); + + void disable(); + bool is_disabled() const { return disabled; }; + + CrashHandler(); + ~CrashHandler(); +}; + +#endif diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 086681d4a4..d61175da60 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -87,6 +87,7 @@ def configure(env): elif (env["target"] == "debug"): env.Prepend(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + env.Append(LINKFLAGS=['-rdynamic']) ## Architecture diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp index 59b1a44247..fdb43c9ae0 100644 --- a/platform/x11/export/export.cpp +++ b/platform/x11/export/export.cpp @@ -50,6 +50,7 @@ void register_x11_exporter() { platform->set_release_64("linux_x11_64_release"); platform->set_debug_64("linux_x11_64_debug"); platform->set_os_name("X11"); + platform->set_chmod_flags(0755); EditorExport::get_singleton()->add_export_platform(platform); } diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp index 3453297716..428385f7cb 100644 --- a/platform/x11/joypad_linux.cpp +++ b/platform/x11/joypad_linux.cpp @@ -125,7 +125,6 @@ void JoypadLinux::enumerate_joypads(udev *p_udev) { enumerate = udev_enumerate_new(p_udev); udev_enumerate_add_match_subsystem(enumerate, "input"); - udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYPAD", "1"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 767ede8540..599c0d2278 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -93,6 +93,13 @@ const char *OS_X11::get_audio_driver_name(int p_driver) const { return AudioDriverManager::get_driver(p_driver)->get_name(); } +void OS_X11::initialize_core() { + + crash_handler.initialize(); + + OS_Unix::initialize_core(); +} + void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { long im_event_mask = 0; @@ -246,6 +253,11 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au // borderless fullscreen window mode if (current_videomode.fullscreen) { + // set bypass compositor hint + Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False); + unsigned long compositing_disable_on = 1; + XChangeProperty(x11_display, x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1); + // needed for lxde/openbox, possibly others Hints hints; Atom property; @@ -301,29 +313,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au XFree(xsh); } - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - audio_driver_index = p_audio_driver; - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - bool success = false; - audio_driver_index = -1; - for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { - if (i == p_audio_driver) - continue; - AudioDriverManager::get_driver(i)->set_singleton(); - if (AudioDriverManager::get_driver(i)->init() == OK) { - success = true; - print_line("Audio Driver Failed: " + String(AudioDriverManager::get_driver(p_audio_driver)->get_name())); - print_line("Using alternate audio driver: " + String(AudioDriverManager::get_driver(i)->get_name())); - audio_driver_index = i; - break; - } - } - if (!success) { - ERR_PRINT("Initializing audio failed."); - } - } + AudioDriverManager::initialize(p_audio_driver); ERR_FAIL_COND(!visual_server); ERR_FAIL_COND(x11_window == 0); @@ -623,7 +613,7 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { XFlush(x11_display); } -void OS_X11::warp_mouse_pos(const Point2 &p_to) { +void OS_X11::warp_mouse_position(const Point2 &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { @@ -695,6 +685,12 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) { xev.xclient.data.l[2] = 0; XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + // set bypass compositor hint + Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False); + unsigned long compositing_disable_on = p_enabled ? 1 : 0; + XChangeProperty(x11_display, x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1); + XFlush(x11_display); if (!p_enabled && !is_window_resizable()) { @@ -2159,7 +2155,7 @@ void OS_X11::set_context(int p_context) { } } -PowerState OS_X11::get_power_state() { +OS::PowerState OS_X11::get_power_state() { return power_manager->get_power_state(); } @@ -2171,11 +2167,15 @@ int OS_X11::get_power_percent_left() { return power_manager->get_power_percent_left(); } -OS_X11::OS_X11() { +void OS_X11::disable_crash_handler() { + crash_handler.disable(); +} -#ifdef RTAUDIO_ENABLED - AudioDriverManager::add_driver(&driver_rtaudio); -#endif +bool OS_X11::is_disable_crash_handler() const { + return crash_handler.is_disabled(); +} + +OS_X11::OS_X11() { #ifdef PULSEAUDIO_ENABLED AudioDriverManager::add_driver(&driver_pulseaudio); @@ -2185,11 +2185,6 @@ OS_X11::OS_X11() { AudioDriverManager::add_driver(&driver_alsa); #endif - if (AudioDriverManager::get_driver_count() == 0) { - WARN_PRINT("No sound driver found... Defaulting to dummy driver"); - AudioDriverManager::add_driver(&driver_dummy); - } - minimized = false; xim_style = 0L; mouse_mode = MOUSE_MODE_VISIBLE; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 51240fa023..a0338dacf1 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -31,17 +31,16 @@ #define OS_X11_H #include "context_gl_x11.h" +#include "crash_handler_x11.h" #include "drivers/unix/os_unix.h" #include "os/input.h" #include "servers/visual_server.h" //#include "servers/visual/visual_server_wrap_mt.h" #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" #include "joypad_linux.h" #include "main/input_default.h" #include "power_x11.h" -#include "servers/audio/audio_driver_dummy.h" #include "servers/audio_server.h" #include "servers/physics_2d/physics_2d_server_sw.h" #include "servers/physics_2d/physics_2d_server_wrap_mt.h" @@ -153,10 +152,6 @@ class OS_X11 : public OS_Unix { JoypadLinux *joypad; #endif -#ifdef RTAUDIO_ENABLED - AudioDriverRtAudio driver_rtaudio; -#endif - #ifdef ALSA_ENABLED AudioDriverALSA driver_alsa; #endif @@ -164,12 +159,13 @@ class OS_X11 : public OS_Unix { #ifdef PULSEAUDIO_ENABLED AudioDriverPulseAudio driver_pulseaudio; #endif - AudioDriverDummy driver_dummy; Atom net_wm_icon; PowerX11 *power_manager; + CrashHandler crash_handler; + int audio_driver_index; unsigned int capture_idle; bool maximized; @@ -191,6 +187,7 @@ protected: virtual int get_audio_driver_count() const; virtual const char *get_audio_driver_name(int p_driver) const; + virtual void initialize_core(); virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); @@ -204,7 +201,7 @@ public: void set_mouse_mode(MouseMode p_mode); MouseMode get_mouse_mode() const; - virtual void warp_mouse_pos(const Point2 &p_to); + virtual void warp_mouse_position(const Point2 &p_to); virtual Point2 get_mouse_position() const; virtual int get_mouse_button_state() const; virtual void set_window_title(const String &p_title); @@ -265,7 +262,7 @@ public: virtual void set_use_vsync(bool p_enable); virtual bool is_vsync_enabled() const; - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); @@ -273,6 +270,9 @@ public: void run(); + void disable_crash_handler(); + bool is_disable_crash_handler() const; + OS_X11(); }; diff --git a/platform/x11/power_x11.cpp b/platform/x11/power_x11.cpp index 32100354a6..76ff7f91fb 100644 --- a/platform/x11/power_x11.cpp +++ b/platform/x11/power_x11.cpp @@ -252,7 +252,7 @@ bool PowerX11::GetPowerInfo_Linux_proc_acpi() { this->nsecs_left = -1; this->percent_left = -1; - this->power_state = POWERSTATE_UNKNOWN; + this->power_state = OS::POWERSTATE_UNKNOWN; dirp->change_dir(proc_acpi_battery_path); Error err = dirp->list_dir_begin(); @@ -282,13 +282,13 @@ bool PowerX11::GetPowerInfo_Linux_proc_acpi() { } if (!have_battery) { - this->power_state = POWERSTATE_NO_BATTERY; + this->power_state = OS::POWERSTATE_NO_BATTERY; } else if (charging) { - this->power_state = POWERSTATE_CHARGING; + this->power_state = OS::POWERSTATE_CHARGING; } else if (have_ac) { - this->power_state = POWERSTATE_CHARGED; + this->power_state = OS::POWERSTATE_CHARGED; } else { - this->power_state = POWERSTATE_ON_BATTERY; + this->power_state = OS::POWERSTATE_ON_BATTERY; } return true; /* definitive answer. */ @@ -400,17 +400,17 @@ bool PowerX11::GetPowerInfo_Linux_proc_apm() { } if (battery_flag == 0xFF) { /* unknown state */ - this->power_state = POWERSTATE_UNKNOWN; + this->power_state = OS::POWERSTATE_UNKNOWN; } else if (battery_flag & (1 << 7)) { /* no battery */ - this->power_state = POWERSTATE_NO_BATTERY; + this->power_state = OS::POWERSTATE_NO_BATTERY; } else if (battery_flag & (1 << 3)) { /* charging */ - this->power_state = POWERSTATE_CHARGING; + this->power_state = OS::POWERSTATE_CHARGING; need_details = true; } else if (ac_status == 1) { - this->power_state = POWERSTATE_CHARGED; /* on AC, not charging. */ + this->power_state = OS::POWERSTATE_CHARGED; /* on AC, not charging. */ need_details = true; } else { - this->power_state = POWERSTATE_ON_BATTERY; + this->power_state = OS::POWERSTATE_ON_BATTERY; need_details = true; } @@ -445,7 +445,7 @@ bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, in return false; } - this->power_state = POWERSTATE_NO_BATTERY; /* assume we're just plugged in. */ + this->power_state = OS::POWERSTATE_NO_BATTERY; /* assume we're just plugged in. */ this->nsecs_left = -1; this->percent_left = -1; @@ -454,7 +454,7 @@ bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, in while (name != "") { bool choose = false; char str[64]; - PowerState st; + OS::PowerState st; int secs; int pct; @@ -475,17 +475,17 @@ bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, in /* some drivers don't offer this, so if it's not explicitly reported assume it's present. */ if (read_power_file(base, name.utf8().get_data(), "present", str, sizeof(str)) && (String(str) == "0\n")) { - st = POWERSTATE_NO_BATTERY; + st = OS::POWERSTATE_NO_BATTERY; } else if (!read_power_file(base, name.utf8().get_data(), "status", str, sizeof(str))) { - st = POWERSTATE_UNKNOWN; /* uh oh */ + st = OS::POWERSTATE_UNKNOWN; /* uh oh */ } else if (String(str) == "Charging\n") { - st = POWERSTATE_CHARGING; + st = OS::POWERSTATE_CHARGING; } else if (String(str) == "Discharging\n") { - st = POWERSTATE_ON_BATTERY; + st = OS::POWERSTATE_ON_BATTERY; } else if ((String(str) == "Full\n") || (String(str) == "Not charging\n")) { - st = POWERSTATE_CHARGED; + st = OS::POWERSTATE_CHARGED; } else { - st = POWERSTATE_UNKNOWN; /* uh oh */ + st = OS::POWERSTATE_UNKNOWN; /* uh oh */ } if (!read_power_file(base, name.utf8().get_data(), "capacity", str, sizeof(str))) { @@ -543,17 +543,17 @@ bool PowerX11::UpdatePowerInfo() { } PowerX11::PowerX11() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } PowerX11::~PowerX11() { } -PowerState PowerX11::get_power_state() { +OS::PowerState PowerX11::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } diff --git a/platform/x11/power_x11.h b/platform/x11/power_x11.h index e34223036d..7fc258bc0d 100644 --- a/platform/x11/power_x11.h +++ b/platform/x11/power_x11.h @@ -33,14 +33,14 @@ #include "os/dir_access.h" #include "os/file_access.h" -#include "os/power.h" +#include "os/os.h" class PowerX11 { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; FileAccessRef open_power_file(const char *base, const char *node, const char *key); bool read_power_file(const char *base, const char *node, const char *key, char *buf, size_t buflen); @@ -58,7 +58,7 @@ public: PowerX11(); virtual ~PowerX11(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; |