staging.inyokaproject.org

window-fu - Erweiterte Fenstersteuerung

Status: Gelöst | Ubuntu-Version: Ubuntu 10.04 (Lucid Lynx)
Antworten |

Yggdrasil

Anmeldungsdatum:
1. Februar 2011

Beiträge: Zähle...

Hallo,

ich habe dein Skript zufällig entdeckt und da es meine eigenes Skript für die Fensterverwaltung abdeckt, übernommen. 😉 Gefällt mir gut, da die wichtigsten Funktionen der „Tiling window manager“ bereitstellt, ohne auf Awesome, etc wechseln zu müssen. Damit die Auflösung beim Erstellen der Config-Datei automatisch erkannt wird, habe ich das Skript an der Stelle angepasst.

Gruß Yggdrasil

# Create a default config file
function config () {

res=`xdpyinfo | grep dim`
width=`echo $res | sed -n -r 's/^.* ([0-9]+)x([0-9]+) .*/\1/ip'`
height=`echo $res | sed -n -r 's/^.* ([0-9]+)x([0-9]+) .*/\2/ip'`

    cat << CONFIG
##WIN-FU CONFIGURATION FILE#################################################
# To ensure the script working properly with your screen resolution and window
# manager theme you have to change the values of the following variables 
# accordingly. Unit is pixels.
# To get the border sizes for your window manager theme have a look in the theme
# folder in /usr/share/themes/.
# The default values currently feature a 1440x900 wide screen resolution with 
# window manager theme Shiki-Colors-Easy and one 32px panel at the bottom.
################################################################################ 
# Screen resolution
screen_width="${width}"
screen_height="${height}"

mrkramps Team-Icon

(Themenstarter)
Avatar von mrkramps

Anmeldungsdatum:
10. Oktober 2006

Beiträge: 5523

Diese Anpassung hatte ich in einer vorherigen Version des Scripts auch verwendet. Allerdings erschien mir das überflüssig, weil die Konfigurationsdatei zum größten Teil von Hand gefüllt werden muss. Aber ausgehend von deinem Beitrag habe ich mir nochmal Gedanken gemacht, wie man die Konfiguration automatisieren könnte. Dabei bin ich auf einige mögliche Lösungsansätze gestoßen und auf diverse Probleme...

LÖSUNGSANSÄTZE: (ich halte mich beim Beispielcode vorwiegen an Xfce, weil meine Desktopumgebung)

"Fenstermanager für Setup festlegen"

Option A: Man übergibt den Fenstermanager beim Aufruf des Setups an $2.

1
2
3
4
5
6
7
8
win-fu -s xfwm4
--
if [ "$2" = "xfwm4"]; then
# do things according to this WM
else
echo "Option unknown or no window manager specified."
echo "Please setup configuration file manually."
fi

Option B: Man lässt diese Information mit wmctrl ausgeben (ist noch unklar wie verlässich das für die verschiedenen WMs funktioniert).

1
2
3
4
5
6
7
wm_active=$(wmctrl -m | awk '/Class:/ {print $2}')

if [ "$wm_active" = "xfwm4" ]; then
# do things according to this WM
else
# see above
fi


"Verwendetes Theme für Setup festlegen"

Das sollte mit Metacity unter Gnome kein Problem mit gconftool sein, für Xfwm4 unter Xfce gibt es dafür xfconf-query. Letzten Endes dienen beide Tools für das Auslesen/Ändern von XML-Dateien. Voraussichtlich werden auch alle anderen WMs diese Information in irgendeiner Konfigurationsdatei ablegen, die man auslesen kann. Anschließend muss man nur noch klären, ob es sich um ein lokal im Homeverzeichnis oder systemweit installiertes Theme handelt, damit das Script weiß in welchem Pfad nach den entsprechenden Dateien zu suchen ist.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
wm_active=$(wmctrl -m | awk '/Class:/ {print $2}')
theme_active=$(xfconf-query -c xfwm4 -p /general/theme)

if [ "$wm_active" = "xfwm4" ]; then
    if [ -d $HOME/.themes/$theme_active/$wm_active ]; then
    # query file(s) in local path
    else
    # query file(s) in global path
    fi
else
# see above
fi


"Größe der Fensterrahmen für Setup festlegen"

Metacity Themes werden alle in einer XML-Datei definiert. Dürften sich also recht einfach auslesen lassen. Xfwm4, OpenBox usw. verwenden allerdings keine Konfigurationsdatei für die Definition der Fensterrahmen, sondern XPM-Bilddateien. Um die Bildgröße solcher Dateien zu ermitteln, fallen mir spontan drei Werkzeuge ein - 1. identify (ImageMagick, wäre aber eine weitere Abhängigkeit), 2. file (leider keine Größenangaben für XPMs), 3. head (Bildgröße in Zeile 3 - Bingo!).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
wm_active=$(wmctrl -m | awk '/Class:/ {print $2}')
theme_active=$(xfconf-query -c xfwm4 -p /general/theme)
local_path="$HOME/.themes/$theme_active/$wm_active"
global_path="/usr/share/themes/$theme_active/$wm_active"

if [ "$wm_active" = "xfwm4" ]; then
    if [ -d $local_path ]; then
    title_bar=$(head -3 $local_path/title-1-active.xpm | awk '/\"/ {print $2}') # title bar height
    else
    title_bar=$(head -3 $global_path/title-1-active.xpm | awk '/\"/ {print $2}') # title bar height
    fi
else
# see above
fi


"Panels oben, unten, links, rechts ?!"

Wie Linux Und Ich in seinem Beitrag schon festgestellt hat, sollte das mit gconftool unter Gnome recht einfach zu machen sein die Größe der jeweiligen Panels für jede Position auf dem Bildschirm auszulesen.

LXDEs Lxpanel speichert die Informationen in jeweils einer einfachen Textdatei pro Panel ohne Große Syntax. Allerdings stellt sich das Panel noch nicht besonders clever an, was die Bezeichnung seiner Konfigurationsdateien betrifft. So wird für das erste Panel als "panel" gespeichert, aber beim zweiten wird als Dateiname dann das genommen, was im Einstellungsdialog unter "Position: Edge" steht - unabhängig davon wo das Panel sich letzen Endes auf dem Bildschirm befinden wird. Müssen also alle Dateien im Verzeichnis nach dem Suchmuster durchforstet werden. Und beim Xfce-Panel wird es dann richtig unterhaltsam. Die Konfiguration aller Panels wird in einer einzelnen XML-Datei abgelegt und die Position des Panels dort lediglich durch einen Zahlenwert für screen-position bezeichnet - untere Bildschirmkante mitte wäre demnach dann <property name="screen-position" value="11"/>. Sortiert sind diese Werte nach Bildschirmkante oben, links, rechts, unten und Ausrichtung link, mitte, rechts bzw. oben, mitte, unten - also oben 1-3, links 4-6, rechts 7-9 und unten 10-12. Bei mir ist das noch ein hässliches Entlein.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# Get all sticky windows, non-panel windows will be ignored later
panels_active=( $(wmctrl -l | awk '/-1/ {print $4}') )

# Paths of panel configurations
lxpanel_path="$HOME/.config/lxpanel/default/panels/"
xfce4-panel_path="$HOME/.config/xfce4/panel/"

for panel in ${panels_active[@]}; do
    if [ "$panel" == "lxpanel" ], then
        bottom_panel=$(awk -F \= '/edge=bottom/,/height/ {print $2}' $(find $lxpanel_path -type f -iname '*') | tail -1)
        top_panel=$(awk -F \= '/edge=top/,/height/ {print $2}' $(find $lxpanel_path -type f -iname '*') | tail -1)
        left_panel=$(awk -F \= '/edge=left/,/height/ {print $2}' $(find $lxpanel_path -type f -iname '*') | tail -1)
        right_panel=$(awk -F \= '/edge=right/,/height/ {print $2}' $(find $lxpanel_path -type f -iname '*') | tail -1)
    elif [ "$panel" == "xfce4-panel" ]; then
        # tail -1 is used here because it's possible to have up to three panels on one screen edge and only one value is required
        bottom_panel=$(grep -B 2 -e '<property name="screen-position" value="10"/>' -e '<property name="screen-position" value="11"/>' -e '<property name="screen-position" value="12"/>' $xfce4-panel_path/panels.xml | awk -F \" '/size/,/value/ {print $4}') | tail -1
        top_panel=$(grep -B 2 -e '<property name="screen-position" value="1"/>' -e '<property name="screen-position" value="2"/>' -e '<property name="screen-position" value="3"/>' $xfce4-panel_path/panels.xml | awk -F \" '/size/,/value/ {print $4}') | tail -1
        left_panel=$(grep -B 2 -e '<property name="screen-position" value="4"/>' -e '<property name="screen-position" value="5"/>' -e '<property name="screen-position" value="6"/>' $xfce4-panel_path/panels.xml | awk -F \" '/size/,/value/ {print $4}') | tail -1
        right_panel=$(grep -B 2 -e '<property name="screen-position" value="7"/>' -e '<property name="screen-position" value="8"/>' -e '<property name="screen-position" value="9"/>' $xfce4-panel_path/panels.xml | awk -F \" '/size/,/value/ {print $4}') | tail -1
    fi
done

Update: Die Ausrichtung von Lxpanel funktioniert genauso wie für das Xfce-Panel. Also müsste man auch dafür sichergehen, dass man für die jeweilige Bildschirmkante jeweils das höchste bzw. breiteste der drei möglichen Panels in die Konfiguration schreiben lässt. Außerdem basiert das Lxpanel von LXDE auf dem fbpanel und verwendet das gleiche System für die Konfiguration. Die Variante ist also auch gültig für das fbpanel.


"Seitenränder der Fenster"

Da der Wert für die Variable $window_margin im Script nicht automatisch generiert werden kann, endet es dafür wahrscheinlich in einem weiteren Parameter.


"Nicht unterstütze/erkannte Fenstermanager und Panels"

Dabei kann man wieder auf die manuelle Konfiguration zurückgreifen.


"Fazit"

Nachdem ich jetzt Stunden, die ich besser hätte schlafen sollen, damit verbracht habe die tatsächlichen Möglichkeiten auszuloten, komme ich zu dem Schluss, dass eine nahezu vollkommen automatisierte Erstellung der Konfigurationsdatei im Bereich des Möglichen liegt. Ich muss dann jetzt "nur noch" jede Menge Grundlagenforschung zum Thema "Konfigurationsdateien von Window Managern und Panels, Bars und Docks" betreiben. 👍

Yggdrasil

Anmeldungsdatum:
1. Februar 2011

Beiträge: 34

Hallo Dauerflucher,

stimmt, dann müssen noch weitere Variablen ermittelt werden. Ich habe mal geprüft, wie die Werte für Gnome/Metacity ermittelt werden könnten.

1. bei Gnome liefert „wmctrl -m“ Name: Metacity Class: N/A PID: N/A

D.h. man müsste „wm_active=$(wmctrl -m | awk '/Name:/ {print $2}')“ verwenden, um den Manager zu erkennen.

2. Panelgrößen. Die können mit dem folgendem Code berechnet werden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash
top_panel=0
bottom_panel=0
right_panel=0
left_panel=0

for panelname in `gconftool --all-dirs /apps/panel/toplevels`
do
    panelSize=$(gconftool --get ${panelname}/size)
    panelOrientation=$(gconftool --get ${panelname}/orientation)
    eval ${panelOrientation}_panel=$(( ${panelOrientation}_panel + ${panelSize} ))
done

echo "Detected panel dimensions:
 Top: ${top_panel}
 Bottom: ${bottom_panel}
 Left: ${left_panel}
 Right: ${right_panel}"

3. Fensterrahmen.

Da habe ich keine andere Möglichkeit gefunden, als die Werte aus dem aktuellen Thema zu ermitteln. Kenne mich allerdings nicht gut aus, was die verschiedenen Konfigurationsmöglichkeiten bei Themes angeht. Dementsprechend sind meine reg. Ausdrücke nicht sehr robust. Bei mir würde das folgende laufen. Allerdings fehlt da noch ein Wert, um die Höhe der Titelzeile zu berechnen. Die hängt von der gewählten Schriftart/Größe (/apps/metacity/general/titlebar_font) ab.

 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
##Detect border width of metacity theme
theme_active=$(gconftool --get /apps/metacity/general/theme)

#Find config file path
if [ -f $HOME/.themes/${theme_active}/metacity-1/metacity-theme-1.xml ]; then
    # query file(s) in local path
		theme_file=`cat $HOME/.themes/${theme_active}/metacity-1/metacity-theme-1.xml`
    else
    # query file(s) in global path
		theme_file=`cat /usr/share/themes/${theme_active}/metacity-1/metacity-theme-1.xml`
	fi

theme_file=$(echo $theme_file | sed -n -r 's!.*<frame_geometry[^>]*>(.*)</frame_geometry>.*!\1!ip')

windowBorderLeft=$(echo $theme_file | sed -n -r 's!.*name="left_width"[^"]+"([0-9]+)".*!\1!ip')
windowBorderRight=$(echo $theme_file | sed -n -r 's!.*name="right_width"[^"]+"([0-9]+)".*!\1!ip')
windowBorderBottom=$(echo $theme_file | sed -n -r 's!.*name="bottom_height"[^"]+"([0-9]+)".*!\1!ip')

titlePad=$(echo $theme_file | sed -n -r 's!.*name="title_vertical_pad"[^"]+"([0-9]+)".*!\1!ip')
titleHeight=$(echo $theme_file | sed -n -r 's!.*name="title_border".*top="([0-9]+).*bottom="([0-9]+)"[^>]*>.*!\1 + \2!ip')

titleHeight=$(($titleHeight + 2 * $titlePad))

echo "Window geometry:
 Left: ${windowBorderLeft}
 Right: ${windowBorderRight}
 Bottom: ${windowBorderBottom}
 TitleHeight: ${titleHeight}"

echo "Achtung, bei Titelheight fehlt noch der durch die Schriftart/-größe definierte Wert."

Gruß Yggdrasil

Yggdrasil

Anmeldungsdatum:
1. Februar 2011

Beiträge: 34

-

mrkramps Team-Icon

(Themenstarter)
Avatar von mrkramps

Anmeldungsdatum:
10. Oktober 2006

Beiträge: 5523

Außer einigen kleinen Tippfehlern wurde eine neue Funktion für die Option -d implementiert, mit der die Konfigurationsdatei als Backup gesichert wird und eine neue Standardkonfiguration geschrieben wird. Diese Funktion sollte jedesmal aufgerufen werden, wenn eine neue Version von WIN-FU verwendet wird um neue Variabeln in der Konfiguration nicht zu übergehen.

Ferner wurde eine weitere Funktion für die Option -e implementiert, die ein Fenster auf die Größe eines geklonten, externen Displays setzt, um z.B. ein Fenster auf einem Beamer zu maximieren. Die Auflösung des externen Displays wird über zwei neue Variabeln in der Konfigurationsdatei gesetzt. Nicht vergessen: win-fu -d

  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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
#!/bin/bash
##WIN-FU########################################################################
# By Andreas Lis <mrkramps@googlemail.com>
# Released under GNU General Public License 3.0
# Copyright (c) 2011
#
# Last updated on Mar /18/2011
#
##GNU GENERAL PUBLIC LICENSE 3.0################################################
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/> or write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
##GENERAL INFORMATION###########################################################
# This script provides additional functionality for window operations with
# EWMH/NetWM compatible X Window Managers such as metacity, xfwm4, kwin, icewm,
# window maker or openbox. Possibly newer versions of some of those window
# managers might already support all or some of the features innately.
#
# Dependencies:
# wmctrl, xdotool, xwit, EWMH/NetWM compatible X Window Manager
#
##END OF HEAD###################################################################
# Uncomment for debugging
#set -x

# Define global variables
# Remaining global variables are defined in configuration file - see line 339
if [ "$1" != "-h" ] && [ "$1" != "-?" ] && [ "$1" != "-s" ] && [ "$1" != "-V" ]
then
# Get active desktop
#desk_active=$(xdotool get_desktop)
#desk_active=$(wmctrl -d | grep "*" | cut -d " " -f1)
desk_active=$(wmctrl -d | awk '/\*/{print $1}')

# Get all window IDs from windows on active desktop
#win_id_all=$(wmctrl -l | grep "  $desk_active" | cut -d " " -f1)
win_id_all=$(wmctrl -l | awk '/  '$desk_active'/{print $1}')

# Store in array for further processing
win_array=( $win_id_all )

# Get total of all windows on active dekstop
win_count=${#win_array[@]}

	if [ "$1" = "-lrr" ] || [ "$1" = "-rll" ] || [ "$1" = "-tbb" ] || [ "$1" = "-btt" ] || [ "$1" = "-m" ] || [ "$1" = "-u" ]
	then
# Get window ID of currently active window
		win_active=$(xdotool getactivewindow)
	fi
fi

# Path of configuration file
config_path="$HOME/.config/win-fu"
config_file="win-fu.cfg"

# Display usage information
function usage () {
	cat <<USAGE
WIN-FU - Based on several command line utilities this script provides
additional functionality for window operations with EWMH/NetWM compatible X
Window Managers. Mainly meant to be controlled via keyboard shortcuts, please
apply those in your keyboard settings manually.
To ensure the script is working properly with your screen resolution and window
manager theme also manually edit the configuration file accordingly.

Dependencies:
	wmctrl, xdotool, xwit, EWMH/NetWM compatible X Window Manager

Usage:
	win-fu [PARAMETER] (best applied to keyboard shortcut)

Example:
	win-fu -l (applied to SHIFT+ALT+KP_LEFT)

Parameters:

	General:
	-h -?	Displays usage information

	-s		Opens win-fu configuration file with the default editor set in
			the $EDITOR environment variable or creates configuration file if
			non-existent in $HOME/.config/win-fu/win-fu.cfg.
			This function is automatically invoked if no configuration file is
			found
			
	-d		Reset configuration to default. Move old file to backup file and 
			open new file with default editor set in the $EDITOR variable. This
			option must be invoked for a new version with additional config 
			variables. 

	-V		Displays version and license information

	Active window only:

	-l		Snap active window to left screen edge maximized vertically

			-------------
			|     |
			|  a  |
			|     |
			-------------

	-r		Snap active window to right screen edge maximized vertically

			-------------
			      |     |
			      |  a  |
			      |     |
			-------------

	-t		Snap active window to top screen edge maximized horizontally

			-------------
			|     a     |
			-------------

			-------------

	-b		Snap active window to bottom screen edge maximized horizontally

			-------------

			-------------
			|     a     |
			-------------

	-f		Toggle active window maximized

			-------------
			|           |
			|     a     |
			|           |
			-------------

	-pt		Set active window height to screen height half and snap to top edge

			-------------
			  |   a   |
			  ---------

			-------------

	-pb		Set active window height to screen height half and snap to bottom 
			edge

			-------------
			  |   a   |
			  ---------

			-------------

	-tl		Set active window height to screen height half and snap to top left
			screen corner

			-------------
			|  a  |
			-------

			-------------

	-bl		Set active window height to screen height half and snap to bottom
			left screen corner

			-------------

			-------
			|  a  |
			-------------

	-tr		Set active window height to screen height half and snap to top right
			screen corner

			-------------
			      |  a  |
			      -------

			-------------

	-br		Set active window height to screen height half and snap to bottom
			right screen corner

			-------------

			      -------
			      |  a  |
			-------------

	-e		Set window size according to screen resolution of a cloned external
			display device and set window position to top left border, useful
			when e.g. a beamer device is connected
			
			-------------
			|       |    
			|   a   |    
			---------    
			-------------

	All windows on active desktop:

	-lr		Snap all windows alternating to left and right screen edges with
			screen width half and maximized vertically

			-------------
			|     |     |
			|     |     |
			|     |     |
			-------------

	-tb		Snap all windows alternating to top and bottom screen edges with
			screen height half and maximized horizontally

			-------------
			|           |
			-------------
			|           |
			-------------

	-lrr	Snap active window to left screen edge maximized vertically, stack
			inactive windows alternating to top and bottom right screen corners

			-------------
			|     |     |
			|  a  -------
			|     |     |
			-------------

	-rll	Snap active window to right screen edge maximized vertically, stack
			inactive windows alternating to top and bottom left screen corners

			-------------
			|     |     |
			-------  a  |
			|     |     |
			-------------

	-tbb	Snap active window to top screen edge maximized horizontally, stack
			inactive windows alternating to bottom left and right screen corners

			-------------
			|     a     |
			-------------
			|     |     |
			-------------

	-btt	Snap active window to bottom screen edge maximized horizontally,
			stack inactive windows alternating to top left and right screen
			corners

			-------------
			|     |     |
			-------------
			|     a     |
			-------------

	-tblr	Snap all windows alternating to top and bottom left and right screen
			corners.

			-------------
			|     |     |
			-------------
			|     |     |
			-------------

	-m		Minimize resp. iconify all windows expect active one on current.
			desktop

	-u		Unminimize resp. popup all windows on current desktop
USAGE
}

# Create a default config file
function config () {
	cat << CONFIG
##WIN-FU CONFIGURATION FILE#####################################################
# To ensure the script is working properly with your screen resolution and
# window manager theme you have to change the values of the following variables
# accordingly. Unit is pixels.
# To get the border sizes for your window manager theme have a look in the theme
# folder in /usr/share/themes/.
# The default values currently feature a 1440x900 wide screen resolution with
# window manager theme Shiki-Colors-Easy, one 32px panel at the bottom and a
# 1024x768 screen resolution for an external display device
################################################################################
# Screen resolution
screen_width="1440"
screen_height="900"

# External screen resolution
external_width="1024"
external_height="768"

# Top panel height
top_panel="0"

# Bottom panel height
bottom_panel="32"

# Left panel width
left_panel="0"

# Right panel width
right_panel="0"

# Window title bar height
title_bar="25"

# Window left border width
left_border="3"

# Window right border width
right_border="3"

# Window bottom border width
bottom_border="3"

# Additional window margins (space between window borders)
window_margin="1"
CONFIG
}

function version () {
	cat << VERSION
WIN-FU --
By Andreas Lis <mrkramps@googlemail.com>
Released unter GNU General Public License 3.0
Copyright (c) 2011

Last updated on Mar /18/2011
VERSION
}

# Function to create and edit configuration file
# Configuration file contains remaining global variables
function setup () {
if [ -e $config_path/$config_file ]
then
	editor $config_path/$config_file
else
	mkdir -p $config_path
	config > $config_path/$config_file
	editor $config_path/$config_file
fi
}

function reset () {
	mv $config_path/$config_file $config_path/$config_file.bak
	setup
}

# Check if a configuration file is existent
if [ -e $config_path/$config_file ]
then
# Source configuration file to define remaining global variables
	if [ "$1" != "-h" ] && [ "$1" != "-?" ] && [ "$1" != "-V" ]
	then
		source $config_path/$config_file
	fi
else
# If non-existent invoke setup function except user manually executes setup
	if [ "$1" != "-s" ]
	then
		setup
	fi
fi

# Functions to define variables for window geometry
function left () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height - $title_bar - $bottom_border -$top_panel - $bottom_panel ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel  + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( 0 + $top_panel ))
}

function right () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height - $title_bar - $bottom_border -$top_panel - $bottom_panel ))
	# For use with wmctrl and gravity 10
	x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin + $right_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin ))
	#y=$(( 0 + $top_panel ))
}

