support for _NET_WM_WINDOW_OPACITY
authorDana Jansens <danakj@orodu.net>
Fri, 11 Jun 2010 19:52:27 +0000 (15:52 -0400)
committerDana Jansens <danakj@orodu.net>
Sat, 26 Jun 2010 23:30:49 +0000 (01:30 +0200)
15 files changed:
obt/prop.c
obt/prop.h
openbox/client.c
openbox/client.h
openbox/composite.c
openbox/dock.c
openbox/event.c
openbox/focus_cycle_popup.c
openbox/menuframe.c
openbox/popup.c
openbox/screen.c
openbox/unmanaged.c
openbox/unmanaged.h
openbox/window.c
openbox/window.h

index bef9c9996d4d091707d7cf9ed4b0016c6da7025d..34e63a039203c4c51a1906cdfa807719645f0f00 100644 (file)
@@ -105,6 +105,7 @@ void obt_prop_startup(void)
     CREATE_(NET_WM_ICON);
     CREATE_(NET_WM_ICON_GEOMETRY);
     CREATE_(NET_WM_PID);
+    CREATE_(NET_WM_WINDOW_OPACITY);
     CREATE_(NET_WM_ALLOWED_ACTIONS);
     CREATE_(NET_WM_USER_TIME);
 /*  CREATE_(NET_WM_USER_TIME_WINDOW); */
index 7ccc218e195ab1d0a09debcc101b0746ddf610e8..852805cfca6cc2a9286525d30a406f2d051409d1 100644 (file)
@@ -145,6 +145,7 @@ typedef enum {
     OBT_PROP_NET_WM_ICON,
     OBT_PROP_NET_WM_ICON_GEOMETRY,
     OBT_PROP_NET_WM_PID,
+    OBT_PROP_NET_WM_WINDOW_OPACITY,
     OBT_PROP_NET_WM_ALLOWED_ACTIONS,
     OBT_PROP_NET_WM_USER_TIME,
 /*  OBT_PROP_NET_WM_USER_TIME_WINDOW, */
index 5c19684a6890bed2819ac6d86da52919caa5be55..2b8842c9300056700d26b2e566e4ad9be58f6b42 100644 (file)
@@ -253,10 +253,15 @@ void client_manage(Window window, ObPrompt *prompt)
     /* create the decoration frame for the client window */
     self->frame = frame_new(self);
 
+    /* this must occur after the frame exists, since we copy the opacity value
+       onto the frame */
+    client_update_opacity(self);
+
     window_set_abstract(CLIENT_AS_WINDOW(self),
                         &self->frame->window, /* top level window */
                         &self->layer,         /* stacking layer */
-                        &self->frame->depth); /* window depth */
+                        &self->frame->depth,  /* window depth */
+                        &self->alpha);        /* opacity */
 
     frame_grab_client(self->frame);
 
@@ -528,7 +533,8 @@ ObClient *client_fake_manage(Window window)
     window_set_abstract(CLIENT_AS_WINDOW(self),
                         &self->frame->window, /* top level window */
                         &self->layer,         /* stacking layer */
-                        &self->frame->depth); /* window depth */
+                        &self->frame->depth,  /* window depth */
+                        NULL);                /* opacity */
 
     frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
 
@@ -2251,6 +2257,21 @@ void client_update_icon_geometry(ObClient *self)
     }
 }
 
