diff options
Diffstat (limited to 'platform/x11')
-rw-r--r-- | platform/x11/context_gl_x11.cpp | 38 | ||||
-rw-r--r-- | platform/x11/context_gl_x11.h | 4 | ||||
-rw-r--r-- | platform/x11/detect.py | 18 | ||||
-rw-r--r-- | platform/x11/export/export.cpp | 28 | ||||
-rw-r--r-- | platform/x11/export/export.h | 31 | ||||
-rw-r--r-- | platform/x11/joystick_linux.cpp | 74 | ||||
-rw-r--r-- | platform/x11/joystick_linux.h | 7 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 254 | ||||
-rw-r--r-- | platform/x11/os_x11.h | 37 | ||||
-rw-r--r-- | platform/x11/platform_config.h | 2 |
10 files changed, 480 insertions, 13 deletions
diff --git a/platform/x11/context_gl_x11.cpp b/platform/x11/context_gl_x11.cpp index 9f987e1376..cd325dfc99 100644 --- a/platform/x11/context_gl_x11.cpp +++ b/platform/x11/context_gl_x11.cpp @@ -34,7 +34,9 @@ #include <unistd.h> #include <stdlib.h> +#define GLX_GLXEXT_PROTOTYPES #include <GL/glx.h> +#include <GL/glxext.h> #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 @@ -176,6 +178,41 @@ int ContextGL_X11::get_window_height() { return xwa.height; } +void ContextGL_X11::set_use_vsync(bool p_use) { + static bool setup = false; + static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = NULL; + static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = NULL; + static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = NULL; + + if (!setup) { + setup = true; + String extensions = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display)); + if (extensions.find("GLX_EXT_swap_control") != -1) + glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT"); + if (extensions.find("GLX_MESA_swap_control") != -1) + glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalMESA"); + if (extensions.find("GLX_SGI_swap_control") != -1) + glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalSGI"); + } + int val = p_use ? 1:0; + if (glXSwapIntervalMESA) { + glXSwapIntervalMESA(val); + } + else if (glXSwapIntervalSGI) { + glXSwapIntervalSGI(val); + } + else if (glXSwapIntervalEXT) { + GLXDrawable drawable = glXGetCurrentDrawable(); + glXSwapIntervalEXT(x11_display, drawable, val); + } + else return; + use_vsync = p_use; +} +bool ContextGL_X11::is_using_vsync() const { + + return use_vsync; +} + ContextGL_X11::ContextGL_X11(::Display *p_x11_display,::Window &p_x11_window,const OS::VideoMode& p_default_video_mode,bool p_opengl_3_context) : x11_window(p_x11_window) { @@ -189,6 +226,7 @@ ContextGL_X11::ContextGL_X11(::Display *p_x11_display,::Window &p_x11_window,con glx_minor=glx_major=0; p = memnew( ContextGL_X11_Private ); p->glx_context=0; + use_vsync=false; } diff --git a/platform/x11/context_gl_x11.h b/platform/x11/context_gl_x11.h index c77fb3e333..4474542c0b 100644 --- a/platform/x11/context_gl_x11.h +++ b/platform/x11/context_gl_x11.h @@ -55,6 +55,7 @@ class ContextGL_X11 : public ContextGL { bool direct_render; int glx_minor,glx_major; bool opengl_3_context; + bool use_vsync; public: virtual void release_current(); @@ -65,6 +66,9 @@ public: virtual Error initialize(); + virtual void set_use_vsync(bool p_use); + virtual bool is_using_vsync() const; + ContextGL_X11(::Display *p_x11_display,::Window &p_x11_window,const OS::VideoMode& p_default_video_mode,bool p_opengl_3_context); ~ContextGL_X11(); diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 6b3f7147ef..5f272536ba 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -45,6 +45,11 @@ def can_build(): print("xinerama not found.. x11 disabled.") return False + x11_error=os.system("pkg-config xrandr --modversion > /dev/null ") + if (x11_error): + print("xrandr not found.. x11 disabled.") + return False + return True # X11 enabled @@ -65,7 +70,10 @@ def get_flags(): return [ ('builtin_zlib', 'no'), + ('glew', 'yes'), ("openssl", "yes"), + ('freetype','yes'), #use system freetype + #("theora","no"), ] @@ -131,6 +139,7 @@ def configure(env): env.ParseConfig('pkg-config x11 --cflags --libs') env.ParseConfig('pkg-config xinerama --cflags --libs') env.ParseConfig('pkg-config xcursor --cflags --libs') + env.ParseConfig('pkg-config xrandr --cflags --libs') if (env["openssl"]=="yes"): env.ParseConfig('pkg-config openssl --cflags --libs') @@ -140,14 +149,9 @@ def configure(env): env.ParseConfig('pkg-config freetype2 --cflags --libs') - if (env["freetype"]!="no"): - env.Append(CCFLAGS=['-DFREETYPE_ENABLED']) - if (env["freetype"]=="builtin"): - env.Append(CPPPATH=['#tools/freetype']) - env.Append(CPPPATH=['#tools/freetype/freetype/include']) - env.Append(CPPFLAGS=['-DOPENGL_ENABLED','-DGLEW_ENABLED']) + env.Append(CPPFLAGS=['-DOPENGL_ENABLED']) if os.system("pkg-config --exists alsa")==0: print("Enabling ALSA") @@ -178,7 +182,7 @@ def configure(env): print("PulseAudio development libraries not found, disabling driver") env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_ENABLED','-DGLES_OVER_GL']) - env.Append(LIBS=['GL', 'GLU', 'pthread', 'z']) + env.Append(LIBS=['GL', 'GLU', 'pthread', 'z', 'dl']) #env.Append(CPPFLAGS=['-DMPC_FIXED_POINT']) #host compiler is default.. diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp index bed57fbe9f..c6675ace72 100644 --- a/platform/x11/export/export.cpp +++ b/platform/x11/export/export.cpp @@ -1,3 +1,31 @@ +/*************************************************************************/ +/* export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ #include "export.h" #include "platform/x11/logo.h" #include "tools/editor/editor_import_export.h" diff --git a/platform/x11/export/export.h b/platform/x11/export/export.h index 1077709ea1..9dc13d7459 100644 --- a/platform/x11/export/export.h +++ b/platform/x11/export/export.h @@ -1,4 +1,29 @@ - - +/*************************************************************************/ +/* export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/*************************************************************************/ void register_x11_exporter(); - diff --git a/platform/x11/joystick_linux.cpp b/platform/x11/joystick_linux.cpp index 2793cc5734..5ce0219df7 100644 --- a/platform/x11/joystick_linux.cpp +++ b/platform/x11/joystick_linux.cpp @@ -316,13 +316,21 @@ void joystick_linux::setup_joystick_properties(int p_id) { } } } -} + joy->force_feedback = false; + joy->ff_effect_timestamp = 0; + unsigned long ffbit[NBITS(FF_CNT)]; + if (ioctl(joy->fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) != -1) { + if (test_bit(FF_RUMBLE, ffbit)) { + joy->force_feedback = true; + } + } +} void joystick_linux::open_joystick(const char *p_path) { int joy_num = get_free_joy_slot(); - int fd = open(p_path, O_RDONLY | O_NONBLOCK); + int fd = open(p_path, O_RDWR | O_NONBLOCK); if (fd != -1 && joy_num != -1) { unsigned long evbit[NBITS(EV_MAX)] = { 0 }; @@ -392,6 +400,55 @@ void joystick_linux::open_joystick(const char *p_path) { } } +void joystick_linux::joystick_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) +{ + Joystick& joy = joysticks[p_id]; + if (!joy.force_feedback || joy.fd == -1 || p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { + return; + } + if (joy.ff_effect_id != -1) { + joystick_vibration_stop(p_id, p_timestamp); + } + + struct ff_effect effect; + effect.type = FF_RUMBLE; + effect.id = -1; + effect.u.rumble.weak_magnitude = floor(p_weak_magnitude * (float)0xffff); + effect.u.rumble.strong_magnitude = floor(p_strong_magnitude * (float)0xffff); + effect.replay.length = floor(p_duration * 1000); + effect.replay.delay = 0; + + if (ioctl(joy.fd, EVIOCSFF, &effect) < 0) { + return; + } + + struct input_event play; + play.type = EV_FF; + play.code = effect.id; + play.value = 1; + write(joy.fd, (const void*)&play, sizeof(play)); + + joy.ff_effect_id = effect.id; + joy.ff_effect_timestamp = p_timestamp; +} + +void joystick_linux::joystick_vibration_stop(int p_id, uint64_t p_timestamp) +{ + Joystick& joy = joysticks[p_id]; + if (!joy.force_feedback || joy.fd == -1 || joy.ff_effect_id == -1) { + return; + } + + struct input_event stop; + stop.type = EV_FF; + stop.code = joy.ff_effect_id; + stop.value = 0; + write(joy.fd, (const void*)&stop, sizeof(stop)); + + joy.ff_effect_id = -1; + joy.ff_effect_timestamp = p_timestamp; +} + InputDefault::JoyAxis joystick_linux::axis_correct(const input_absinfo *p_abs, int p_value) const { int min = p_abs->minimum; @@ -485,6 +542,19 @@ uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) { if (len == 0 || (len < 0 && errno != EAGAIN)) { close_joystick(i); }; + + if (joy->force_feedback) { + uint64_t timestamp = input->get_joy_vibration_timestamp(i); + if (timestamp > joy->ff_effect_timestamp) { + Vector2 strength = input->get_joy_vibration_strength(i); + float duration = input->get_joy_vibration_duration(i); + if (strength.x == 0 && strength.y == 0) { + joystick_vibration_stop(i, timestamp); + } else { + joystick_vibration_start(i, strength.x, strength.y, duration, timestamp); + } + } + } } joy_mutex->unlock(); return p_event_id; diff --git a/platform/x11/joystick_linux.h b/platform/x11/joystick_linux.h index 4f0533721b..7ea2664ebb 100644 --- a/platform/x11/joystick_linux.h +++ b/platform/x11/joystick_linux.h @@ -61,6 +61,10 @@ private: String devpath; input_absinfo *abs_info[MAX_ABS]; + bool force_feedback; + int ff_effect_id; + uint64_t ff_effect_timestamp; + Joystick(); ~Joystick(); void reset(); @@ -88,6 +92,9 @@ private: void run_joystick_thread(); void open_joystick(const char* path); + void joystick_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); + void joystick_vibration_stop(int p_id, uint64_t p_timestamp); + InputDefault::JoyAxis axis_correct(const input_absinfo *abs, int value) const; }; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 4d7532d637..1ca779ef7c 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -57,6 +57,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> +#include <dlfcn.h> //stupid linux.h #ifdef KEY_TAB @@ -105,6 +106,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi last_timestamp=0; last_mouse_pos_valid=false; last_keyrelease_time=0; + xdnd_version = 0; if (get_render_thread_mode()==RENDER_SEPARATE_THREAD) { XInitThreads(); @@ -116,6 +118,37 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi char * modifiers = XSetLocaleModifiers ("@im=none"); ERR_FAIL_COND( modifiers == NULL ); + const char* err; + xrr_get_monitors = NULL; + xrr_free_monitors = NULL; + int xrandr_major = 0; + int xrandr_minor = 0; + int event_base, error_base; + xrandr_ext_ok = XRRQueryExtension(x11_display,&event_base, &error_base); + xrandr_handle = dlopen("libXrandr.so", RTLD_LAZY); + err = dlerror(); + if (!xrandr_handle) { + fprintf(stderr, "could not load libXrandr.so, Error: %s\n", err); + } + else { + XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor); + if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) { + xrr_get_monitors = (xrr_get_monitors_t) dlsym(xrandr_handle, "XRRGetMonitors"); + if (!xrr_get_monitors) { + err = dlerror(); + fprintf(stderr, "could not find symbol XRRGetMonitors\nError: %s\n", err); + } + else { + xrr_free_monitors = (xrr_free_monitors_t) dlsym(xrandr_handle, "XRRFreeMonitors"); + if (!xrr_free_monitors) { + err = dlerror(); + fprintf(stderr, "could not find XRRFreeMonitors\nError: %s\n", err); + xrr_get_monitors = NULL; + } + } + } + } + xim = XOpenIM (x11_display, NULL, NULL, NULL); @@ -415,6 +448,19 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi } set_cursor_shape(CURSOR_BUSY); + //Set Xdnd (drag & drop) support + Atom XdndAware = XInternAtom(x11_display, "XdndAware", False); + Atom version=5; + XChangeProperty(x11_display, x11_window, XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&version, 1); + + xdnd_enter = XInternAtom(x11_display, "XdndEnter", False); + xdnd_position = XInternAtom(x11_display, "XdndPosition", False); + xdnd_status = XInternAtom(x11_display, "XdndStatus", False); + xdnd_action_copy = XInternAtom(x11_display, "XdndActionCopy", False); + xdnd_drop = XInternAtom(x11_display, "XdndDrop", False); + xdnd_finished = XInternAtom(x11_display, "XdndFinished", False); + xdnd_selection = XInternAtom(x11_display, "XdndSelection", False); + requested = None; visual_server->init(); // @@ -466,6 +512,9 @@ void OS_X11::finalize() { physics_2d_server->finish(); memdelete(physics_2d_server); + if (xrandr_handle) + dlclose(xrandr_handle); + XUnmapWindow( x11_display, x11_window ); XDestroyWindow( x11_display, x11_window ); @@ -708,6 +757,46 @@ Size2 OS_X11::get_screen_size(int p_screen) const { return size; } +int OS_X11::get_screen_dpi(int p_screen) const { + + //invalid screen? + ERR_FAIL_INDEX_V(p_screen, get_screen_count(), 0); + + //Get physical monitor Dimensions through XRandR and calculate dpi + Size2 sc = get_screen_size(p_screen); + if (xrandr_ext_ok) { + int count = 0; + if (xrr_get_monitors) { + xrr_monitor_info *monitors = xrr_get_monitors(x11_display, x11_window, true, &count); + if (p_screen < count) { + double xdpi = sc.width / (double) monitors[p_screen].mwidth * 25.4; + double ydpi = sc.height / (double) monitors[p_screen].mheight * 25.4; + xrr_free_monitors(monitors); + return (xdpi + ydpi) / 2; + } + xrr_free_monitors(monitors); + } + else if (p_screen == 0) { + XRRScreenSize *sizes = XRRSizes(x11_display, 0, &count); + if (sizes) { + double xdpi = sc.width / (double) sizes[0].mwidth * 25.4; + double ydpi = sc.height / (double) sizes[0].mheight * 25.4; + return (xdpi + ydpi) / 2; + } + } + } + + int width_mm = DisplayWidthMM(x11_display, p_screen); + int height_mm = DisplayHeightMM(x11_display, p_screen); + double xdpi = (width_mm ? sc.width / (double) width_mm * 25.4 : 0); + double ydpi = (height_mm ? sc.height / (double) height_mm * 25.4 : 0); + if (xdpi || xdpi) + return (xdpi + ydpi)/(xdpi && ydpi ? 2 : 1); + + //could not get dpi + return 96; +} + Point2 OS_X11::get_window_position() const { int x,y; Window child; @@ -1166,6 +1255,72 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { input->parse_input_event( event); } +struct Property +{ + unsigned char *data; + int format, nitems; + Atom type; +}; + +static Property read_property(Display* p_display, Window p_window, Atom p_property) { + + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *ret=0; + + int read_bytes = 1024; + + //Keep trying to read the property until there are no + //bytes unread. + do + { + if(ret != 0) + XFree(ret); + + XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType, + &actual_type, &actual_format, &nitems, &bytes_after, + &ret); + + read_bytes *= 2; + + }while(bytes_after != 0); + + Property p = {ret, actual_format, nitems, actual_type}; + + return p; +} + +static Atom pick_target_from_list(Display* p_display, Atom *p_list, int p_count) { + + static const char* target_type = "text/uri-list"; + + for (int i = 0; i < p_count; i++) { + + Atom atom = p_list[i]; + + if (atom != None && String(XGetAtomName(p_display, atom)) == target_type) + return atom; + } + return None; +} + +static Atom pick_target_from_atoms(Display* p_disp, Atom p_t1, Atom p_t2, Atom p_t3) { + + static const char* target_type = "text/uri-list"; + if (p_t1 != None && String(XGetAtomName(p_disp, p_t1)) == target_type) + return p_t1; + + if (p_t2 != None && String(XGetAtomName(p_disp, p_t2)) == target_type) + return p_t2; + + if (p_t3 != None && String(XGetAtomName(p_disp, p_t3)) == target_type) + return p_t3; + + return None; +} + void OS_X11::process_xevents() { //printf("checking events %i\n", XPending(x11_display)); @@ -1456,11 +1611,96 @@ void OS_X11::process_xevents() { XFlush (x11_display); } break; + case SelectionNotify: + + if (event.xselection.target == requested) { + + Property p = read_property(x11_display, x11_window, XInternAtom(x11_display, "PRIMARY", 0)); + + Vector<String> files = String((char *)p.data).split("\n", false); + for (int i = 0; i < files.size(); i++) { + files[i] = files[i].replace("file://", "").replace("%20", " ").strip_escapes(); + } + main_loop->drop_files(files); + + //Reply that all is well. + XClientMessageEvent m; + memset(&m, sizeof(m), 0); + m.type = ClientMessage; + m.display = x11_display; + m.window = xdnd_source_window; + m.message_type = xdnd_finished; + m.format=32; + m.data.l[0] = x11_window; + m.data.l[1] = 1; + m.data.l[2] = xdnd_action_copy; //We only ever copy. + + XSendEvent(x11_display, xdnd_source_window, False, NoEventMask, (XEvent*)&m); + } + break; case ClientMessage: if ((unsigned int)event.xclient.data.l[0]==(unsigned int)wm_delete) main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); + + else if ((unsigned int)event.xclient.message_type == (unsigned int)xdnd_enter) { + + //File(s) have been dragged over the window, check for supported target (text/uri-list) + xdnd_version = ( event.xclient.data.l[1] >> 24); + Window source = event.xclient.data.l[0]; + bool more_than_3 = event.xclient.data.l[1] & 1; + if (more_than_3) { + Property p = read_property(x11_display, source, XInternAtom(x11_display, "XdndTypeList", False)); + requested = pick_target_from_list(x11_display, (Atom*)p.data, p.nitems); + } + else + requested = pick_target_from_atoms(x11_display, event.xclient.data.l[2],event.xclient.data.l[3], event.xclient.data.l[4]); + } + else if ((unsigned int)event.xclient.message_type == (unsigned int )xdnd_position) { + + //xdnd position event, reply with an XDND status message + //just depending on type of data for now + XClientMessageEvent m; + memset(&m, sizeof(m), 0); + m.type = ClientMessage; + m.display = event.xclient.display; + m.window = event.xclient.data.l[0]; + m.message_type = xdnd_status; + m.format=32; + m.data.l[0] = x11_window; + m.data.l[1] = (requested != None); + m.data.l[2] = 0; //empty rectangle + m.data.l[3] = 0; + m.data.l[4] = xdnd_action_copy; + + XSendEvent(x11_display, event.xclient.data.l[0], False, NoEventMask, (XEvent*)&m); + XFlush(x11_display); + } + else if ((unsigned int)event.xclient.message_type == (unsigned int)xdnd_drop) { + + if (requested != None) { + xdnd_source_window = event.xclient.data.l[0]; + if(xdnd_version >= 1) + XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), x11_window, event.xclient.data.l[2]); + else + XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), x11_window, CurrentTime); + } + else { + //Reply that we're not interested. + XClientMessageEvent m; + memset(&m, sizeof(m), 0); + m.type = ClientMessage; + m.display = event.xclient.display; + m.window = event.xclient.data.l[0]; + m.message_type = xdnd_finished; + m.format=32; + m.data.l[0] = x11_window; + m.data.l[1] = 0; + m.data.l[2] = None; //Failed. + XSendEvent(x11_display, event.xclient.data.l[0], False, NoEventMask, (XEvent*)&m); + } + } break; default: break; @@ -1787,6 +2027,20 @@ String OS_X11::get_joy_guid(int p_device) const { return input->get_joy_guid_remapped(p_device); } +void OS_X11::set_use_vsync(bool p_enable) { + if (context_gl) + return context_gl->set_use_vsync(p_enable); +} + +bool OS_X11::is_vsnc_enabled() const { + + if (context_gl) + return context_gl->is_using_vsync(); + + return true; +} + + void OS_X11::set_context(int p_context) { XClassHint* classHint = NULL; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index d9a5b1688c..71bbe726dd 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -52,6 +52,7 @@ #include <X11/keysym.h> #include <X11/Xlib.h> #include <X11/Xcursor/Xcursor.h> +#include <X11/extensions/Xrandr.h> // Hints for X11 fullscreen typedef struct { @@ -62,6 +63,20 @@ typedef struct { unsigned long status; } Hints; +typedef struct _xrr_monitor_info { + Atom name; + Bool primary; + Bool automatic; + int noutput; + int x; + int y; + int width; + int height; + int mwidth; + int mheight; + RROutput *outputs; +} xrr_monitor_info; + #undef CursorShape /** @author Juan Linietsky <reduzio@gmail.com> @@ -70,6 +85,17 @@ typedef struct { class OS_X11 : public OS_Unix { Atom wm_delete; + Atom xdnd_enter; + Atom xdnd_position; + Atom xdnd_status; + Atom xdnd_action_copy; + Atom xdnd_drop; + Atom xdnd_finished; + Atom xdnd_selection; + Atom requested; + + int xdnd_version; + #if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) ContextGL_X11 *context_gl; #endif @@ -78,6 +104,7 @@ class OS_X11 : public OS_Unix { VideoMode current_videomode; List<String> args; Window x11_window; + Window xdnd_source_window; MainLoop *main_loop; ::Display* x11_display; char *xmbstring; @@ -150,6 +177,12 @@ class OS_X11 : public OS_Unix { //void set_wm_border(bool p_enabled); void set_wm_fullscreen(bool p_enabled); + typedef xrr_monitor_info* (*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors); + typedef void (*xrr_free_monitors_t)(xrr_monitor_info* monitors); + xrr_get_monitors_t xrr_get_monitors; + xrr_free_monitors_t xrr_free_monitors; + void *xrandr_handle; + Bool xrandr_ext_ok; protected: @@ -207,6 +240,7 @@ public: virtual void set_current_screen(int p_screen); virtual Point2 get_screen_position(int p_screen=0) const; virtual Size2 get_screen_size(int p_screen=0) const; + virtual int get_screen_dpi(int p_screen=0) const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2& p_position); virtual Size2 get_window_size() const; @@ -228,6 +262,9 @@ public: virtual void set_context(int p_context); + virtual void set_use_vsync(bool p_enable); + virtual bool is_vsnc_enabled() const; + void run(); OS_X11(); diff --git a/platform/x11/platform_config.h b/platform/x11/platform_config.h index aac50c27c2..3b47b2c92d 100644 --- a/platform/x11/platform_config.h +++ b/platform/x11/platform_config.h @@ -34,6 +34,6 @@ #define PTHREAD_BSD_SET_NAME #endif -#define GLES2_INCLUDE_H "gl_context/glew.h" +#define GLES2_INCLUDE_H "gl_context/GL/glew.h" |