function top () {
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	w=$(( $screen_width - $left_border - $right_border - $left_panel - $right_panel ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( 0 + $top_panel ))
}

function bottom () {
	w=$(( $screen_width - $left_border - $right_border - $left_panel - $right_panel ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 ))
}

function top_left () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( 0 + $top_panel ))
}

function bottom_left () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel/2 + $right_panel/2 + $window_margin + $left_border ))
	y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel/2 + $right_panel/2 + $window_margin ))
	#y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 ))
}

function top_right () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin + $right_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin ))
	#y=$(( 0 + $top_panel ))
}

function bottom_right () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin + $right_border ))
	y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin ))
	#y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 ))
}

function pos_top () {
	w="-1"
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	x="-1"
	# For use with wmctrl and gravity 10
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#y=$(( 0 + $top_panel ))
}

function pos_bottom () {
	w="-1"
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	x="-1"
	# For use with wmctrl and gravity 10
	y=$(( $screen_height/2 - $bottom_panel/2 - $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#y=$(( $screen_height/2 - $bottom_panel/2 - $top_panel/2 ))
}

function external () {
	w=$(( $external_width - $left_border - $right_border - $left_panel ))
	h=$(( $external_height - $title_bar - $bottom_border - $top_panel ))
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel + $title_bar ))
}