+void client_update_opacity(ObClient *self)
+{
+    /* The alpha value is to be copied from the client onto its top-level
+       window for third-party compositing managers to see */
+    if (!OBT_PROP_GET32(self->window, NET_WM_WINDOW_OPACITY, CARDINAL,
+                        &self->alpha))
+    {
+        self->alpha = 0xffffffff;
+        OBT_PROP_ERASE(self->frame->window, NET_WM_WINDOW_OPACITY);
+    }
+    else
+        OBT_PROP_SET32(self->frame->window, NET_WM_WINDOW_OPACITY, CARDINAL,
+                       self->alpha);
+}
+
 static void client_get_session_ids(ObClient *self)
 {
     guint32 leader;
index 6f2aad5420301213dedf5c448e069f720ca6d3ee..7aa73e112fa566c9b792ff358dc4ead8e7ce0c58 100644 (file)
@@ -120,6 +120,8 @@ struct _ObClient
     gchar *wm_command;
     /*! The PID of the process which owns the window */
     pid_t pid;
+    /*! The opacity for the window. 0 is transparent, 0xffffffff is opaque */
+    guint32 alpha;
 
     /*! The application that created the window */
     gchar *name;
@@ -633,6 +635,8 @@ void client_update_strut(ObClient *self);
 void client_update_icons(ObClient *self);
 /*! Updates the window's icon geometry (where to iconify to/from) */
 void client_update_icon_geometry(ObClient *self);
+/*! Updates the window's opacity */
+void client_update_opacity(ObClient *client);
 
 /*! Set up what decor should be shown on the window and what functions should
   be allowed (ObClient::decorations and ObClient::functions).
index 3d79b88a895a76bf5dc70419d50f6f99c7112423..8cc19425da4d32b1e0cd2e97d5e23c905213e081 100644 (file)
@@ -562,6 +562,9 @@ static gboolean composite(gpointer data)
         w = win->area.width + win->border * 2;
         h = win->area.height + win->border * 2;
 
+        if (win->alpha && *win->alpha < 0xffffffff)
+            glColor4ui(0xffffffff, 0xffffffff, 0xffffffff, *win->alpha);
+
         glBegin(GL_QUADS);
         glTexCoord2f(0, 0);
         glVertex3f(x, y, 0.0);
@@ -572,6 +575,10 @@ static gboolean composite(gpointer data)
         glTexCoord2f(1, 0);
         glVertex3f(x + w, y, 0.0);
         glEnd();
+
+        if (win->alpha && *win->alpha < 0xffffffff)
+            glColor4f(1.0, 1.0, 1.0, 1.0);
+
         cglXReleaseTexImage(obt_display, win->gpixmap, GLX_FRONT_LEFT_EXT);
     }
 
@@ -579,7 +586,7 @@ static gboolean composite(gpointer data)
     glFinish();
 
     if (ob_comp_indirect)
-        g_usleep(5000);
+        g_usleep(1000);
 
 #ifdef DEBUG
     {
index b54ed437ac4b759ba707cd0f5419664d72cbc91d..606a8b7346b027e132aa9c83438e7797a7416a86 100644 (file)
@@ -112,7 +112,8 @@ void dock_startup(gboolean reconfig)
     window_set_abstract(DOCK_AS_WINDOW(dock),
                         &dock->frame,         /* top level window */
                         &config_dock_layer,   /* stacking layer */
-                        &dock->depth);        /* window depth */
+                        &dock->depth,         /* window depth */
+                        NULL);
 
     window_add(&dock->frame, DOCK_AS_WINDOW(dock));
     stacking_add(DOCK_AS_WINDOW(dock));
index b9bb5c0f0c6246863db787a9bef014b4072195ff..553c2219e7cb638c253093f44814e754aa10e80b 100644 (file)
@@ -1754,6 +1754,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 moveresize_end(FALSE);
             client_update_sync_request_counter(client);
         }
+        else if (msgtype == OBT_PROP_ATOM(NET_WM_WINDOW_OPACITY))
+            client_update_opacity(client);
 #endif
         break;
     case ColormapNotify:
