terça-feira, 23 de junho de 2009

Removing decorations in Metacity « XRunHProf

Removing decorations in Metacity « XRunHProf

April 13, 2009

Removing decorations in Metacity

Filed under: Uncategorized — Tags: , , — xrunhprof @ 8:12 am

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 = 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 <<>
+ 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 <>
+ {
+ 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;

5 Comments »

  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’.
    *

    Comment by Chris — May 21, 2009 @ 3:08 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.

    Comment by xrunhprof — May 21, 2009 @ 6:20 pm

  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.

    Comment by Chris — May 22, 2009 @ 6:34 am

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

    Comment by xrunhprof — May 22, 2009 @ 6:14 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.

    Comment by Chris — May 24, 2009 @ 1:38 pm

Nenhum comentário: