DeDoimAU
Anmeldungsdatum: 13. Mai 2007
Beiträge: 74
|
Hallo, seit Jahren benutze ich ein Python-Script zum An- und Abschalten der Festerdekoration einzelner Fenster.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #! /usr/bin/python
from gtk.gdk import *
w=window_foreign_new((get_default_root_window().property_get("_NET_ACTIVE_WINDOW")[2][0]))
state = w.property_get("_NET_WM_STATE")[2]
maximized='_NET_WM_STATE_MAXIMIZED_HORZ' in state and '_NET_WM_STATE_MAXIMIZED_VERT' in state
if maximized: w.unmaximize()
if w.get_decorations() == 0 :
w.set_decorations(DECOR_ALL)
else:
w.set_decorations(0)
if maximized: w.maximize()
window_process_all_updates()
|
Doch plötzlich funktioniert es nicht mehr. Ich habe heute Xubuntu 20.04.1 neu installiert, allerdings das zweite Mal und ich könnte schwören, dass es davor noch funktioniert hat. Wenn ich die Datei im Terminal ausführe bekomme ich folgende Rückmeldung | bash: /usr/bin/decoration.py: /usr/bin/python: Defekter Interpreter: Datei oder Verzeichnis nicht gefunden
|
Ich habe python-is-python2 installiert. Daraufhin gibt das Terminal Traceback (most recent call last):
File "/usr/bin/decoration.py", line 2, in <module>
from gtk.gdk import *
ImportError: No module named gtk.gdk
Traceback (most recent call last):
File "/usr/bin/decoration.py", line 2, in <module>
from gtk.gdk import *
ImportError: No module named gtk.gdk zur Antwort. Ich habe das gegoogelt, aber die Ergebnisse übersteigen mein Verständnis bei Weitem. Moderiert von Taomon: Dieses Thema ist verschoben worden. Bitte beachte die als wichtig markierten Themen („Welche Themen gehören hier her und welche nicht?“)!
|
Vain
Anmeldungsdatum: 12. April 2008
Beiträge: 2503
|
Sieht nach Python2 und GTK2 aus. Beide tot. GTK3 als Nachfolger hat ein Problem: Die Entwickler konzentrieren sich auf zusehends auf Wayland statt X11 und deswegen sind da schon viele X11-Sachen aus GTK3 rausgeflogen oder als deprecated markiert. Ich habe mir gar nicht die Mühe gemacht, zu schauen, ob dein Skript vielleicht doch auf Python3 / GTK3 portierbar ist – vielleicht hat da jemand anderes Lust drauf. ☺ Du könntest jetzt probieren: Python2 und GTK2 auf deinem System nachinstallieren, dann kannst du dein Skript vorerst weiterverwenden. Wie genau, kann ich dir nicht sagen, weil ich selbst gerade kein Ubuntu hier habe. Die ideale Lösung wäre, einen Window-Manager zu suchen, der die Funktion gleich eingebaut hat. ☺
Aus Spaß an der Freude habe ich ein ähnliches Programm in C geschrieben, siehe unten. Speichern als xtoggledeco.c , Befehl zum Kompilieren steht oben im Kommentar. Es macht den Tanz mit „entmaximieren und dann wieder maximieren“ nicht, weil ich das bei meinem Test mit Openbox nicht brauchte. Vielleicht hilft dir das Teil trotzdem. Insgesamt steht wegen der vielen Bestrebungen, alles auf Wayland zu hieven, ohnehin in den Sternen, ob du das so in ein paar Jahren noch benutzen kannst. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 | /*
* Compile: cc -Wall -Wextra -lX11 xtoggledeco.c -o xtoggledeco
*/
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
int
main()
{
int di, screen;
Display *dpy;
Window root, win = 0;
Atom da, atom_active, atom_motif;
unsigned long *value, nitems, dl;
unsigned long mwm_decorated[5] = { 2, 0, 1, 0, 0 }, *mwm_hints;
dpy = XOpenDisplay(NULL);
if (!dpy)
{
fprintf(stderr, "xtoggledeco: Cannot open display\n");
exit(EXIT_FAILURE);
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
atom_active = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
atom_motif = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
if (XGetWindowProperty(dpy, root, atom_active, 0, 1, False, XA_WINDOW,
&da, &di, &nitems, &dl,
(unsigned char **)&value) != Success || nitems != 1)
{
fprintf(stderr, "xtoggledeco: Cannot get current window\n");
exit(EXIT_FAILURE);
}
win = value[0];
if (XGetWindowProperty(dpy, win, atom_motif, 0, 5, False, atom_motif,
&da, &di, &nitems, &dl,
(unsigned char **)&mwm_hints) != Success || nitems != 5)
{
mwm_hints = mwm_decorated;
}
if (mwm_hints[2] == 1)
mwm_hints[2] = 0;
else
mwm_hints[2] = 1;
XChangeProperty(dpy, win, atom_motif, atom_motif, 32, PropModeReplace,
(unsigned char *)mwm_hints, 5);
XFlush(dpy);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
}
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
Mit GTK3 wurde die Möglichkeit gestrichen die Fensterdekoration zu manipulieren - da es damit auch die Möglichkeit für Bedienelemente in der Titelleiste gibt, macht es in dem Fall auch keinen großen Sinn mehr die komplette Dekoration zu entfernen (gibt interessante Effekte mit doppelt gezeichneten Dekorationen, wenn man es versucht). Wenn man nicht direkt über C-Code gehen will, könnte man das z.B. mit dem Paket python3-ewmh so machen, dann hat man eine kleine Abstraktionsschicht über dem Xlib-Wrapper für Python, was einem ein kleines bisschen Code einspart: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | #!/usr/bin/env python3
import sys
from collections import namedtuple
import ewmh
mwm_hints = namedtuple("mwn_hints", "flags, functions, decorations, inputMode, status")
def set_maximize(e, window, maximized):
for state in ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"):
e.setWmState(window, maximized, state)
if __name__ == '__main__':
e = ewmh.EWMH()
if not (window := e.getActiveWindow()):
sys.exit("could not determine the active window")
wm_states = e.getWmState(window, str=True)
if (was_maximized := "_NET_WM_STATE_MAXIMIZED_VERT" in wm_states and
"_NET_WM_STATE_MAXIMIZED_HORZ" in wm_states
):
set_maximize(e, window, 0)
_MOTIF_WM_HINTS = e.display.intern_atom("_MOTIF_WM_HINTS")
if (result := window.get_property(_MOTIF_WM_HINTS, ewmh.ewmh.X.AnyPropertyType, 0, 32)):
hints = mwm_hints(*result.value)
if hints.decorations == 1:
hints = hints._replace(decorations=0)
else:
hints = hints._replace(decorations=1)
window.change_property(_MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, hints)
else:
print("failed to read _MOTIF_WM_HINTS")
e.display.flush()
if was_maximized:
set_maximize(e, window, 1)
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
Noch eine kleine Anmerkung zum C-Programm: der Gold Linker, der unter Ubuntu zum Einsatz kommt, will da eine andere Reihenfolge der Argumente - das -lX11 muss hinter dem Pfad für die Quelldatei stehen, damit er die Symbole für X11 auflösen kann:
cc -Wall -Wextra xtoggledeco.c -l X11 -o xtoggledeco
|
DeDoimAU
(Themenstarter)
Anmeldungsdatum: 13. Mai 2007
Beiträge: 74
|
Ich muss gestehen, dass ich praktisch nichts in den Antworten verstanden habe, außer dass GTK3 anders funktioniert als GTK2 und es noch Wayland gibt, wo's auch wieder anders ist. Ich kenne ehrlich gesagt den Unterschied nicht. Ich benutze seit 2009 Xubuntu und seit damals hat sich praktisch nichts verändert - nichts, was ich sehen kann. Ich habe aber auch keine Ahnung was unter der Haube passiert. Motoren haben sich ja auch verändert, obwohl es schon immer Kupplungen gab. Ich habe hier (https://gist.github.com/avallete/e84dc3543ff58e29beace47b29fcf75a) ein Script gefunden, dass alle Dekorationen von allen Fenstern offenen verschwinden lässt. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | #!/usr/bin/python
import argparse
from gi import require_version
require_version('Gdk', '3.0')
from gi.repository import Gdk
def check_args():
parser = argparse.ArgumentParser(description="Script to toggle the titlebar into Unity windows.")
parser.add_argument('-D', '--decorate', help='Decorate window.',
action='store_true', dest='decorate')
parser.add_argument('-F', '--focus', help='apply the decoration modification only on focused window.', action='store_true')
return parser.parse_args()
if __name__ == "__main__":
screen = Gdk.Screen.get_default()
args = check_args()
decorator = False
if args.decorate:
decorator = Gdk.WMDecoration.ALL
if args.focus:
windows = [screen.get_active_window()]
|
Ich wollte es nur für einzelne Fenster und wenn die Dekorationen einmal weg sind, kriege ich sie auch nicht zurück. Ich vermute ich werde mich daran gewöhnen müssen, dass das nicht mehr geht. Schade. Trotzdem vielen Dank für die Klärungsversuche! Was machen wir jetzt mit dem Thread? Gelöst ist er ja nicht wirklich. Aber voran geht es vermutlich auch nicht mehr.
|
Vain
Anmeldungsdatum: 12. April 2008
Beiträge: 2503
|
DeDoimAU schrieb: Was machen wir jetzt mit dem Thread? Gelöst ist er ja nicht wirklich. Aber voran geht es vermutlich auch nicht mehr.
Das Python-Skript vom seahawk müsste doch funktionieren, oder? Hast du das mal probiert? Du müsstest da nur über die Paketverwaltung vorher das Paket „python3-ewmh “ installieren, denn ohne das geht’s nicht.
|
DeDoimAU
(Themenstarter)
Anmeldungsdatum: 13. Mai 2007
Beiträge: 74
|
Nein, leider nicht. Wenn ich versuche den Befehl zum kompilieren für das C-Script auszuführen, bekomme ich folgendes angezeigt: xtoggledeco.c:7:10: fatal error: X11/Xatom.h: Datei oder Verzeichnis nicht gefunden
7 | #include <X11/Xatom.h>
| ^~~~~~~~~~~~~
Und bei dem Python-Script bekomme ich: failed to read _MOTIF_WM_HINTS
|
Vain
Anmeldungsdatum: 12. April 2008
Beiträge: 2503
|
Ignorier’ mal die Version in C. Mit Python kommen wir hier bestimmt schneller ans Ziel. ☺ Probier’ mal das:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | #!/usr/bin/env python3
import sys
from collections import namedtuple
import ewmh
mwm_hints = namedtuple("mwn_hints", "flags, functions, decorations, inputMode, status")
def set_maximize(e, window, maximized):
for state in ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"):
e.setWmState(window, maximized, state)
if __name__ == '__main__':
e = ewmh.EWMH()
if not (window := e.getActiveWindow()):
sys.exit("could not determine the active window")
wm_states = e.getWmState(window, str=True)
if (was_maximized := "_NET_WM_STATE_MAXIMIZED_VERT" in wm_states and
"_NET_WM_STATE_MAXIMIZED_HORZ" in wm_states
):
set_maximize(e, window, 0)
_MOTIF_WM_HINTS = e.display.intern_atom("_MOTIF_WM_HINTS")
if (result := window.get_property(_MOTIF_WM_HINTS, ewmh.ewmh.X.AnyPropertyType, 0, 32)):
hints = mwm_hints(*result.value)
if hints.decorations == 1:
hints = hints._replace(decorations=0)
else:
hints = hints._replace(decorations=1)
else:
hints = (2, 0, 0, 0, 0)
window.change_property(_MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, hints)
e.display.flush()
if was_maximized:
set_maximize(e, window, 1)
|
Das Skript von oben brach ab, wenn noch gar keine Hints gesetzt waren, was aber bei vielen Fenstern der Fall ist.
|
DeDoimAU
(Themenstarter)
Anmeldungsdatum: 13. Mai 2007
Beiträge: 74
|
Tasächlich, das klappt! Vielen Dank!!! 😀
|