@@ -1806,6 +1808,10 @@ static void event_handle_unmanaged(ObUnmanaged *um, XEvent *e)
     Window w;
 
     switch (e->type) {
+    case PropertyNotify:
+        if (e->xproperty.atom == OBT_PROP_ATOM(NET_WM_WINDOW_OPACITY))
+            unmanaged_update_opacity(um);
+        break;
     case DestroyNotify:
         unmanaged_destroy(um);
         break;
index 3de68d67f131aad05d8f65c79a87af1e636c389c..661ac25a72b2f3348e86fa39e8ff48055a18fd5e 100644 (file)
@@ -212,7 +212,8 @@ void focus_cycle_popup_startup(gboolean reconfig)
     window_set_abstract(INTERNAL_AS_WINDOW(popup),
                         &popup->bg,
                         &popup->layer,
-                        &popup->depth);
+                        &popup->depth,
+                        NULL);
 
     stacking_add(INTERNAL_AS_WINDOW(popup));
     window_add(&popup->bg, INTERNAL_AS_WINDOW(popup));
index 9413e8008113fc8c3e7c89bdf558fd10f276d484..2f7d2b5de0b76ecfe78c3f055e4439d048495697 100644 (file)
@@ -136,7 +136,8 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
     window_set_abstract(MENUFRAME_AS_WINDOW(self),
                         &self->window,        /* top level window */
                         &self->layer,         /* stacking layer */
-                        &self->depth);        /* window depth */
+                        &self->depth,         /* window depth */
+                        NULL);                /* opacity */
 
     window_add(&self->window, MENUFRAME_AS_WINDOW(self));
     stacking_add(MENUFRAME_AS_WINDOW(self));
index 297fc529705e9489edcbb04fb4f3ad990ec35d6c..1045cadfc957bb1d5234986fcc289a8d48a89e60 100644 (file)
@@ -61,7 +61,8 @@ ObPopup *popup_new(void)
     window_set_abstract(INTERNAL_AS_WINDOW(self),
                         &self->bg,      /* top level window */
                         &self->layer,   /* stacking layer */
-                        &self->depth);  /* window depth */
+                        &self->depth,   /* window depth */
+                        NULL);          /* opacity */
 
     stacking_add(INTERNAL_AS_WINDOW(self));
     window_add(&self->bg, INTERNAL_AS_WINDOW(self));
index 249b456a03533e0664f4fcb8c9c19cc050eaf4c0..201ce34292745c310a43887a4f427e2ada717b45 100644 (file)
@@ -290,6 +290,7 @@ gboolean screen_annex(void)
     supported[i++] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST_COUNTER);
 #endif
     supported[i++] = OBT_PROP_ATOM(NET_WM_PID);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_OPACITY);
     supported[i++] = OBT_PROP_ATOM(NET_WM_PING);
 
     supported[i++] = OBT_PROP_ATOM(KDE_WM_CHANGE_STATE);
index edd04b8770c411909f06ea19b6412f5e72dc0b0a..8050210bf5880d328e09e3ac758a2675fe24f910 100644 (file)
 #include "composite.h"
 #include "window.h"
 #include "obt/display.h"
+#include "obt/prop.h"
 
 struct _ObUnmanaged {
     ObWindow super;
-    Window win;
+    Window window;
     ObStackingLayer layer;
     gint depth;
-
+    guint32 alpha;
 };
 
 static GSList *unmanaged_list = NULL;
@@ -44,16 +45,22 @@ ObUnmanaged* unmanaged_new(Window w)
         return NULL;
 
     self = window_new(OB_WINDOW_CLASS_UNMANAGED, ObUnmanaged);
-    self->win = w;
+    self->window = w;
     self->layer = OB_STACKING_LAYER_ALL;
     self->depth = at.depth;
+    self->alpha = 0xffffffff;
+
+    XSelectInput(obt_display, self->window, PropertyChangeMask);
+
+    unmanaged_update_opacity(self);
     
     window_set_abstract(UNMANAGED_AS_WINDOW(self),
-                        &self->win,
+                        &self->window,
                         &self->layer,
-                        &self->depth);
+                        &self->depth,
+                        &self->alpha);
 
-    window_add(&self->win, UNMANAGED_AS_WINDOW(self));
+    window_add(&self->window, UNMANAGED_AS_WINDOW(self));
     stacking_add(UNMANAGED_AS_WINDOW(self));
     unmanaged_list = g_slist_prepend(unmanaged_list, self);
 