# wmctrl commands for window placement
# Use gravity 10 to influence window content geometry only and avoid problems
# with window manager theme borders not properly recognized for some programs
function place () {
	wmctrl -i -r $win_id -e 10,$x,$y,$w,$h
}

function place_active () {
	wmctrl -r :ACTIVE: -e 10,$x,$y,$w,$h
}

# Functions for each type of placement grid
function left_right () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		if [ "$(( $n % 2 ))" -eq "0" ]
		then
		left && place
		else
		right && place
		fi
	done
}

function top_bottom () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		if [ "$(( $n % 2 ))" -eq "0" ]
		then
			top && place
		else
			bottom && place
		fi
	done
}

function left_right_right () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				left && place
			else
				top_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then 
			if [ $win_active = $win_current ]
			then
				left && place
			else
				bottom_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				left && place
			else
				top_right && place
			fi
		fi
	done
}

function right_left_left () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				right && place
			else
				top_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then
			if [ $win_active = $win_current ]
			then
				right && place
			else
				bottom_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				right && place
			else
				top_left && place
			fi
		fi
	done
}

function top_bottom_bottom () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				top && place
			else
				bottom_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then
			if [ $win_active = $win_current ]
			then
				top && place
			else
				bottom_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				top && place
			else
				bottom_left && place
			fi
		fi
	done
}

