Home > Uncategorized > Removing decorations in Metacity

Removing decorations in Metacity

I switched to gnome and I miss one wonderful feature of kwin. By combining always on top and remove decoration, kwin allow to transform any window into a kind of post-it embedded into an other window. For example I use it to add an xterm in Netbeans. I don’t know any other window manager than kwin being able to hide decoration with a hot key.

From Devil’s pie source code I found that it was possible to remove decoration using the _MOTIF_WM_HINTS window property. It first tried it with the xprop command, but I had some trouble to handle the maximized window case. Then I found the Ralf Neupert wmctrl patch. I used it as inspiration to write my wmctrl patch, which toggle decoration and ensure that maximized window spread on the whole screen. See the patch bellow.

Metacity have a built-in support for binding custom action to shortcut. In gconf-editor:

  • /apps/metacity/keybinding_commands/command_1 = wmctrl -r :ACTIVE: -B
  • /apps/metacity/global_keybindings/run_command_1 = <mod4>H

A first implementation in shell script using the xprop command. It doesn’t handle the maximized window case.

#! /bin/sh -x
winid=$(xprop -root | awk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}')
current=$(xprop -id $winid | awk '/_MOTIF_WM_HINTS/ { sub(/,/,"",$5); print $5 }')
if [ -z $current ]; then
    current=0;
else
    current=$((1-$current))
fi

xprop -id $winid -f _MOTIF_WM_HINTS 32c -set _MOTIF_WM_HINTS "0x2, 0x0, $current, 0x0, 0x0"

This is a patch to wmctrl, adapted from Ralf one. It ensure that window keep it’s maximized status:

--- /tmp/wmctrl-1.07/main.c	2009-05-22 19:58:19.000000000 +0200
+++ main.c	2009-04-12 16:51:40.000000000 +0200
@@ -264,7 +264,7 @@
         }
     }
    
