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 | 4 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 179 | ||||
-rw-r--r-- | platform/x11/os_x11.h | 15 |
5 files changed, 238 insertions, 2 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..5a43bf9323 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -143,8 +143,8 @@ def configure(env): 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(CPPPATH=['#drivers/freetype']) + env.Append(CPPPATH=['#drivers/freetype/freetype/include']) env.Append(CPPFLAGS=['-DOPENGL_ENABLED','-DGLEW_ENABLED']) diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 4d7532d637..b089436a17 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -105,6 +105,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(); @@ -415,6 +416,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(); // @@ -1166,6 +1180,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 +1536,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 +1952,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..311f26d4d3 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -70,6 +70,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 +89,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; @@ -228,6 +240,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(); |