function bottom_top_top () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				bottom && place
			else
				top_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then
			if [ $win_active = $win_current ]
			then
				bottom && place
			else
				top_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				bottom && place
			else
				top_left && place
			fi
		fi
	done
}

function top_bottom_left_right () {
	for (( n=0 ; n <= $(($win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		if [ "$(( $n % 4 ))" -eq "0" ]
		then
		top_left && place
		elif [ "$(( $n % 4 ))" -eq "1" ]
		then
		bottom_left && place
		elif [ "$(( $n % 4 ))" -eq "2" ]
		then
		top_right && place
		elif [ "$(( $n % 4 ))" -eq "3" ]
		then
		bottom_right && place
		fi
	done
}

function minimize () {
	for i in ${win_array[@]}
	do
		# wmctrl outputs hex, xdotool and xwit use decimal values for window IDs
		# let converts those hex to decimal values
		let win_id=$i
		if [ "$win_active" != "$win_id" ]
		then
		xwit -iconify -id $win_id
		fi
	done
}

function unminimize () {
	for i in ${win_array[@]}
	do
		# See function minimize for explaination
		let win_id=$i
		if [ "$win_active" != "$win_id" ]
		then
		# Give focus to each unhidden window to avoid pager blinking
		xwit -pop -focus -id $win_id
		fi
	done
	# Give focus to formerly active window again
	xwit -focus -id $win_active
}

# Bring together parameters and according functions
function win_fu () {
	case $1 in
		-h)
			usage
			echo ""
			version
			;;
		-\?)
			usage
			echo ""
			version
			;;
		-s)
			setup
			;;
		-d)
			reset
			;;
		-V)
			version
			;;
		-l)
			left && place_active
			;;
		-r)
			right && place_active
			;;
		-t)
			top && place_active
			;;
		-b)
			bottom && place_active
			;;
		-f)
			wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
			;;
		-pt)
			pos_top && place_active
			;;
		-pb)
			pos_bottom && place_active
			;;
		-tl)
			top_left && place_active
			;;
		-bl)
			bottom_left && place_active
			;;
		-tr)
			top_right && place_active
			;;
		-br)
			bottom_right && place_active
			;;
		-e)
			external && place_active
			;;
		-lr)
			left_right
			;;
		-tb)
			top_bottom
			;;
		-lrr)
			left_right_right
			;;
		-rll)
			right_left_left
			;;
		-tbb)
			top_bottom_bottom
			;;
		-btt)
			bottom_top_top
			;;
		-tblr)
			top_bottom_left_right
			;;
		-m)
			minimize
			;;
		-u)
			unminimize
			;;
		*)
			exit 1
			;;
	esac
}

