Browse Source

Merge pull request #51 from linkdd/sticky-window

Sticky window
Martin Duquesnoy 12 years ago
parent
commit
eed683ca00
9 changed files with 113 additions and 3 deletions
  1. 22 1
      src/client.c
  2. 10 0
      src/client.h
  3. 3 0
      src/config.h
  4. 32 0
      src/ewmh.c
  5. 1 0
      src/ewmh.h
  6. 40 0
      src/infobar.c
  7. 2 0
      src/infobar.h
  8. 1 1
      src/layout.c
  9. 2 1
      src/wmfs.h

+ 22 - 1
src/client.c

@@ -972,12 +972,14 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
           client_apply_rule(c);
      }
 
+     ewmh_manage_state_sticky(c);
+
      /*
       * Conf option set per client, for possibility
       * to config only one client
       */
      c->border = c->theme->client_border_width;
-     if(!(c->tbarw = c->theme->client_titlebar_width))
+     if(!(c->tbarw = c->theme->client_titlebar_width) || (c->flags & CLIENT_STICKY))
           c->tbarw = c->border;
 
      c->ncol = c->theme->client_n;
@@ -1199,6 +1201,25 @@ client_moveresize(struct client *c, struct geo *g)
      client_configure(c);
 }
 
+void
+client_place_at_mouse(struct client *c)
+{
+     int x, y;
+
+     Window w;
+     int d, u;
+
+     XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (uint *)&u);
+
+     if(x < c->screen->ugeo.x)
+          x = 0;
+     if(y < c->screen->ugeo.y)
+          y = 0;
+
+     c->geo.x = ((x + c->geo.w) > c->screen->ugeo.w ? c->screen->ugeo.w - c->geo.w : x);
+     c->geo.y = ((y + c->geo.h) > c->screen->ugeo.h ? c->screen->ugeo.h - c->geo.h : y);
+}
+
 void
 client_maximize(struct client *c)
 {

+ 10 - 0
src/client.h

@@ -44,6 +44,7 @@ void client_geo_hints(struct geo *g, int *s);
 void client_get_sizeh(struct client *c);
 bool client_winsize(struct client *c, struct geo *geo);
 void client_moveresize(struct client *c, struct geo *g);
+void client_place_at_mouse(struct client *c);
 void client_maximize(struct client *c);
 void client_fac_resize(struct client *c, enum position p, int fac);
 void client_fac_adjust(struct client *c);
@@ -211,4 +212,13 @@ client_get_larger(struct tag *t, bool ignoring_tag)
      return lc;
 }
 
+static inline void
+clients_layout_refresh(void)
+{
+     struct client *c;
+
+     SLIST_FOREACH(c, &W->h.client, next)
+          layout_fix_hole(c);
+}
+
 #endif /* CLIENT_H */

+ 3 - 0
src/config.h

@@ -88,6 +88,9 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
      { "status" ,        uicb_status },
      { "status_surface", uicb_status_surface },
 
+     /* Infobar */
+     { "infobar_toggle_hide", uicb_infobar_toggle_hide },
+
      /* Mouse */
      { "mouse_resize", uicb_mouse_resize },
      { "mouse_move",   uicb_mouse_move },

+ 32 - 0
src/ewmh.c

@@ -227,6 +227,38 @@ ewmh_manage_state(long data[], struct client *c)
                     layout_fix_hole(c);
           }
      }
+
+}
+
+void
+ewmh_manage_state_sticky(struct client *c)
+{
+     Atom *atom, rf;
+     int f;
+     unsigned long n, il, i;
+     unsigned char *data = NULL;
+
+     if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_state], 0L, 0x7FFFFFFFL, false,
+                           XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
+     {
+          atom = (Atom*)data;
+
+          for(i = 0; i < n; ++i)
+          {
+               /* manage _NET_WM_STATE_STICKY */
+               if(atom[i] == W->net_atom[net_wm_state_sticky])
+               {
+                    c->flags |= CLIENT_STICKY;
+                    c->flags |= CLIENT_FREE;
+
+                    client_place_at_mouse(c);
+
+                    break;
+               }
+          }
+
+          XFree(data);
+     }
 }
 
 void

+ 1 - 0
src/ewmh.h

@@ -124,6 +124,7 @@ void ewmh_get_client_list(void);
 long ewmh_get_xembed_state(Window win);
 void ewmh_update_wmfs_props(void);
 void ewmh_manage_state(long data[], struct client *c);
+void ewmh_manage_state_sticky(struct client *c);
 void ewmh_manage_window_type(struct client *c);
 bool ewmh_manage_window_type_desktop(Window win);
 

+ 40 - 0
src/infobar.c

@@ -515,8 +515,48 @@ infobar_free(struct screen *s)
      }
 }
 
+void
+uicb_infobar_toggle_hide(Uicb iname)
+{
+     struct infobar *i;
 
+     if (iname)
+          i = infobar_gb_name(iname);
+     else
+          i = SLIST_FIRST(&W->screen->infobars);
 
+     if(i->pos == BarHide)
+     {
+          i->pos = i->opos;
 
+          if(infobar_placement(i, i->pos))
+          {
+               barwin_map(i->bar);
+               barwin_map_subwin(i->bar);
+               barwin_refresh_color(i->bar);
+               infobar_refresh(i);
+          }
+     }
+     else
+     {
+          i->opos = i->pos;
+          i->pos = BarHide;
+
+          barwin_unmap_subwin(i->bar);
+          barwin_unmap(i->bar);
+
+          switch(i->opos)
+          {
+               case BarTop:
+                    i->screen->ugeo.y -= i->geo.h;
+               case BarBottom:
+                    i->screen->ugeo.h += i->geo.h;
+               case BarHide:
+               default:
+                    break;
+          }
+     }
 
+     clients_layout_refresh();
+}
 

+ 2 - 0
src/infobar.h

@@ -88,4 +88,6 @@ infobar_gb_name(const char *name)
      return SLIST_FIRST(&s->infobars);
 }
 
+void uicb_infobar_toggle_hide(Uicb iname);
+
 #endif /* INFOBAR_H */

+ 1 - 1
src/layout.c

@@ -631,7 +631,7 @@ layout_client(struct client *c)
           return;
      }
 
-     if(c->flags & CLIENT_FREE)
+     if(c->flags & (CLIENT_FREE | CLIENT_STICKY))
      {
           layout_split_arrange_closed(c);
           c->flags ^= CLIENT_TILED;

+ 2 - 1
src/wmfs.h

@@ -151,7 +151,7 @@ struct infobar
      struct screen *screen;
      struct theme *theme;
      struct status_ctx statusctx;
-     enum barpos pos;
+     enum barpos opos, pos;
      char *elemorder;
      char *name;
      TAILQ_HEAD(esub, element) elements;
@@ -217,6 +217,7 @@ struct client
 #define CLIENT_TILED         0x2000
 #define CLIENT_MOUSE         0x4000
 #define CLIENT_IGNORE_TAG    0x8000
+#define CLIENT_STICKY        0x10000
      Flags flags;
      Window win, frame, tmp;
      SLIST_ENTRY(client) next;   /* Global list */