@@ -62,10 +69,12 @@ ObUnmanaged* unmanaged_new(Window w)
 
 void unmanaged_destroy(ObUnmanaged *self)
 {
+    XSelectInput(obt_display, self->window, NoEventMask);
+
     window_cleanup(UNMANAGED_AS_WINDOW(self));
     unmanaged_list = g_slist_remove(unmanaged_list, self);
     stacking_remove(UNMANAGED_AS_WINDOW(self));
-    window_remove(self->win);
+    window_remove(self->window);
     window_free(UNMANAGED_AS_WINDOW(self));
 }
 
@@ -74,3 +83,10 @@ void unmanaged_destroy_all(void)
     while (unmanaged_list)
         unmanaged_destroy(unmanaged_list->data);
 }
+
+void unmanaged_update_opacity(ObUnmanaged *self)
+{
+    if (!OBT_PROP_GET32(self->window, NET_WM_WINDOW_OPACITY, CARDINAL,
+                        &self->alpha))
+        self->alpha = 0xffffffff;
+}
index 7b0028c28d3259279b0d9d7130a9f13f10d2678c..33a0fd2ee61794cea740cd171d7219fe0399a099 100644 (file)
@@ -30,4 +30,6 @@ void unmanaged_destroy(ObUnmanaged *self);
 
 void unmanaged_destroy_all(void);
 
+void unmanaged_update_opacity(ObUnmanaged *self);
+
 #endif
index 13ba0658acff1a3dc6d6c28ee2e7e791747762c6..31cf039a47a056c7b8e244fdfefac77c28b1a5c9 100644 (file)
@@ -64,11 +64,15 @@ ObWindow* window_new_size(ObWindowClass type, gsize size)
 void window_set_abstract(ObWindow *self,
                          const Window *top,
                          const ObStackingLayer *layer,
-                         const int *depth)
+                         const int *depth,
+                         const guint32 *alpha)
 {
+    g_assert(!self->top && !self->layer && !self->depth && !self->alpha);
+
     self->top = top;
     self->layer = layer;
     self->depth = depth;
+    self->alpha = alpha;
 
     /* set up any things in ObWindow that require use of the abstract pointers
        now */
@@ -126,9 +130,10 @@ ObInternalWindow* window_internal_new(Window window, int depth)
     self->layer = OB_STACKING_LAYER_INTERNAL;
     self->depth = depth;
     window_set_abstract(INTERNAL_AS_WINDOW(self),
-                        &self->window,
-                        &self->layer,
-                        &self->depth);
+                        &self->window, /* top-most window */
+                        &self->layer,  /* stacking layer */
+                        &self->depth,  /* window depth */
+                        NULL);         /* opacity */
     return self;
 }
 
index 02de98d0de4b76d49759524f9ff7d30bf6878f17..e01bea5c148caa68baaff341373a013d292f4629 100644 (file)
@@ -55,9 +55,12 @@ struct _ObWindow {
     const Window *top;
     /*! Points to the stacking layer for the ObWindow */
     const ObStackingLayer *layer;
-    /*! Points to the position and size occupied by the ObWindow */
     /*! Points to the depth of the ObWindow */
     const int *depth;
+    /*! Points to the alpha the ObWindow.
+      0xffffffff is completely transparent, 0 is opaque.  If this is NULL,
+      then the window will be considered opaque. */
+    const guint32 *alpha;
 
 #ifdef USE_COMPOSITING
     GLuint texture;
@@ -114,7 +117,8 @@ ObWindow* window_new_size(ObWindowClass type, gsize size);
 void      window_set_abstract(ObWindow *self,
                               const Window *top,
                               const ObStackingLayer *layer,
-                              const int *depth);
+                              const int *depth,
+                              const guint32 *alpha);
 /*! A subclass of ObWindow must call this when it is going to be destroying
   itself, but _before_ it destroys the members it sets in
   window_set_abstract() */