# Let it happen
win_fu $1

Ikem

Anmeldungsdatum:
13. Januar 2011

Beiträge: 38

Ich finde "win-fu" einen etwas unglücklich gewählten Namen.

Im englischen steht "fu" nämlich umgangssprachlich für "f-ck you".

mrkramps Team-Icon

(Themenstarter)
Avatar von mrkramps

Anmeldungsdatum:
10. Oktober 2006

Beiträge: 5523

Ikem schrieb:

Ich finde "win-fu" einen etwas unglücklich gewählten Namen.

Im englischen steht "fu" nämlich umgangssprachlich für "f-ck you".

Ich war mehr damit beschäftigt, dass das Script tut, was es tun soll, als dem Kind noch einen kreativen Namen zu geben. Meine Anlehnung war an „Kung Fu“ und den Chinesen will man jetzt nicht auch erzählen, dass sie ihre renommierte Kampfsportart umbenennen müssen, weil im Englischen irgendwas für irgendwas anderes stehen könnte.

Abgesehen davon, wo ist dein Vorschlag? Ich benenne dieses vernachlässigbare Script gerne um, wenn du mir einen Namen vorgibst.

Ikem

Anmeldungsdatum:
13. Januar 2011

Beiträge: 38

Ich wollte dich nicht doof anmachen. Ich wollte nur darauf hinweisen, das es falsch verstanden werden könnte.