-    while ((opt = getopt(argc, argv, "FGVvhlupidmxa:r:s:c:t:w:k:o:n:g:e:b:N:I:T:R:")) != -1) {
+    while ((opt = getopt(argc, argv, "BFGVvhlupidmxa:r:s:c:t:w:k:o:n:g:e:b:N:I:T:R:")) != -1) {
         missing_option = 0;
         switch (opt) {
             case 'F':
@@ -356,7 +356,7 @@
             ret = wm_info(disp);
             break;
         case 'a': case 'c': case 'R': 
-        case 't': case 'e': case 'b': case 'N': case 'I': case 'T':
+	case 't': case 'e': case 'b': case 'N': case 'I': case 'T': case 'B':
             if (! options.param_window) {
                 fputs("No window was specified.\n", stderr);
                 return EXIT_FAILURE;
@@ -874,6 +874,83 @@
     }
 }/*}}}*/
 
+static int switch_decoration (Display *disp, Window win) {
+    #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
+    #define MWM_HINTS_DECORATIONS (1L << 1)
+    struct {
+        unsigned long flags;
+        unsigned long functions;
+        unsigned long decorations;
+        long inputMode;
+        unsigned long status;
+    } hints = {0,};
+
+    Atom mA = XInternAtom(disp, "_MOTIF_WM_HINTS", False);
+    Atom sA = XInternAtom(disp, "_NET_WM_STATE", False);
+    //Atom maximizedHorzAtom = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+    Atom maximizedVertAtom = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+    Atom actual_type_return;
+    int actual_format_return;
+    int max=0;
+    int i;
+    unsigned long nitems_return;
+    unsigned long bytes_after_return;
+    unsigned long *prop_return;
+    int x, y, junkx, junky;
+    unsigned int wwidth, wheight, bw, depth;
+    Window junkroot;
+
+    //check if the window is maxmized
+    XGetWindowProperty(disp, win, sA, 0, PROP_MOTIF_WM_HINTS_ELEMENTS, 0,
+        AnyPropertyType, &actual_type_return, &actual_format_return,
+        &nitems_return, &bytes_after_return, &prop_return);
+
+    for(i = 0; i < nitems_return; i++)
+    {
+        if(prop_return[i] == maximizedVertAtom)
+            max = 1;
+    }
+
+    //get the window size
+    XGetGeometry (disp, win, &junkroot, &junkx, &junky,
+                      &wwidth, &wheight, &bw, &depth);
+    XTranslateCoordinates (disp, win, junkroot, junkx, junky,
+                           &x, &y, &junkroot);
+    wwidth += junkx;
+    wheight += junky;
+
+    //check the decoration stats
+    XGetWindowProperty(disp, win, mA, 0, PROP_MOTIF_WM_HINTS_ELEMENTS, 0, mA,
+        &actual_type_return, &actual_format_return, &nitems_return,
+        &bytes_after_return, &prop_return);
+
+    if(nitems_return >= 3)
+        hints.decorations = 1 ^ prop_return[2];
+    else
+        hints.decorations = 0;
+   
+    //fix the window size so it does'nt move after removing the border
+    if(!max)
+    {
+        if(!hints.decorations)
+            XMoveWindow(disp, win, x+junkx, y+junky);
+        else
+            XMoveWindow(disp, win, x-junkx, y-junky);
+    }
+
+    // show/hide borders
+    hints.flags = MWM_HINTS_DECORATIONS;
+    XChangeProperty(disp, win, mA, mA, 32, PropModeReplace,
+        (unsigned char *)&hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
+
+    //Ensure the window is still maximized
+    if(max)
+        XResizeWindow(disp, win, wwidth, wheight);
+
+    activate_window (disp, win, 0);
+    return EXIT_SUCCESS;
+}
+
 static int action_window (Display *disp, Window win, char mode) {/*{{{*/
     p_verbose("Using window: 0x%.8lx\n", win);
     switch (mode) {
@@ -909,7 +986,8 @@
         case 'N': case 'I': case 'T':
             window_set_title(disp, win, options.param, mode);
             return EXIT_SUCCESS;
-
+        case 'B':
+	    return switch_decoration(disp, win);
         default:
             fprintf(stderr, "Unknown action: '%c'\n", mode);
             return EXIT_FAILURE;
Categories: Uncategorized Tags: , ,
  1. Chris
    May 21, 2009 at 3:08 pm | #1

    Hi, I compiled wmctrl 1.07 with your patch but failed.

    Here is the message, I’m using Gentoo with gcc 4.4 and gcc 4.3.3.
    Thanks!

    main.c:672: warning: pointer targets in passing argument 7 of ‘XChangeProperty’ differ in signedness
    /usr/include/X11/Xlib.h:2086: note: expected ‘const unsigned char *’ but argument is of type ‘gchar *’
    main.c: In function ‘switch_decoration’:
    main.c:906: warning: passing argument 12 of ‘XGetWindowProperty’ from incompatible pointer type
    /usr/include/X11/Xlib.h:2694: note: expected ‘unsigned char **’ but argument is of type ‘long unsigned int **’
    main.c:908: warning: suggest parentheses around assignment used as truth value
    main.c:910: error: ‘else’ without a previous ‘if’
    main.c:901: warning: unused variable ‘junkroot’
    main.c:900: warning: unused variable ‘depth’
    main.c:900: warning: unused variable ‘bw’
    main.c:891: warning: unused variable ‘maximizedVertAtom’
    make: *** [main.o] Error 1
    *
    * ERROR: x11-misc/wmctrl-1.07-r1 failed.
    * Call stack:
    * ebuild.sh, line 49: Called src_compile
    * environment, line 2267: Called _eapi0_src_compile
    * ebuild.sh, line 600: Called _eapi2_src_compile
    * ebuild.sh, line 634: Called die
    * The specific snippet of code:
    * emake || die “emake failed”
    * The die message:
    * emake failed
    *
    * If you need support, post the topmost build error, and the call stack if relevant.
    * A complete build log is located at ‘/data/tmp/portage/x11-misc/wmctrl-1.07-r1/temp/build.log’.
    * The ebuild environment file is located at ‘/data/tmp/portage/x11-misc/wmctrl-1.07-r1/temp/environment’.
    *

  2. xrunhprof
    May 21, 2009 at 6:20 pm | #2

    Oops my patch was messed up after the c/c in WordPress. The operators were interpreted as HTML tags. I will fix this tomorow or the day after.

  3. Chris
    May 22, 2009 at 6:34 am | #3

    Hi, just report back, removed following lines from patch and got wmctrl compiled.

    + for(i = 0; i = 3)
    + hints.decorations = 1 ^ prop_return[2];
    + else
    + hints.decorations = 0;

    I think it works now, Thank you!

    But I still have a problem, it might have nothing to do with your patch.

    I’m using gnome and metacity, wmctrl -B could remove the decoration of the window, but if I switch to another workspace then switch back, decoration get restored.

    I tried devilspie, same behavior.

    Thanks again.

  4. xrunhprof
    May 22, 2009 at 6:14 pm | #4

    I didn’t notice this problem as I only use one desktop. Anyway I fixed the patch.

  5. Chris
    May 24, 2009 at 1:38 pm | #5

    I recompiled wmctrl again, and seems -B didn’t remove decoration anymore…
    The window just don’t change.
    And I didn’t keep your old patch so I am not sure what’s the problem, could you verify that?

    Thank you.

  6. Rob
    November 11, 2009 at 7:04 pm | #6

    I updated the patch for wmctrl-1.07-6 in Ubuntu Karmic Koala:

    — wmctrl-1.07/main.c 2009-11-11 14:01:01.000000000 -0500
    +++ wmctrl-1.07-patched/main.c 2009-11-11 13:58:30.000000000 -0500
    @@ -264,7 +264,7 @@
    }
    }

    - while ((opt = getopt(argc, argv, “FGVvhlupidmxa:r:s:c:t:w:k:o:n:g:e:b:N:I:T:R:”)) != -1) {
    + while ((opt = getopt(argc, argv, “BFGVvhlupidmxa:r:s:c:t:w:k:o:n:g:e:b:N:I:T:R:”)) != -1) {
    missing_option = 0;
    switch (opt) {
    case ‘F’:
    @@ -356,7 +356,7 @@
    ret = wm_info(disp);
    break;
    case ‘a’: case ‘c’: case ‘R’:
    - case ‘t’: case ‘e’: case ‘b’: case ‘N’: case ‘I’: case ‘T’:
    + case ‘t’: case ‘e’: case ‘b’: case ‘N’: case ‘I’: case ‘T’: case ‘B’:
    if (! options.param_window) {
    fputs(“No window was specified.\n”, stderr);
    return EXIT_FAILURE;
    @@ -874,6 +874,85 @@
    }
    }/*}}}*/

    +static int switch_decoration (Display *disp, Window win) {
    + #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
    + #define MWM_HINTS_DECORATIONS (1L << 1)
    + struct {
    + unsigned long flags;
    + unsigned long functions;
    + unsigned long decorations;
    + long inputMode;
    + unsigned long status;
    + } hints = {0,};
    +
    + Atom mA = XInternAtom(disp, "_MOTIF_WM_HINTS", False);
    + Atom sA = XInternAtom(disp, "_NET_WM_STATE", False);
    + //Atom maximizedHorzAtom = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
    + Atom maximizedVertAtom = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_VERT", False);
    + Atom actual_type_return;
    + int actual_format_return;
    + int max=0;
    + int i;
    + unsigned long nitems_return;
    + unsigned long bytes_after_return;
    + unsigned long *prop_return;
    + int x, y, junkx, junky;
    + unsigned int wwidth, wheight, bw, depth;
    + Window junkroot;
    +
    + //check if the window is maxmized
    + XGetWindowProperty(disp, win, sA, 0, PROP_MOTIF_WM_HINTS_ELEMENTS, 0,
    + AnyPropertyType, &actual_type_return, &actual_format_return,
    + &nitems_return, &bytes_after_return, &prop_return);
    +
    + for(i = 0; i = 3)
    + hints.decorations = 1 ^ prop_return[2];
    + else
    + hints.decorations = 0;
    +
    + //fix the window size so it does’nt move after removing the border
    + if(!max)
    + {
    + if(!hints.decorations)
    + // For some reason removing the border needs to move the
    + // window left as well.
    + XMoveWindow(disp, win, x-junkx, y-junky);
    + else
    + XMoveWindow(disp, win, x-junkx, y-junky);
    + }
    +
    + // show/hide borders
    + hints.flags = MWM_HINTS_DECORATIONS;
    + XChangeProperty(disp, win, mA, mA, 32, PropModeReplace,
    + (unsigned char *)&hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
    +
    + //Ensure the window is still maximized
    + if(max)
    + XResizeWindow(disp, win, wwidth, wheight);
    +
    + activate_window (disp, win, 0);
    + return EXIT_SUCCESS;
    +}
    +
    static int action_window (Display *disp, Window win, char mode) {/*{{{*/
    p_verbose(“Using window: 0x%.8lx\n”, win);
    switch (mode) {
    @@ -909,7 +988,8 @@
    case ‘N’: case ‘I’: case ‘T’:
    window_set_title(disp, win, options.param, mode);
    return EXIT_SUCCESS;
    -
    + case ‘B’:
    + return switch_decoration(disp, win);
    default:
    fprintf(stderr, “Unknown action: ‘%c’\n”, mode);
    return EXIT_FAILURE;

  7. Ole Brustad
    January 13, 2010 at 8:51 pm | #7

    Tanks for a super tip!
    I just cut-n-pasted the script, and it worked perfectly in
    Gnome, Metacity, Ubuntu Karmic on a Acer Aspire One.
    (to increase performance I have killed the launcher and maximus…)

  8. February 18, 2010 at 12:55 am | #8

    Interesting. Have you discussed getting your patch integrated with the wmctl author?

  9. tdignan1
    April 17, 2012 at 11:24 pm | #10

    Thank you for the xprop script! Exactly what I was looking for.

  1. February 3, 2010 at 11:41 pm | #1
  2. February 4, 2010 at 4:41 am | #2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.