From: Dana Jansens Date: Fri, 11 Jun 2010 19:52:27 +0000 (-0400) Subject: support for _NET_WM_WINDOW_OPACITY X-Git-Tag: cgl~35 X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=1f9da9d387f39ca33d47d64d23262ad0c841b841;p=dana%2Fopenbox.git support for _NET_WM_WINDOW_OPACITY --- diff --git a/obt/prop.c b/obt/prop.c index bef9c999..34e63a03 100644 --- a/obt/prop.c +++ b/obt/prop.c @@ -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); */ diff --git a/obt/prop.h b/obt/prop.h index 7ccc218e..852805cf 100644 --- a/obt/prop.h +++ b/obt/prop.h @@ -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, */ diff --git a/openbox/client.c b/openbox/client.c index 5c19684a..2b8842c9 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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; diff --git a/openbox/client.h b/openbox/client.h index 6f2aad54..7aa73e11 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -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). diff --git a/openbox/composite.c b/openbox/composite.c index 3d79b88a..8cc19425 100644 --- a/openbox/composite.c +++ b/openbox/composite.c @@ -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 { diff --git a/openbox/dock.c b/openbox/dock.c index b54ed437..606a8b73 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -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)); diff --git a/openbox/event.c b/openbox/event.c index b9bb5c0f..553c2219 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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; diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c index 3de68d67..661ac25a 100644 --- a/openbox/focus_cycle_popup.c +++ b/openbox/focus_cycle_popup.c @@ -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)); diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 9413e800..2f7d2b5d 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -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)); diff --git a/openbox/popup.c b/openbox/popup.c index 297fc529..1045cadf 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -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)); diff --git a/openbox/screen.c b/openbox/screen.c index 249b456a..201ce342 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -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); diff --git a/openbox/unmanaged.c b/openbox/unmanaged.c index edd04b87..8050210b 100644 --- a/openbox/unmanaged.c +++ b/openbox/unmanaged.c @@ -20,13 +20,14 @@ #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; +} diff --git a/openbox/unmanaged.h b/openbox/unmanaged.h index 7b0028c2..33a0fd2e 100644 --- a/openbox/unmanaged.h +++ b/openbox/unmanaged.h @@ -30,4 +30,6 @@ void unmanaged_destroy(ObUnmanaged *self); void unmanaged_destroy_all(void); +void unmanaged_update_opacity(ObUnmanaged *self); + #endif diff --git a/openbox/window.c b/openbox/window.c index 13ba0658..31cf039a 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -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; } diff --git a/openbox/window.h b/openbox/window.h index 02de98d0..e01bea5c 100644 --- a/openbox/window.h +++ b/openbox/window.h @@ -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() */