Und man weiss ja nie wo ein Skript mal landen wird. 😉

Also mein Vorschlag wäre "wsnap". Das ist schön kurz, und noch nah genug an "window snapping".

mrkramps Team-Icon

(Themenstarter)
Avatar von mrkramps

Anmeldungsdatum:
10. Oktober 2006

Beiträge: 5523

Ikem schrieb:

Ich wollte dich nicht doof anmachen. Ich wollte nur darauf hinweisen, das es falsch verstanden werden könnte.

Und man weiss ja nie wo ein Skript mal landen wird. 😉

Also mein Vorschlag wäre "wsnap". Das ist schön kurz, und noch nah genug an "window snapping".

Jau, passt. Find ich nicht verkehrt. 👍

Gibt zwar schon ein gleichnamiges Windows-Programm für Screencasts, aber da kann man drüber hinweg sehen.

Entsprechende Aktualisierung des Quelltextes:

  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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
#!/bin/bash
##WSNAP########################################################################
# By Andreas Lis <mrkramps@googlemail.com>
# Released under GNU General Public License 3.0
# Copyright (c) 2011-2012
#
# Last updated on 2012-09-05
#
##GNU GENERAL PUBLIC LICENSE 3.0################################################
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/> or write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
##GENERAL INFORMATION###########################################################
# This script provides additional functionality for window operations with
# EWMH/NetWM compatible X Window Managers such as metacity, xfwm4, kwin, icewm,
# window maker or openbox. Possibly newer versions of some of those window
# managers might already support all or some of the features innately.
#
# Dependencies:
# wmctrl, xdotool, xwit, EWMH/NetWM compatible X Window Manager
#
##END OF HEAD###################################################################
# Uncomment for debugging
#set -x

# Define global variables
# Remaining global variables are defined in configuration file - see line 339
if [ "$1" != "-h" ] && [ "$1" != "-?" ] && [ "$1" != "-s" ] && [ "$1" != "-V" ]
then
# Get active desktop
#desk_active=$(xdotool get_desktop)
#desk_active=$(wmctrl -d | grep "*" | cut -d " " -f1)
desk_active=$(wmctrl -d | awk '/\*/{print $1}')

# Get all window IDs from windows on active desktop
#win_id_all=$(wmctrl -l | grep "  $desk_active" | cut -d " " -f1)
win_id_all=$(wmctrl -l | awk '/  '$desk_active'/{print $1}')

# Store in array for further processing
win_array=( $win_id_all )

