diff options
| -rw-r--r-- | CMakeLists.txt | 4 | ||||
| -rw-r--r-- | plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp | 31 | ||||
| -rw-r--r-- | plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h | 4 | ||||
| -rw-r--r-- | plugins/unitydialog/src/unitydialog.cpp | 98 | ||||
| -rw-r--r-- | plugins/unitydialog/src/unitydialog.h | 24 | ||||
| -rw-r--r-- | plugins/unityshell/src/BamfLauncherIcon.cpp | 4 | ||||
| -rw-r--r-- | plugins/unityshell/src/IconLoader.cpp | 168 | ||||
| -rw-r--r-- | plugins/unityshell/src/IconRenderer.cpp | 33 | ||||
| -rw-r--r-- | plugins/unityshell/src/LauncherModel.cpp | 52 | ||||
| -rw-r--r-- | plugins/unityshell/src/ScreenEffectFramebufferObject.cpp | 4 | ||||
| -rw-r--r-- | plugins/unityshell/src/ScreenEffectFramebufferObject.h | 2 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.cpp | 187 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.h | 21 | ||||
| -rw-r--r-- | services/panel-service.c | 3 | ||||
| -rw-r--r-- | standalone-clients/TestShortcut.cpp | 2 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | tests/test_icon_loader.cpp | 191 | ||||
| -rwxr-xr-x | tools/unity-introspection-visualiser.py | 87 |
18 files changed, 786 insertions, 134 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 359efd68e..66c47f12e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ set (CMAKE_CXX_FLAGS "-DGNOME_DESKTOP_USE_UNSTABLE_API -std=c++0x -fno-permissiv set (CMAKE_CXX_FLAGS_DEBUG "-g3") set (CMAKE_CXX_FLAGS_RELEASE "") +if (BUILD_GLES) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNUX_OPENGLES_20 -DUSE_GLES") +endif (BUILD_GLES) # # Niceties @@ -136,6 +139,7 @@ add_subdirectory(UnityCore) add_subdirectory(guides) add_subdirectory(standalone-clients EXCLUDE_FROM_ALL) + # # GSettings Schema # diff --git a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp index ce5792da1..c17ad2d0f 100644 --- a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp +++ b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp @@ -438,13 +438,21 @@ UnityMTGrabHandlesWindow::getOutputExtents(CompWindowExtents& output) bool UnityMTGrabHandlesWindow::glDraw(const GLMatrix& transform, +#ifdef USE_GLES + const GLWindowPaintAttrib& attrib, +#else GLFragment::Attrib& fragment, +#endif const CompRegion& region, unsigned int mask) { /* Draw the window on the bottom, we will be drawing the * handles on top */ +#ifdef USE_GLES + bool status = gWindow->glDraw(transform, attrib, region, mask); +#else bool status = gWindow->glDraw(transform, fragment, region, mask); +#endif if (mHandles && mHandles->visible()) { @@ -464,10 +472,17 @@ UnityMTGrabHandlesWindow::glDraw(const GLMatrix& transform, GLTexture::MatrixList matl; GLTexture::Matrix mat = tex->matrix(); CompRegion paintRegion(region); +#ifdef USE_GLES + GLWindowPaintAttrib wAttrib(attrib); +#endif /* We can reset the window geometry since it will be * re-added later */ +#ifdef USE_GLES + gWindow->vertexBuffer()->begin(); +#else gWindow->geometry().reset(); +#endif /* Not sure what this does, but it is necessary * (adjusts for scale?) */ @@ -483,23 +498,35 @@ UnityMTGrabHandlesWindow::glDraw(const GLMatrix& transform, * dim (so we get a nice render for things like * wobbly etc etc */ gWindow->glAddGeometry(matl, reg, paintRegion); - +#ifdef USE_GLES + gWindow->vertexBuffer()->end(); + wAttrib.opacity = mHandles->opacity(); +#else /* Did it succeed? */ if (gWindow->geometry().vertices) { fragment.setOpacity(mHandles->opacity()); /* Texture rendering set-up */ us->gScreen->setTexEnvMode(GL_MODULATE); +#endif glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Draw the dim texture with all of it's modified * geometry glory */ - gWindow->glDrawTexture(tex, fragment, mask | PAINT_WINDOW_BLEND_MASK + gWindow->glDrawTexture(tex, +#ifdef USE_GLES + transform, wAttrib, +#else + fragment, +#endif + mask | PAINT_WINDOW_BLEND_MASK | PAINT_WINDOW_TRANSLUCENT_MASK | PAINT_WINDOW_TRANSFORMED_MASK); /* Texture rendering tear-down */ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +#ifndef USE_GLES us->gScreen->setTexEnvMode(GL_REPLACE); } +#endif } handle++; diff --git a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h index e10568ce0..a5a4e362e 100644 --- a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h +++ b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h @@ -229,7 +229,11 @@ public: void moveNotify(int dx, int dy, bool immediate); bool glDraw(const GLMatrix&, +#ifdef USE_GLES + const GLWindowPaintAttrib&, +#else GLFragment::Attrib&, +#endif const CompRegion&, unsigned int); diff --git a/plugins/unitydialog/src/unitydialog.cpp b/plugins/unitydialog/src/unitydialog.cpp index f2423fe90..300b8e19f 100644 --- a/plugins/unitydialog/src/unitydialog.cpp +++ b/plugins/unitydialog/src/unitydialog.cpp @@ -420,7 +420,12 @@ UnityDialogWindow::glAddGeometry(const GLTexture::MatrixList& matrices, /* Collect textures */ void UnityDialogWindow::glDrawTexture(GLTexture* texture, +#ifdef USE_GLES + const GLMatrix &transform, + const GLWindowPaintAttrib &attrib, +#else GLFragment::Attrib& fa, +#endif unsigned int mask) { unity::PaintInfoCollector::Active ()->processTexture (texture); @@ -448,7 +453,11 @@ unity::GeometryCollection::addGeometryForWindow (CompWindow *w, const CompRegion { /* We can reset the window geometry since it will be * re-added later */ +#ifdef USE_GLES + GLWindow::get (w)->vertexBuffer()->begin(); +#else GLWindow::get (w)->geometry().reset(); +#endif for (unsigned int i = 0; i < collectedMatrixLists.size (); i++) { @@ -462,6 +471,10 @@ unity::GeometryCollection::addGeometryForWindow (CompWindow *w, const CompRegion * wobbly etc etc */ GLWindow::get (w)->glAddGeometry(matl, reg, paintRegion, min, max); } + +#ifdef USE_GLES + GLWindow::get (w)->vertexBuffer()->end(); +#endif } void @@ -497,7 +510,11 @@ unity::TexGeometryCollection::setTexture (GLTexture *tex) } void -unity::TexGeometryCollection::addGeometriesAndDrawTextureForWindow(CompWindow *w, unsigned int mask) +unity::TexGeometryCollection::addGeometriesAndDrawTextureForWindow(CompWindow *w, +#ifdef USE_GLES + const GLMatrix &transform, +#endif + unsigned int mask) { if (mTexture && mGeometries.status ()) { @@ -509,6 +526,25 @@ unity::TexGeometryCollection::addGeometriesAndDrawTextureForWindow(CompWindow *w mGeometries.addGeometryForWindow (w, paintRegion); +#ifdef USE_GLES + UnityDialogScreen *uds = UnityDialogScreen::get (screen); + GLWindowPaintAttrib attrib (gWindow->lastPaintAttrib()); + unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex(); + /* Texture rendering set-up */ +// uds->gScreen->setTexEnvMode(GL_MODULATE); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + /* Draw the dim texture with all of it's modified + * geometry glory */ + gWindow->glDrawTextureSetCurrentIndex(MAXSHORT); + gWindow->glDrawTexture(mTexture, transform, attrib, mask + | PAINT_WINDOW_BLEND_MASK + | PAINT_WINDOW_TRANSLUCENT_MASK + | PAINT_WINDOW_TRANSFORMED_MASK); + gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex); + /* Texture rendering tear-down */ + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + uds->gScreen->setTexEnvMode(GL_REPLACE); +#else if (gWindow->geometry().vertices) { UnityDialogScreen *uds = UnityDialogScreen::get (screen); @@ -528,6 +564,7 @@ unity::TexGeometryCollection::addGeometriesAndDrawTextureForWindow(CompWindow *w glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); uds->gScreen->setTexEnvMode(GL_REPLACE); } +#endif } } @@ -581,10 +618,18 @@ unity::PaintInfoCollector::processTexture (GLTexture *tex) } void -unity::PaintInfoCollector::drawGeometriesForWindow(CompWindow *w, unsigned int pm) +unity::PaintInfoCollector::drawGeometriesForWindow(CompWindow *w, +#ifdef USE_GLES + const GLMatrix &transform, +#endif + unsigned int pm) { for (unity::TexGeometryCollection &tcg : mCollection) +#if USE_GLES + tcg.addGeometriesAndDrawTextureForWindow (w, transform, pm); +#else tcg.addGeometriesAndDrawTextureForWindow (w, pm); +#endif } unity::PaintInfoCollector * unity::PaintInfoCollector::active_collector = NULL; @@ -599,7 +644,11 @@ unity::PaintInfoCollector::Active () bool UnityDialogWindow::glDraw(const GLMatrix& transform, +#ifdef USE_GLES + const GLWindowPaintAttrib& attrib, +#else GLFragment::Attrib& fragment, +#endif const CompRegion& region, unsigned int mask) { @@ -610,7 +659,13 @@ UnityDialogWindow::glDraw(const GLMatrix& transform, /* Draw the window on the bottom, we will be drawing the * dim render on top */ - bool status = gWindow->glDraw(transform, fragment, region, mask); + bool status = gWindow->glDraw(transform, +#ifdef USE_GLES + attrib, +#else + fragment, +#endif + region, mask); UNITY_DIALOG_SCREEN(screen); @@ -618,10 +673,17 @@ UnityDialogWindow::glDraw(const GLMatrix& transform, { GLTexture::MatrixList matl; GLTexture::Matrix mat = tex->matrix(); +#ifdef USE_GLES + GLWindowPaintAttrib wAttrib(attrib); +#endif /* We can reset the window geometry since it will be * re-added later */ +#ifdef USE_GLES + gWindow->vertexBuffer()->begin(); +#else gWindow->geometry().reset(); +#endif /* Scale the dim render by the ratio of dim size * to window size */ @@ -642,7 +704,28 @@ UnityDialogWindow::glDraw(const GLMatrix& transform, * dim (so we get a nice render for things like * wobbly etc etc */ gWindow->glAddGeometry(matl, reg, paintRegion); - +#ifdef USE_GLES + gWindow->vertexBuffer()->end(); +#endif + +#ifdef USE_GLES + unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex(); + wAttrib.opacity = mShadeProgress; + /* Texture rendering set-up */ +// uds->gScreen->setTexEnvMode(GL_MODULATE); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + /* Draw the dim texture with all of it's modified + * geometry glory */ + gWindow->glDrawTextureSetCurrentIndex(MAXSHORT); + gWindow->glDrawTexture(tex, transform, attrib, mask + | PAINT_WINDOW_BLEND_MASK + | PAINT_WINDOW_TRANSLUCENT_MASK + | PAINT_WINDOW_TRANSFORMED_MASK); + gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex); + /* Texture rendering tear-down */ + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + uds->gScreen->setTexEnvMode(GL_REPLACE); +#else /* Did it succeed? */ if (gWindow->geometry().vertices) { @@ -662,6 +745,7 @@ UnityDialogWindow::glDraw(const GLMatrix& transform, glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); uds->gScreen->setTexEnvMode(GL_REPLACE); } +#endif } for (CompWindow* w : mTransients) @@ -674,7 +758,11 @@ UnityDialogWindow::glDraw(const GLMatrix& transform, unity::PaintInfoCollector pc (w); pc.collect(); - pc.drawGeometriesForWindow (window, mask); + pc.drawGeometriesForWindow (window, +#ifdef USE_GLES + transform, +#endif + mask); } } diff --git a/plugins/unitydialog/src/unitydialog.h b/plugins/unitydialog/src/unitydialog.h index c57a99b5c..be3d785ac 100644 --- a/plugins/unitydialog/src/unitydialog.h +++ b/plugins/unitydialog/src/unitydialog.h @@ -64,7 +64,13 @@ namespace unity int max); void setTexture (GLTexture *); +#ifdef USE_GLES + void addGeometriesAndDrawTextureForWindow (CompWindow *w, + const GLMatrix &transform, + unsigned int mask); +#else void addGeometriesAndDrawTextureForWindow (CompWindow *, unsigned int pm); +#endif private: GLTexture* mTexture; @@ -78,7 +84,13 @@ namespace unity PaintInfoCollector (CompWindow *w); void collect (); +#ifdef USE_GLES + void drawGeometriesForWindow (CompWindow *w, + const GLMatrix &transform, + unsigned int pm); +#else void drawGeometriesForWindow (CompWindow *w, unsigned int pm); +#endif void processGeometry (const GLTexture::MatrixList &ml, const CompRegion &r, @@ -242,7 +254,12 @@ public: public: bool - glDraw(const GLMatrix&, GLFragment::Attrib&, + glDraw(const GLMatrix&, +#ifdef USE_GLES + const GLWindowPaintAttrib&, +#else + GLFragment::Attrib&, +#endif const CompRegion&, unsigned int); bool @@ -258,7 +275,12 @@ public: void glDrawTexture(GLTexture* texture, +#ifdef USE_GLES + const GLMatrix& transform, + const GLWindowPaintAttrib& attrib, +#else GLFragment::Attrib& attrib, +#endif unsigned int mask); diff --git a/plugins/unityshell/src/BamfLauncherIcon.cpp b/plugins/unityshell/src/BamfLauncherIcon.cpp index 7a3d76aea..a136d2114 100644 --- a/plugins/unityshell/src/BamfLauncherIcon.cpp +++ b/plugins/unityshell/src/BamfLauncherIcon.cpp @@ -323,9 +323,7 @@ std::string BamfLauncherIcon::NameForWindow (Window window) view = static_cast <BamfView*> (l->data); if (BAMF_IS_WINDOW(view) && (Window) bamf_window_get_xid(BAMF_WINDOW(view)) == window) { - gchar *name = bamf_view_get_name (view); - result = name; - g_free (name); + result = glib::String(bamf_view_get_name(view)).Str(); break; } } diff --git a/plugins/unityshell/src/IconLoader.cpp b/plugins/unityshell/src/IconLoader.cpp index 52a4f9956..f385517d9 100644 --- a/plugins/unityshell/src/IconLoader.cpp +++ b/plugins/unityshell/src/IconLoader.cpp @@ -85,6 +85,9 @@ private: IconLoaderCallback slot; Handle handle; Impl* self; + GtkIconInfo* icon_info; + GdkPixbuf* result; + glib::Error error; IconLoaderTask(IconLoaderRequestType type_, std::string const& data_, @@ -95,6 +98,7 @@ private: Impl* self_) : type(type_), data(data_), size(size_), key(key_) , slot(slot_), handle(handle_), self(self_) + , icon_info(NULL), result(NULL) {} }; @@ -116,17 +120,19 @@ private: unsigned size, IconLoaderCallback slot); + // these methods might run asynchronously bool ProcessTask(IconLoaderTask* task); bool ProcessIconNameTask(IconLoaderTask* task); bool ProcessGIconTask(IconLoaderTask* task); - - // URI processing is async. bool ProcessURITask(IconLoaderTask* task); - void ProcessURITaskReady(IconLoaderTask* task, char* contents, gsize length); - static void LoadContentsReady(GObject* object, GAsyncResult* res, IconLoaderTask* task); + + // Loading/rendering of pixbufs is done in a separate thread + static gboolean LoaderJobFunc(GIOSchedulerJob* job, GCancellable *canc, + IconLoaderTask *task); + static gboolean LoadIconComplete(IconLoaderTask* task); // Loop calls the iteration function. - static bool Loop(Impl* self); + static gboolean Loop(Impl* self); bool Iteration(); private: @@ -312,26 +318,17 @@ bool IconLoader::Impl::ProcessTask(IconLoaderTask* task) bool IconLoader::Impl::ProcessIconNameTask(IconLoaderTask* task) { - GdkPixbuf* pixbuf = nullptr; GtkIconInfo* info = gtk_icon_theme_lookup_icon(theme_, task->data.c_str(), task->size, (GtkIconLookupFlags)0); if (info) { - glib::Error error; + task->icon_info = info; + g_io_scheduler_push_job ((GIOSchedulerJobFunc) LoaderJobFunc, + task, NULL, G_PRIORITY_HIGH_IDLE, NULL); - pixbuf = gtk_icon_info_load_icon(info, &error); - if (GDK_IS_PIXBUF(pixbuf)) - { - cache_[task->key] = pixbuf; - } - else - { - LOG_WARNING(logger) << "Unable to load icon " << task->data - << " at size " << task->size << ": " << error; - } - gtk_icon_info_free(info); + return false; } else { @@ -339,14 +336,12 @@ bool IconLoader::Impl::ProcessIconNameTask(IconLoaderTask* task) << " at size " << task->size; } - task->slot(task->data, task->size, pixbuf); + task->slot(task->data, task->size, nullptr); return true; } bool IconLoader::Impl::ProcessGIconTask(IconLoaderTask* task) { - GdkPixbuf* pixbuf = NULL; - glib::Error error; glib::Object<GIcon> icon(::g_icon_new_for_string(task->data.c_str(), &error)); @@ -368,18 +363,11 @@ bool IconLoader::Impl::ProcessGIconTask(IconLoaderTask* task) (GtkIconLookupFlags)0); if (info) { - pixbuf = gtk_icon_info_load_icon(info, &error); + task->icon_info = info; + g_io_scheduler_push_job ((GIOSchedulerJobFunc) LoaderJobFunc, + task, NULL, G_PRIORITY_HIGH_IDLE, NULL); - if (GDK_IS_PIXBUF(pixbuf)) - { - cache_[task->key] = pixbuf; - } - else - { - LOG_WARNING(logger) << "Unable to load icon " << task->data - << " at size " << task->size << ": " << error; - } - gtk_icon_info_free(info); + return false; } else { @@ -409,58 +397,91 @@ bool IconLoader::Impl::ProcessGIconTask(IconLoaderTask* task) << " at size " << task->size << ": " << error; } - task->slot(task->data, task->size, pixbuf); + task->slot(task->data, task->size, nullptr); return true; } bool IconLoader::Impl::ProcessURITask(IconLoaderTask* task) { - glib::Object<GFile> file(g_file_new_for_uri(task->data.c_str())); - - g_file_load_contents_async(file, - NULL, - (GAsyncReadyCallback)LoadContentsReady, - task); + g_io_scheduler_push_job ((GIOSchedulerJobFunc) LoaderJobFunc, + task, NULL, G_PRIORITY_HIGH_IDLE, NULL); return false; } -void IconLoader::Impl::ProcessURITaskReady(IconLoaderTask* task, - char* contents, - gsize length) +gboolean IconLoader::Impl::LoaderJobFunc(GIOSchedulerJob* job, + GCancellable *canc, + IconLoaderTask *task) { - GInputStream* stream = g_memory_input_stream_new_from_data(contents, length, NULL); + // careful here this is running in non-main thread + if (task->icon_info) + { + task->result = gtk_icon_info_load_icon(task->icon_info, &task->error); - glib::Error error; - glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_stream_at_scale(stream, - -1, - task->size, - true, - NULL, - &error)); - if (error) + gtk_icon_info_free (task->icon_info); + task->icon_info = NULL; + } + else if (task->type == REQUEST_TYPE_URI) { - LOG_WARNING(logger) << "Unable to create pixbuf from input stream for " - << task->data << " at size " << task->size << ": " << error; + glib::Object<GFile> file(g_file_new_for_uri(task->data.c_str())); + glib::String contents; + gsize length = 0; + + if (g_file_load_contents(file, canc, &contents, &length, + NULL, &task->error)) + { + glib::Object<GInputStream> stream( + g_memory_input_stream_new_from_data(contents.Value(), length, NULL)); + + task->result = gdk_pixbuf_new_from_stream_at_scale(stream, + -1, + task->size, + TRUE, + canc, + &task->error); + g_input_stream_close(stream, canc, NULL); + } + } + + g_io_scheduler_job_send_to_mainloop_async (job, + (GSourceFunc) LoadIconComplete, + task, + NULL); + + return FALSE; +} + +// this will be invoked back in the thread from which push_job was called +gboolean IconLoader::Impl::LoadIconComplete(IconLoaderTask* task) +{ + if (GDK_IS_PIXBUF(task->result)) + { + task->self->cache_[task->key] = task->result; } else { - cache_[task->key] = pixbuf; + LOG_WARNING(logger) << "Unable to load icon " << task->data + << " at size " << task->size << ": " << task->error; } - task->slot(task->data, task->size, pixbuf); - g_input_stream_close(stream, NULL, NULL); + task->slot(task->data, task->size, task->result); + + // this was all async, we need to erase ourselves from the task_map + task->self->task_map_.erase(task->handle); + delete task; + + return FALSE; } bool IconLoader::Impl::Iteration() { - static const int MAX_MICRO_SECS = 10000; + static const int MAX_MICRO_SECS = 1000; util::Timer timer; bool queue_empty = tasks_.empty(); - while (!queue_empty && - (timer.ElapsedMicroSeconds() < MAX_MICRO_SECS)) + // always do at least one iteration if the queue isn't empty + while (!queue_empty) { IconLoaderTask* task = tasks_.front(); @@ -472,6 +493,8 @@ bool IconLoader::Impl::Iteration() tasks_.pop(); queue_empty = tasks_.empty(); + + if (timer.ElapsedMicroSeconds() >= MAX_MICRO_SECS) break; } LOG_DEBUG(logger) << "Iteration done, queue size now at " << tasks_.size(); @@ -487,34 +510,11 @@ bool IconLoader::Impl::Iteration() } -bool IconLoader::Impl::Loop(IconLoader::Impl* self) +gboolean IconLoader::Impl::Loop(IconLoader::Impl* self) { - return self->Iteration(); + return self->Iteration() ? TRUE : FALSE; } -void IconLoader::Impl::LoadContentsReady(GObject* obj, - GAsyncResult* res, - IconLoaderTask* task) -{ - glib::String contents; - glib::Error error; - gsize length = 0; - - if (g_file_load_contents_finish(G_FILE(obj), res, &contents, &length, NULL, &error)) - { - task->self->ProcessURITaskReady(task, contents.Value(), length); - } - else - { - LOG_WARNING(logger) << "Unable to load contents of " - << task->data << ": " << error; - task->slot(task->data, task->size, nullptr); - } - task->self->task_map_.erase(task->handle); - delete task; -} - - IconLoader::IconLoader() : pimpl(new Impl()) { diff --git a/plugins/unityshell/src/IconRenderer.cpp b/plugins/unityshell/src/IconRenderer.cpp index f461b4045..2c6cb41e4 100644 --- a/plugins/unityshell/src/IconRenderer.cpp +++ b/plugins/unityshell/src/IconRenderer.cpp @@ -39,6 +39,14 @@ namespace unity namespace ui { +#ifdef USE_GLES + #define VertexShaderHeader "#version 100\n" + #define FragmentShaderHeader "#version 100\n precision mediump float;\n" +#else + #define VertexShaderHeader "#version 120\n" + #define FragmentShaderHeader "#version 110\n" +#endif + /* Use this shader to pass vertices in screen coordinates in the C++ code and compute use the fragment shader to perform the texture perspective correct division. @@ -60,9 +68,9 @@ namespace ui #define LUMIN_BLUE "0.055" nux::NString gPerspectiveCorrectShader = TEXT( -"[Vertex Shader] \n\ -#version 120 \n\ -uniform mat4 ViewProjectionMatrix; \n\ +"[Vertex Shader] \n" +VertexShaderHeader +"uniform mat4 ViewProjectionMatrix; \n\ \n\ attribute vec4 iTexCoord0; \n\ attribute vec4 iVertex; \n\ @@ -75,9 +83,9 @@ void main() \n\ gl_Position = ViewProjectionMatrix * iVertex; \n\ } \n\ \n\ -[Fragment Shader] \n\ -#version 110 \n\ - \n\ +[Fragment Shader] \n" +FragmentShaderHeader +" \n\ varying vec4 varyTexCoord0; \n\ \n\ uniform sampler2D TextureObject0; \n\ @@ -649,8 +657,13 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, // Perspective correct v0.x, v0.y, 0.0f, 1.0f, s0 / v0.w, t0 / v0.w, 0.0f, 1.0f / v0.w, v1.x, v1.y, 0.0f, 1.0f, s1 / v1.w, t1 / v1.w, 0.0f, 1.0f / v1.w, +#ifdef USE_GLES + v3.x, v3.y, 0.0f, 1.0f, s3 / v3.w, t3 / v3.w, 0.0f, 1.0f / v3.w, + v2.x, v2.y, 0.0f, 1.0f, s2 / v2.w, t2 / v2.w, 0.0f, 1.0f / v2.w, +#else v2.x, v2.y, 0.0f, 1.0f, s2 / v2.w, t2 / v2.w, 0.0f, 1.0f / v2.w, v3.x, v3.y, 0.0f, 1.0f, s3 / v3.w, t3 / v3.w, 0.0f, 1.0f / v3.w, +#endif }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); @@ -681,6 +694,7 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, local::shader_program_uv_persp_correction->SetUniformLocMatrix4fv((GLint)VPMatrixLocation, 1, false, (GLfloat*) & (_stored_projection_matrix.m)); } } +#ifndef USE_GLES else { local::asm_shader->Begin(); @@ -698,6 +712,7 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadMatrixf((float*) GfxContext.GetOpenGLProjectionMatrix().m)); } +#endif CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); @@ -716,8 +731,13 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, CHECKGL(glUniform4fARB(DesatFactor, arg.saturation, arg.saturation, arg.saturation, arg.saturation)); nux::GetWindowThread()->GetGraphicsEngine().SetTexture(GL_TEXTURE0, icon); +#ifdef USE_GLES + CHECKGL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); +#else CHECKGL(glDrawArrays(GL_QUADS, 0, 4)); +#endif } +#ifndef USE_GLES else { CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, bg_color.red, bg_color.green, bg_color.blue, bg_color.alpha)); @@ -726,6 +746,7 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, nux::GetWindowThread()->GetGraphicsEngine().SetTexture(GL_TEXTURE0, icon); CHECKGL(glDrawArrays(GL_QUADS, 0, 4)); } +#endif if (VertexLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); diff --git a/plugins/unityshell/src/LauncherModel.cpp b/plugins/unityshell/src/LauncherModel.cpp index dc862b76a..45cc4196a 100644 --- a/plugins/unityshell/src/LauncherModel.cpp +++ b/plugins/unityshell/src/LauncherModel.cpp @@ -66,19 +66,17 @@ LauncherModel::Populate() _inner.clear(); - iterator it, it2; - int i = 0; - for (it = main_begin(); it != main_end(); it++) + for (auto icon : _inner_main) { - _inner.push_back(*it); - (*it)->SetSortPriority(i++); + _inner.push_back(icon); + icon->SetSortPriority(i++); } - for (it = shelf_begin(); it != shelf_end(); it++) + for (auto icon : _inner_shelf) { - _inner.push_back(*it); - (*it)->SetSortPriority(i++); + _inner.push_back(icon); + icon->SetSortPriority(i++); } return !std::equal(begin(), end(), copy.begin()); @@ -195,35 +193,33 @@ LauncherModel::ReorderBefore(LauncherIcon* icon, LauncherIcon* other, bool save) if (icon == other) return; - LauncherModel::iterator it; - int i = 0; int j = 0; - for (it = begin(); it != end(); it++) + for (auto icon_it : _inner) { - if ((*it) == icon) + if (icon_it == icon) { j++; continue; } - if ((*it) == other) + if (icon_it == other) { icon->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; - (*it)->SetSortPriority(i); + icon_it->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; } else { - (*it)->SetSortPriority(i); + icon_it->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; } j++; @@ -238,48 +234,46 @@ LauncherModel::ReorderSmart(LauncherIcon* icon, LauncherIcon* other, bool save) if (icon == other) return; - LauncherModel::iterator it; - int i = 0; int j = 0; bool skipped = false; - for (it = begin(); it != end(); it++) + for (auto icon_it : _inner) { - if ((*it) == icon) + if (icon_it == icon) { skipped = true; j++; continue; } - if ((*it) == other) + if (icon_it == other) { if (!skipped) { icon->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; } - (*it)->SetSortPriority(i); + icon_it->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; if (skipped) { icon->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; } } else { - (*it)->SetSortPriority(i); + icon_it->SetSortPriority(i); if (i != j && save) - (*it)->SaveCenter(); + icon_it->SaveCenter(); i++; } j++; diff --git a/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp b/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp index 6b0011f38..2f2010396 100644 --- a/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp +++ b/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp @@ -17,6 +17,7 @@ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> */ +#ifndef USE_GLES #include "ScreenEffectFramebufferObject.h" #include "BackgroundEffectHelper.h" #include <NuxCore/Logger.h> @@ -232,3 +233,6 @@ unity::ScreenEffectFramebufferObject::~ScreenEffectFramebufferObject () if (mFBTexture) glDeleteTextures (1, &mFBTexture); } + +#endif // USE_GLES + diff --git a/plugins/unityshell/src/ScreenEffectFramebufferObject.h b/plugins/unityshell/src/ScreenEffectFramebufferObject.h index 1dbecca0e..2481136f1 100644 --- a/plugins/unityshell/src/ScreenEffectFramebufferObject.h +++ b/plugins/unityshell/src/ScreenEffectFramebufferObject.h @@ -20,6 +20,7 @@ #ifndef UNITY_SCREENEFFECT_FRAMEBUFFER_H #define UNITY_SCREENEFFECT_FRAMEBUFFER_H +#ifndef USE_GLES #include <Nux/Nux.h> namespace unity @@ -84,4 +85,5 @@ private: }; } // namespace unity +#endif // USE_GLES #endif diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index 168049cbb..cab4bbc25 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -114,7 +114,9 @@ UnityScreen::UnityScreen(CompScreen* screen) , damaged(false) , _key_nav_mode_requested(false) , _last_output(nullptr) +#ifndef USE_GLES , _active_fbo (0) +#endif , dash_is_open_ (false) , grab_index_ (0) , painting_tray_ (false) @@ -128,6 +130,7 @@ UnityScreen::UnityScreen(CompScreen* screen) int (*old_handler)(Display*, XErrorEvent*); old_handler = XSetErrorHandler(NULL); +#ifndef USE_GLES /* Ensure OpenGL version is 1.4+. */ version = get_opengl_version_f32((const gchar*) glGetString(GL_VERSION)); if (version < 1.4f) @@ -183,6 +186,7 @@ UnityScreen::UnityScreen(CompScreen* screen) failed = true; } } +#endif if (!failed) { @@ -199,16 +203,27 @@ UnityScreen::UnityScreen(CompScreen* screen) CompositeScreenInterface::setHandler(cScreen); GLScreenInterface::setHandler(gScreen); +#ifdef USE_GLES + gScreen->glPaintCompositedOutputSetEnabled (this, true); +#endif + PluginAdapter::Initialize(screen); WindowManager::SetDefault(PluginAdapter::Default()); StartupNotifyService::Default()->SetSnDisplay(screen->snDisplay(), screen->screenNum()); nux::NuxInitialize(0); +#ifndef USE_GLES wt = nux::CreateFromForeignWindow(cScreen->output(), glXGetCurrentContext(), &UnityScreen::initUnity, this); +#else + wt = nux::CreateFromForeignWindow(cScreen->output(), + eglGetCurrentContext(), + &UnityScreen::initUnity, + this); +#endif wt->RedrawRequested.connect(sigc::mem_fun(this, &UnityScreen::onRedrawRequested)); @@ -226,6 +241,7 @@ UnityScreen::UnityScreen(CompScreen* screen) _edge_timeout = optionGetLauncherRevealEdgeTimeout (); _in_paint = false; +#ifndef USE_GLES void *dlhand = dlopen ("libunityshell.so", RTLD_LAZY); if (dlhand) @@ -242,6 +258,7 @@ UnityScreen::UnityScreen(CompScreen* screen) uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry)); uScreen->_fbo->onScreenSizeChanged (geometry); } +#endif optionSetBackgroundColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); @@ -363,7 +380,7 @@ void UnityScreen::initAltTabNextWindow() { KeyboardUtil key_util (screen->dpy()); guint above_tab_keycode = key_util.GetKeycodeAboveKeySymbol (XStringToKeysym("Tab")); - KeySym above_tab_keysym = XKeycodeToKeysym (screen->dpy(), above_tab_keycode, 0); + KeySym above_tab_keysym = XkbKeycodeToKeysym (screen->dpy(), above_tab_keycode, 0, 0); if (above_tab_keysym != NoSymbol) { @@ -443,6 +460,7 @@ void UnityScreen::CreateSuperNewAction(char shortcut, bool use_shift, bool use_n void UnityScreen::nuxPrologue() { +#ifndef USE_GLES /* Vertex lighting isn't used in Unity, we disable that state as it could have * been leaked by another plugin. That should theoretically be switched off * right after PushAttrib since ENABLE_BIT is meant to restore the LIGHTING @@ -459,12 +477,14 @@ void UnityScreen::nuxPrologue() glMatrixMode(GL_MODELVIEW); glPushMatrix(); +#endif glGetError(); } void UnityScreen::nuxEpilogue() { +#ifndef USE_GLES (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo); glMatrixMode(GL_PROJECTION); @@ -486,6 +506,11 @@ void UnityScreen::nuxEpilogue() glReadBuffer(GL_BACK); glPopAttrib(); +#else + glDepthRangef(0, 1); + //glViewport(-1, -1, 2, 2); + gScreen->resetRasterPos(); +#endif glDisable(GL_SCISSOR_TEST); } @@ -500,6 +525,7 @@ void UnityScreen::OnLauncherHiddenChanged() void UnityScreen::paintPanelShadow(const GLMatrix& matrix) { +#ifndef USE_GLES if (relayoutSourceId > 0) return; @@ -559,6 +585,86 @@ void UnityScreen::paintPanelShadow(const GLMatrix& matrix) glDisable(GL_BLEND); } } +#else +#warning Panel shadow not properly implemented for GLES2 + return; + + if (relayoutSourceId > 0) + return; + + if (PluginAdapter::Default()->IsExpoActive()) + return; + + nuxPrologue(); + + CompOutput* output = _last_output; + float vc[4]; + float h = 20.0f; + float w = 1.0f; + float panel_h = 24.0f; + + float x1 = output->x(); + float y1 = output->y() + panel_h; + float x2 = x1 + output->width(); + float y2 = y1 + h; + + vc[0] = x1; + vc[1] = x2; + vc[2] = y1; + vc[3] = y2; + + if (!dash_is_open_ && panel_controller_->opacity() > 0.0f) + { + foreach(GLTexture * tex, _shadow_texture) + { + std::vector<GLfloat> vertexData; + std::vector<GLfloat> textureData; + std::vector<GLushort> colorData; + GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer(); + bool wasBlend = glIsEnabled(GL_BLEND); + + if (!wasBlend) + glEnable(GL_BLEND); + + GL::activeTexture(GL_TEXTURE0); + tex->enable(GLTexture::Fast); + + glTexParameteri(tex->target(), GL_TEXTURE_WRAP_S, GL_REPEAT); + + colorData = { 0xFFFF, 0xFFFF, 0xFFFF, + (GLushort)(panel_controller_->opacity() * 0xFFFF) + }; + + vertexData = { + vc[0], vc[2], 0, + vc[0], vc[3], 0, + vc[1], vc[2], 0, + vc[1], vc[3], 0, + }; + + textureData = { + COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), 0), + COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), h), + COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), 0), + COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), h), + }; + + streamingBuffer->begin(GL_TRIANGLE_STRIP); + + streamingBuffer->addColors(1, &colorData[0]); + streamingBuffer->addVertices(4, &vertexData[0]); + streamingBuffer->addTexCoords(0, 4, &textureData[0]); + + streamingBuffer->end(); + streamingBuffer->render(matrix); + + tex->disable(); + if (!wasBlend) + glDisable(GL_BLEND); + } + } + nuxEpilogue(); +#endif } void @@ -573,11 +679,16 @@ UnityWindow::updateIconPos (int &wx, wy = y + (last_bound.height - height) / 2; } +#ifdef USE_GLES +void UnityScreen::paintDisplay() +#else void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask) +#endif { CompOutput *output = _last_output; Window tray_xid = panel_controller_->GetTrayXid (); +#ifndef USE_GLES bool was_bound = _fbo->bound (); _fbo->unbind (); @@ -596,6 +707,11 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(), screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8); +#else + nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture = + nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (), + output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8); +#endif nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture; @@ -603,6 +719,13 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo nux::Geometry oGeo = nux::Geometry (output->x (), output->y (), output->width (), output->height ()); BackgroundEffectHelper::monitor_rect_ = geo; +#ifdef USE_GLES + GLint fboID; + // Nux renders to the referenceFramebuffer when it's embedded. + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fboID); + wt->GetWindowCompositor().SetReferenceFramebuffer(fboID, geo); +#endif + nuxPrologue(); _in_paint = true; wt->RenderInterfaceFromForeignCmd (&oGeo); @@ -617,36 +740,56 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo { GLMatrix oTransform; UnityWindow *uTrayWindow = UnityWindow::get (tray); +#ifndef USE_GLES GLFragment::Attrib attrib (uTrayWindow->gWindow->lastPaintAttrib()); +#else + GLWindowPaintAttrib attrib (uTrayWindow->gWindow->lastPaintAttrib()); +#endif unsigned int oldGlAddGeometryIndex = uTrayWindow->gWindow->glAddGeometryGetCurrentIndex (); unsigned int oldGlDrawIndex = uTrayWindow->gWindow->glDrawGetCurrentIndex (); +#ifndef USE_GLES unsigned int oldGlDrawGeometryIndex = uTrayWindow->gWindow->glDrawGeometryGetCurrentIndex (); +#endif +#ifndef USE_GLES attrib.setOpacity (OPAQUE); attrib.setBrightness (BRIGHT); attrib.setSaturation (COLOR); +#else + attrib.opacity = OPAQUE; + attrib.brightness = BRIGHT; + attrib.saturation = COLOR; +#endif oTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); +#ifndef USE_GLES glPushMatrix (); glLoadMatrixf (oTransform.getMatrix ()); +#endif painting_tray_ = true; /* force the use of the core functions */ uTrayWindow->gWindow->glDrawSetCurrentIndex (MAXSHORT); uTrayWindow->gWindow->glAddGeometrySetCurrentIndex ( MAXSHORT); +#ifndef USE_GLES uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (MAXSHORT); +#endif uTrayWindow->gWindow->glDraw (oTransform, attrib, infiniteRegion, PAINT_WINDOW_TRANSFORMED_MASK | PAINT_WINDOW_BLEND_MASK | PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK); +#ifndef USE_GLES uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (oldGlDrawGeometryIndex); +#endif uTrayWindow->gWindow->glAddGeometrySetCurrentIndex (oldGlAddGeometryIndex); uTrayWindow->gWindow->glDrawSetCurrentIndex (oldGlDrawIndex); painting_tray_ = false; +#ifndef USE_GLES glPopMatrix (); +#endif } } @@ -1009,6 +1152,7 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib, allowWindowPaint = true; _last_output = output; +#ifndef USE_GLES /* bind the framebuffer here * - it will be unbound and flushed * to the backbuffer when some @@ -1020,16 +1164,43 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib, * its bind reference so make sure that * you always unbind as much as you bind */ _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ())); +#endif /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */ ret = gScreen->glPaintOutput(attrib, transform, region, output, mask); +#ifndef USE_GLES if (doShellRepaint) paintDisplay(region, transform, mask); +#endif return ret; } +#ifdef USE_GLES +void UnityScreen::glPaintCompositedOutput (const CompRegion ®ion, + GLFramebufferObject *fbo, + unsigned int mask) +{ + bool useFbo = false; + + if (doShellRepaint) + { + oldFbo = fbo->bind (); + useFbo = fbo->checkStatus () && fbo->tex (); + if (!useFbo) { + printf ("bailing from UnityScreen::glPaintCompositedOutput"); + GLFramebufferObject::rebind (oldFbo); + return; + } + paintDisplay(); + GLFramebufferObject::rebind (oldFbo); + } + + gScreen->glPaintCompositedOutput(region, fbo, mask); +} +#endif + /* called whenever a plugin needs to paint the entire scene * transformed */ @@ -1111,7 +1282,9 @@ void UnityScreen::handleEvent(XEvent* event) PluginAdapter::Default()->OnScreenGrabbed(); else if (event->xfocus.mode == NotifyUngrab) PluginAdapter::Default()->OnScreenUngrabbed(); +#ifndef USE_GLES cScreen->damageScreen(); // evil hack +#endif if (_key_nav_mode_requested) launcher.startKeyNavMode(); _key_nav_mode_requested = false; @@ -1770,7 +1943,11 @@ bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib, * and if so paint nux and stop us from painting * other windows or on top of the whole screen */ bool UnityWindow::glDraw(const GLMatrix& matrix, +#ifndef USE_GLES GLFragment::Attrib& attrib, +#else + const GLWindowPaintAttrib& attrib, +#endif const CompRegion& region, unsigned int mask) { @@ -1786,7 +1963,11 @@ bool UnityWindow::glDraw(const GLMatrix& matrix, { if (xwns[i] == id) { +#ifdef USE_GLES + uScreen->paintDisplay(); +#else uScreen->paintDisplay(region, matrix, mask); +#endif break; } } @@ -2258,11 +2439,13 @@ void UnityScreen::Relayout() if (!needsRelayout) return; +#ifndef USE_GLES if (GL::fbo) { uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry)); uScreen->_fbo->onScreenSizeChanged (geometry); } +#endif UScreen *uscreen = UScreen::GetDefault(); int primary_monitor = uscreen->GetPrimaryMonitor(); @@ -2388,7 +2571,7 @@ void UnityScreen::InitHints() hints_.push_back(new shortcut::Hint(launcher, "", "", _("Switch applications via Launcher."), shortcut::HARDCODED_OPTION, "Super + Tab")); hints_.push_back(new shortcut::Hint(launcher, "", _(" + 1 to 9"), _("Same as clicking on a Launcher icon."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); hints_.push_back(new shortcut::Hint(launcher, "", _(" + Shift + 1 to 9"), _("Open new window of the app."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); - hints_.push_back(new shortcut::Hint(launcher, "", " + T", _("Open the Rubbish Bin."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); + hints_.push_back(new shortcut::Hint(launcher, "", " + T", _("Open the Trash."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); // Dash... std::string const dash = _("Dash"); diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index d81b1de29..adb8d800a 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -49,7 +49,9 @@ #include "DebugDBusInterface.h" #include "SwitcherController.h" #include "UBusWrapper.h" +#ifndef USE_GLES #include "ScreenEffectFramebufferObject.h" +#endif #include "compizminimizedwindowhandler.h" #include "BGHash.h" @@ -130,7 +132,11 @@ public: void nuxEpilogue(); /* nux draw wrapper */ +#ifdef USE_GLES + void paintDisplay(); +#else void paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask); +#endif void paintPanelShadow(const GLMatrix& matrix); void preparePaint (int ms); @@ -151,6 +157,11 @@ public: const CompRegion&, CompOutput*, unsigned int); +#ifdef USE_GLES + void glPaintCompositedOutput (const CompRegion ®ion, + GLFramebufferObject *fbo, + unsigned int mask); +#endif /* paint in the special case that the output is transformed */ void glPaintTransformedOutput(const GLScreenPaintAttrib&, @@ -302,8 +313,12 @@ private: unity::BGHash _bghash; +#ifdef USE_GLES + GLFramebufferObject *oldFbo; +#else ScreenEffectFramebufferObject::Ptr _fbo; GLuint _active_fbo; +#endif bool queryForShader (); @@ -314,7 +329,9 @@ private: bool painting_tray_; unsigned int tray_paint_mask_; +#ifndef USE_GLES ScreenEffectFramebufferObject::GLXGetProcAddressProc glXGetProcAddressP; +#endif friend class UnityWindow; }; @@ -351,7 +368,11 @@ public: /* basic window draw function */ bool glDraw(const GLMatrix& matrix, +#ifndef USE_GLES GLFragment::Attrib& attrib, +#else + const GLWindowPaintAttrib& attrib, +#endif const CompRegion& region, unsigned intmask); diff --git a/services/panel-service.c b/services/panel-service.c index faab66bf9..da0927954 100644 --- a/services/panel-service.c +++ b/services/panel-service.c @@ -31,6 +31,7 @@ #include <gdk/gdkx.h> #include <X11/extensions/XInput2.h> +#include <X11/XKBlib.h> #include "panel-marshal.h" @@ -249,7 +250,7 @@ event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self) if (event->evtype == XI_KeyRelease) { - if (XKeycodeToKeysym(event->display, event->detail, 0) == GDK_KEY_F10) + if (XkbKeycodeToKeysym(event->display, event->detail, 0, 0) == GDK_KEY_F10) { if (GTK_MENU (priv->last_menu)) gtk_menu_popdown (GTK_MENU (priv->last_menu)); diff --git a/standalone-clients/TestShortcut.cpp b/standalone-clients/TestShortcut.cpp index db8722494..8a658c115 100644 --- a/standalone-clients/TestShortcut.cpp +++ b/standalone-clients/TestShortcut.cpp @@ -42,7 +42,7 @@ void ThreadWidgetInit(nux::NThread* thread, void* InitData) hints.push_back(new shortcut::MockHint(_("Launcher"), "", "", _("Switch application via Launcher."), shortcut::HARDCODED_OPTION, "Super + Tab")); hints.push_back(new shortcut::MockHint(_("Launcher"), "", _(" + 1 to 9"), _("Same as clicking on a Launcher icon."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); hints.push_back(new shortcut::MockHint(_("Launcher"), "", _(" + Shift + 1 to 9"), _("Open a new window of the app."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); - hints.push_back(new shortcut::MockHint(_("Launcher"), "", " + T", _("Open the Rubbish Bin."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); + hints.push_back(new shortcut::MockHint(_("Launcher"), "", " + T", _("Open the Trash."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); // Dash... hints.push_back(new shortcut::MockHint(_("Dash"), "", _(" (Tap)"), _("Open the Dash Home."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e7620f209..94b4ac7b2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -185,10 +185,15 @@ if (GTEST_FOUND AND test_dashview_impl.cpp test_texture_cache.cpp test_main.cpp + test_icon_loader.cpp ${UNITY_SRC}/DashViewPrivate.cpp ${UNITY_SRC}/DashViewPrivate.h ${UNITY_SRC}/TextureCache.cpp ${UNITY_SRC}/TextureCache.h + ${UNITY_SRC}/IconLoader.cpp + ${UNITY_SRC}/IconLoader.h + ${UNITY_SRC}/Timer.cpp + ${UNITY_SRC}/Timer.h ) target_link_libraries(test-gtest ${GTEST_BOTH_LIBRARIES}) add_test(UnityGTest test-gtest) diff --git a/tests/test_icon_loader.cpp b/tests/test_icon_loader.cpp new file mode 100644 index 000000000..0c9a42a1b --- /dev/null +++ b/tests/test_icon_loader.cpp @@ -0,0 +1,191 @@ +/* + * Copyright 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Michal Hruby <michal.hruby@canonical.com> + */ + +#include <gmock/gmock.h> + +#include "IconLoader.h" + +using namespace testing; +using namespace unity; + +namespace +{ +bool IsValidPixbuf(GdkPixbuf *pixbuf) +{ + return GDK_IS_PIXBUF (pixbuf); +} + +gboolean TimeoutReached (gpointer data) +{ + bool *b = static_cast<bool*>(data); + + *b = true; + + return FALSE; +} + +struct LoadResult +{ + GdkPixbuf *pixbuf; + bool got_callback; + + LoadResult() : pixbuf(NULL), got_callback(false) {} + void IconLoaded(std::string const& icon_name, unsigned size, + GdkPixbuf *buf) + { + pixbuf = buf; + + got_callback = true; + } +}; + +TEST(TestIconLoader, TestGetDefault) +{ + // we need to initialize gtk + int args_cnt = 0; + gtk_init (&args_cnt, NULL); + + IconLoader::GetDefault(); +} + +TEST(TestIconLoader, TestGetOneIcon) +{ + LoadResult load_result; + IconLoader& icon_loader = IconLoader::GetDefault(); + volatile bool timeout_reached = false; + + icon_loader.LoadFromIconName("gedit-icon", 48, sigc::mem_fun(load_result, + &LoadResult::IconLoaded)); + + guint tid = g_timeout_add (10000, TimeoutReached, (gpointer)(&timeout_reached)); + while (!timeout_reached && !load_result.got_callback) + { + g_main_context_iteration (NULL, TRUE); + } + + EXPECT_TRUE(load_result.got_callback); + EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf)); + + g_source_remove (tid); +} + +TEST(TestIconLoader, TestGetManyIcons) +{ + std::vector<LoadResult> results; + IconLoader& icon_loader = IconLoader::GetDefault(); + volatile bool timeout_reached = false; + int i = 0; + int icon_count; + + GList *icons = gtk_icon_theme_list_icons (gtk_icon_theme_get_default (), + "Applications"); + // loading 100 icons should suffice + icon_count = MIN (100, g_list_length (icons)); + results.resize (icon_count); + for (GList *it = icons; it != NULL; it = it->next) + { + const char *icon_name = static_cast<char*>(it->data); + icon_loader.LoadFromIconName(icon_name, 48, sigc::mem_fun(results[i++], + &LoadResult::IconLoaded)); + if (i >= icon_count) break; + } + + guint tid = g_timeout_add (30000, TimeoutReached, (gpointer)(&timeout_reached)); + while (!timeout_reached) + { + g_main_context_iteration (NULL, TRUE); + bool all_loaded = true; + for (auto loader: results) + { + all_loaded &= loader.got_callback; + if (!all_loaded) break; + } + if (all_loaded) break; + } + + for (auto load_result: results) + { + EXPECT_TRUE(load_result.got_callback); + EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf)); + } + + g_source_remove (tid); +} + +TEST(TestIconLoader, TestCancelSome) +{ + std::vector<LoadResult> results; + std::vector<int> handles; + IconLoader& icon_loader = IconLoader::GetDefault(); + volatile bool timeout_reached = false; + int i = 0; + int icon_count; + + GList *icons = gtk_icon_theme_list_icons (gtk_icon_theme_get_default (), + "Emblems"); + // loading 100 icons should suffice + icon_count = MIN (100, g_list_length (icons)); + results.resize (icon_count); + handles.resize (icon_count); + for (GList *it = icons; it != NULL; it = it->next) + { + const char *icon_name = static_cast<char*>(it->data); + int handle = icon_loader.LoadFromIconName(icon_name, 48, sigc::mem_fun( + results[i], &LoadResult::IconLoaded)); + handles[i++] = handle; + if (i >= icon_count) break; + } + + // disconnect every other handler + for (i = 0; i < icon_count; i += 2) + { + icon_loader.DisconnectHandle(handles[i]); + } + + guint tid = g_timeout_add (30000, TimeoutReached, (gpointer)(&timeout_reached)); + while (!timeout_reached) + { + g_main_context_iteration (NULL, TRUE); + bool all_loaded = true; + for (int i = 1; i < icon_count; i += 2) + { + all_loaded &= results[i].got_callback; + if (!all_loaded) break; + } + if (all_loaded) break; + } + + for (i = 0; i < icon_count; i++) + { + if (i % 2) + { + EXPECT_TRUE(results[i].got_callback); + EXPECT_TRUE(IsValidPixbuf(results[i].pixbuf)); + } + else + { + EXPECT_FALSE(results[i].got_callback); + } + } + + g_source_remove (tid); +} + + +} diff --git a/tools/unity-introspection-visualiser.py b/tools/unity-introspection-visualiser.py new file mode 100755 index 000000000..fae236e2c --- /dev/null +++ b/tools/unity-introspection-visualiser.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +# +# Script to generate a nice PNG file of the currently running unity introspection tree. +from sys import argv +import dbus + +try: + from autopilot.emulators.unity import Unity +except ImportError: + print "Error: could not import the autopilot python module." + print "Make sure the autopilot module is in your $PYTHONPATH." + exit(1) + +try: + import pydot +except ImportError: + print "Error: the 'pydot' module is required to run this script." + print "Try installing the 'python-pydot' package." + exit(1) + +NEXT_NODE_ID=1 + +def string_rep(dbus_type): + """Get a string representation of various dbus types.""" + if type(dbus_type) == dbus.Boolean: + return repr(bool(dbus_type)) + if type(dbus_type) == dbus.String: + return str(dbus_type) + if type(dbus_type) in (dbus.Int16, dbus.UInt16, dbus.Int32, dbus.UInt32, dbus.Int64, dbus.UInt64): + return repr(int(dbus_type)) + if type(dbus_type) == dbus.Double: + return repr(float(dbus_type)) + if type(dbus_type) == dbus.Array: + return ', '.join([string_rep(i) for i in dbus_type]) + else: + return repr(dbus_type) + + +def escape(s): + """Escape a string so it can be use in a dot label.""" + return pydot.quote_if_necessary(s).replace('<','\\<').replace('>', '\\>') + + +def traverse_tree(state, parent, graph): + """Recursively traverse state tree, building dot graph as we go.""" + global NEXT_NODE_ID + lbl = parent.get_comment() + "|" + # first, set labels for this node: + bits = ["%s=%s" % (k, string_rep(state[k])) for k in state.keys() if k != 'Children'] + lbl += "\l".join(bits) + parent.set_label(escape('"{' + lbl + '}"')) + if state.has_key('Children'): + # Add all array nodes as children of this node. + for child_name, child_state in state['Children']: + child = pydot.Node(str(NEXT_NODE_ID)) + NEXT_NODE_ID+=1 + child.set_comment(child_name) + graph.add_node(child) + graph.add_edge(pydot.Edge(parent, child)) + + traverse_tree(child_state, child, graph) + + +if __name__ == '__main__': + if len(argv) != 2: + print """Usage: %s output_file.png. + +This script queries the currently running Unity process and dumps the entire +introspection tree into a graph, and renders this to a PNG file. +""" % (argv[0]) + exit(1) + + u = Unity() + introspection_tree = u.get_state() + graph = pydot.Dot() + graph.set_simplify(False) + graph.set_node_defaults(shape='Mrecord') + graph.set_fontname('Ubuntu') + graph.set_fontsize('10') + + gnode_unity = pydot.Node("Unity") + gnode_unity.set_comment("Unity") + traverse_tree(introspection_tree[0], gnode_unity, graph) + + graph.write(argv[1], format='png') + |