# Get total of all windows on active dekstop
win_count=${#win_array[@]}

	if [ "$1" = "-lrr" ] || [ "$1" = "-rll" ] || [ "$1" = "-tbb" ] || [ "$1" = "-btt" ] || [ "$1" = "-m" ] || [ "$1" = "-u" ]
	then
# Get window ID of currently active window
		win_active=$(xdotool getactivewindow)
	fi
fi

# Path of configuration file
config_path="$HOME"
config_file=".wsnaprc"

# Display usage information
function usage () {
	cat <<USAGE
WSNAP - Based on several command line utilities this script provides
additional functionality for window operations with EWMH/NetWM compatible X
Window Managers. Mainly meant to be controlled via keyboard shortcuts, please
apply those in your keyboard settings manually.
To ensure the script is working properly with your screen resolution and window
manager theme also manually edit the configuration file accordingly.

Dependencies:
	wmctrl, xdotool, xwit, EWMH/NetWM compatible X Window Manager

Usage:
	wsnap [PARAMETER] (best applied to keyboard shortcut)

Example:
	wsnap -l (applied to SHIFT+ALT+KP_LEFT)

Parameters:

	General:
	-h -?	Displays usage information

	-s		Opens wsnap configuration file with the default editor set in
			the $EDITOR environment variable or creates configuration file if
			non-existent at $HOME/.wsnaprc.
			This function is automatically invoked if no configuration file is
			found.
			
	-d		Reset configuration to default. Move old file to backup file and 
			open new file with default editor set in the $EDITOR variable. This
			option must be invoked for a new version with additional config 
			variables. 

	-V		Display version and license information

	Active window only:

	-l		Snap active window to left screen edge maximized vertically

			-------------
			|     |
			|  a  |
			|     |
			-------------

	-r		Snap active window to right screen edge maximized vertically

			-------------
			      |     |
			      |  a  |
			      |     |
			-------------

	-t		Snap active window to top screen edge maximized horizontally

			-------------
			|     a     |
			-------------

			-------------

	-b		Snap active window to bottom screen edge maximized horizontally

			-------------

			-------------
			|     a     |
			-------------

	-f		Toggle active window maximized

			-------------
			|           |
			|     a     |
			|           |
			-------------

	-pt		Set active window height to screen height half and snap to top edge

			-------------
			  |   a   |
			  ---------

			-------------

	-pb		Set active window height to screen height half and snap to bottom 
			edge

			-------------
			  |   a   |
			  ---------

			-------------

	-tl		Set active window height to screen height half and snap to top left
			screen corner

			-------------
			|  a  |
			-------

			-------------

	-bl		Set active window height to screen height half and snap to bottom
			left screen corner

			-------------

			-------
			|  a  |
			-------------

	-tr		Set active window height to screen height half and snap to top right
			screen corner

			-------------
			      |  a  |
			      -------

			-------------

	-br		Set active window height to screen height half and snap to bottom
			right screen corner

			-------------

			      -------
			      |  a  |
			-------------

	-e		Set window size according to screen resolution of a cloned external
			display device and set window position to top left border, useful
			when e.g. a beamer device is connected
			
			-------------
			|       |    
			|   a   |    
			---------    
			-------------

	All windows on active desktop:

	-lr		Snap all windows alternating to left and right screen edges with
			screen width half and maximized vertically

			-------------
			|     |     |
			|     |     |
			|     |     |
			-------------

	-tb		Snap all windows alternating to top and bottom screen edges with
			screen height half and maximized horizontally

			-------------
			|           |
			-------------
			|           |
			-------------

	-lrr	Snap active window to left screen edge maximized vertically, stack
			inactive windows alternating to top and bottom right screen corners

			-------------
			|     |     |
			|  a  -------
			|     |     |
			-------------

	-rll	Snap active window to right screen edge maximized vertically, stack
			inactive windows alternating to top and bottom left screen corners

			-------------
			|     |     |
			-------  a  |
			|     |     |
			-------------

	-tbb	Snap active window to top screen edge maximized horizontally, stack
			inactive windows alternating to bottom left and right screen corners

			-------------
			|     a     |
			-------------
			|     |     |
			-------------

	-btt	Snap active window to bottom screen edge maximized horizontally,
			stack inactive windows alternating to top left and right screen
			corners

			-------------
			|     |     |
			-------------
			|     a     |
			-------------

	-tblr	Snap all windows alternating to top and bottom left and right screen
			corners.

			-------------
			|     |     |
			-------------
			|     |     |
			-------------

	-m		Minimize resp. iconify all windows except active one on current.
			desktop
bin bash - (2012-09-05 04:09:24)
	-u		Unminimize resp. pop up all windows of and on current desktop
USAGE
}

# Create a default config file
function config () {
	cat << CONFIG
##WSNAP CONFIGURATION FILE#####################################################
# To ensure the script is working properly with your screen resolution and
# window manager theme you have to change the values of the following variables
# accordingly. Unit is pixels.
# To get the border sizes for your window manager theme have a look in the theme
# folder in /usr/share/themes/.
# The default values currently feature a 1440x900 wide screen resolution with
# window manager theme Shiki-Colors-Easy, one 32px panel at the bottom and a
# 1024x768 screen resolution for an external display device
################################################################################
# Screen resolution
screen_width="1440"
screen_height="900"

# External screen resolution
external_width="1024"
external_height="768"

# Top panel height
top_panel="0"

# Bottom panel height
bottom_panel="32"

# Left panel width
left_panel="0"

# Right panel width
right_panel="0"

# Window title bar height
title_bar="25"

# Window left border width
left_border="3"

# Window right border width
right_border="3"

# Window bottom border width
bottom_border="3"

# Additional window margins (space between window borders)
window_margin="1"
CONFIG
}

function version () {
	cat << VERSION
wsnap --
By Andreas Lis <mrkramps@googlemail.com>
Released under GNU General Public License 3.0
Copyright (c) 2011-2012

Last updated on 2012-09-05
VERSION
}

# Function to create and edit configuration file
# Configuration file contains remaining global variables
function setup () {
if [ -e $config_path/$config_file ]
then
	editor $config_path/$config_file
else
	mkdir -p $config_path
	config > $config_path/$config_file
	editor $config_path/$config_file
fi
}

function reset () {
	mv $config_path/$config_file $config_path/$config_file.bak
	setup
}

# Check if a configuration file is existent
if [ -e $config_path/$config_file ]
then
# Source configuration file tbin bash - (2012-09-05 04:09:24)o define remaining global variables
	if [ "$1" != "-h" ] && [ "$1" != "-?" ] && [ "$1" != "-V" ]
	then
		source $config_path/$config_file
	fi
else
# If non-existent invoke setup function except user manually executes setup
	if [ "$1" != "-s" ]
	then
		setup
	fi
fi

# Functions to define variables for window geometry
function left () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height - $title_bar - $bottom_border -$top_panel - $bottom_panel ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel  + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( 0 + $top_panel ))
}

function right () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height - $title_bar - $bottom_border -$top_panel - $bottom_panel ))
	# For use with wmctrl and gravity 10
	x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin + $right_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin ))
	#y=$(( 0 + $top_panel ))
}

function top () {
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	w=$(( $screen_width - $left_border - $right_border - $left_panel - $right_panel ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( 0 + $top_panel ))
}

function bottom () {
	w=$(( $screen_width - $left_border - $right_border - $left_panel - $right_panel ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 ))
}

function top_left () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel ))
	#y=$(( 0 + $top_panel ))
}

function bottom_left () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( 0 + $left_panel/2 + $right_panel/2 + $window_margin + $left_border ))
	y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( 0 + $left_panel/2 + $right_panel/2 + $window_margin ))
	#y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 ))
}

function top_right () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin + $right_border ))
	y=$(( 0 + $top_panel + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin ))
	#y=$(( 0 + $top_panel ))
}

function bottom_right () {
	w=$(( $screen_width/2 - $left_border - $right_border - $left_panel/2 - $right_panel/2 - $window_margin ))
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	# For use with wmctrl and gravity 10
	x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin + $right_border ))
	y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#x=$(( $screen_width/2 - $right_panel/2 + $left_panel/2 + $window_margin ))
	#y=$(( $screen_height/2 - $bottom_panel/2 + $top_panel/2 ))
}

function pos_top () {
	w="-1"
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	x="-1"
	# For use with wmctrl and gravity 10
	y=$(( 0 + $top_panel + $tbin bash - (2012-09-05 04:09:24)itle_bar ))
	# For use with wmctrl and gravity 0
	#y=$(( 0 + $top_panel ))
}

function pos_bottom () {
	w="-1"
	h=$(( $screen_height/2 - $title_bar - $bottom_border - $top_panel/2 - $bottom_panel/2 - $window_margin ))
	x="-1"
	# For use with wmctrl and gravity 10
	y=$(( $screen_height/2 - $bottom_panel/2 - $top_panel/2 + $title_bar ))
	# For use with wmctrl and gravity 0
	#y=$(( $screen_height/2 - $bottom_panel/2 - $top_panel/2 ))
}

function external () {
	w=$(( $external_width - $left_border - $right_border - $left_panel ))
	h=$(( $external_height - $title_bar - $bottom_border - $top_panel ))
	x=$(( 0 + $left_panel + $left_border ))
	y=$(( 0 + $top_panel + $title_bar ))
}

# wmctrl commands for window placement
# Use gravity 10 to influence window content geometry only and avoid problems
# with window manager theme borders not properly recognized for some programs
function place () {
	wmctrl -i -r $win_id -e 10,$x,$y,$w,$h
}

function place_active () {
	wmctrl -r :ACTIVE: -e 10,$x,$y,$w,$h
}

# Functions for each type of placement grid
function left_right () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		if [ "$(( $n % 2 ))" -eq "0" ]
		then
		left && place
		else
		right && place
		fi
	done
}

function top_bottom () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		if [ "$(( $n % 2 ))" -eq "0" ]
		then
			top && place
		else
			bottom && place
		fi
	done
}

function left_right_right () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				left && place
			else
				top_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then 
			if [ $win_active = $win_current ]
			then
				left && place
			else
				bottom_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				left && place
			else
				top_right && place
			fi
		fi
	done
}

function right_left_left () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				right && place
			else
				top_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then
			if [ $win_active = $win_current ]
			then
				right && place
			else
				bottom_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				right && place
			else
				top_left && place
			fi
		fi
	done
}

function top_bottom_bottom () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				top && place
			else
				bottom_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then
			if [ $win_active = $win_current ]
			then
				top && place
			else
				bottom_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				top && place
			else
				bottom_left && place
			fi
		fi
	done
}

function bottom_top_top () {
	for (( n=0 ; n <= $((win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		let win_current=$win_id
		if [ "$(( $n % 3 ))" -eq "0" ]
		then
			if [ $win_active = $win_current ]
			then
				bottom && place
			else
				top_left && place
			fi
		elif [ "$(( $n % 3 ))" -eq "1" ]
		then
			if [ $win_active = $win_current ]
			then
				bottom && place
			else
				top_right && place
			fi
		elif [ "$(( $n % 3 ))" -eq "2" ]
		then
			if [ $win_active = $win_current ]
			then
				bottom && place
			else
				top_left && place
			fi
		fi
	done
}

function top_bottom_left_right () {
	for (( n=0 ; n <= $(($win_count - 1)) ; n++ ))
	do
		win_id=${win_array[$n]}
		if [ "$(( $n % 4 ))" -eq "0" ]
		then
		top_left && place
		elif [ "$(( $n % 4 ))" -eq "1" ]
		then
		bottom_left && place
		elif [ "$(( $n % 4 ))" -eq "2" ]
		then
		top_right && place
		elif [ "$(( $n % 4 ))" -eq "3" ]
		then
		bottom_right && place
		fi
	done
}

function minimize () {
	for i in ${win_array[@]}
	do
		# wmctrl outputs hex, xdotool and xwit use decimal values for window IDs
		# let converts those hex to decimal values
		let win_id=$i
		if [ "$win_active" != "$win_id" ]
		then
		xwit -iconify -id $win_id
		fi
	done
}

function unminimize () {
	for i in ${win_array[@]}
	do
		# See function minimize for explaination
		let win_id=$i
		if [ "$win_active" != "$win_id" ]
		then
		# Give focus to each unhidden window to avoid pager blinking
		xwit -pop -focus -id $win_id
		fi
	done
	# Give focus to formerly active window again
	xwit -focus -id $win_active
}

# Bring together parameters and according functions
function w_snap () {
	case $1 in
		-h)
			usage
			echo ""
			version
			;;
		-\?)
			usage
			echo ""
			version
			;;
		-s)
			setup
			;;
		-d)
			reset
			;;
		-V)
			version
			;;
		-l)
			left && place_active
			;;
		-r)
			right && place_active
			;;
		-t)
			top && place_active
			;;
		-b)
			bottom && place_active
			;;
		-f)
			wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
			;;
		-pt)
			pos_top && place_active
			;;
		-pb)
			pos_bottom && place_active
			;;
		-tl)
			top_left && place_active
			;;
		-bl)
			bottom_left && place_active
			;;
		-tr)
			top_right && place_active
			;;
		-br)
			bottom_right && place_active
			;;
		-e)
			external && place_active
			;;
		-lr)
			left_right
			;;
		-tb)
			top_bottom
			;;
		-lrr)
			left_right_right
			;;
		-rll)
			right_left_left
			;;
		-tbb)
			top_bottom_bottom
			;;
		-btt)
			bottom_top_top
			;;
		-tblr)
			top_bottom_left_right
			;;
		-m)
			minimize
			;;
		-u)
			unminimize
			;;
		*)
			exit 1
			;;
	esac
}

# Let it happen
w_snap $1


Ich hab das Skript in diesem Zusammenhang nochmal überflogen und mir spontan überlegt, dass es sinnvoller wäre, statt einer Konfigurationsdatei in ~/.config einfach ein rc-Datei in $HOME zu verwenden. In der aktuellen Version wird $HOME/.config/win-fu/win-fu.cfg ersetzt durch $HOME/.wsnaprc

Zum Migrieren vorhandener Einstellungen:

mv $HOME/.config/win-fu/winfu.cfg $HOME/.wsnaprc && rm -r $HOME/.config/win-fu 


Jetzt fehlt nur noch ein Moderator, der den Threadtitel umbenennt… Ich wäre sehr verbunden. Danke.

wsnap-2012-09-05 (19.5 KiB)
Das Skript als Dateianhang
Download wsnap-2012-09-05
Antworten |