[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Monitor names



So yeah, I implemented monitor names :)
As previously mentioned I'll probably correct the small changes you
proposed in the error messages patchset soon. If you have more time
than me currently, feel free to do it yourself ;)

 MIGRATION            |   9 ++
 NEWS                 |   1 +
 doc/herbstluftwm.txt |  79 +++++++------
 src/command.c        |  35 +++++-
 src/command.h        |   1 +
 src/main.c           |  15 ++-
 src/monitor.c        | 275 ++++++++++++++++++++++++++++++++-----------
 src/monitor.h        |  12 +-
 src/stack.c          |   9 +-
 9 files changed, 322 insertions(+), 114 deletions(-)

Florian Bruhin (10):
      Add monitor names to add_monitor
      Add monitor names to stack command
      Add monitor names to list_monitors
      Add string_to_monitor/monitor_index functions
      Make focus_monitor accept output
      Add monitor names to all commands using monitors
      Add monitor argument to list_padding
      Add new command name_monitor
      Implement completion for monitor names
      Add monitor names to shift_to_monitor

-- 
() ascii ribbon campaign - stop html mail    www.asciiribbon.org
/\ www.the-compiler.org  | I love long mails http://email.is-not-s.ms/
The more things change, the more they stay insane. 
From e969d9eb63406fff7ed147db05dd4d44b3968ac0 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Sun, 25 Nov 2012 23:59:00 +0100
Subject: [PATCH 01/10] Add monitor names to add_monitor

---
 MIGRATION            |  5 +++++
 NEWS                 |  1 +
 doc/herbstluftwm.txt | 11 +++++------
 src/monitor.c        | 55 +++++++++++++++++++++++++++++++++++++++++++---------
 src/monitor.h        |  5 ++++-
 5 files changed, 61 insertions(+), 16 deletions(-)

diff --git a/MIGRATION b/MIGRATION
index 64974dc..fe742af 100644
--- a/MIGRATION
+++ b/MIGRATION
@@ -10,6 +10,11 @@ herbstclient now returns the exitstatus 9 (HERBST_NEED_MORE_ARGS) instead of 3
 (HERBST_INVALID_ARGUMENT) if a command needs more arguments. If an error occurs,
 it now outputs an error message to stderr.
 
+The padding arguments have been removed from add_monitor and a monitor name has
+been added instead. If you add a monitor with padding, instead of 'hc
+add_monitor 1024x768+0+0 1 2 3 4' now use 'hc add_monitor 1024x768+0+0; hc pad N
+1 2 3 4'.
+
 0.3 to 0.4
 ~~~~~~~~~~
 The setting window_gap is now called frame_gap. Simply replace all occurrences
diff --git a/NEWS b/NEWS
index 7a69e51..75a5095 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,7 @@ Changes:
     * add error messages for herbstclient
     * new command: shift_edge
     * new command: shift_to_monitor
+    * optional names for monitors
 
 Release: 0.4.1 on 2012-08-30
 ----------------------------
diff --git a/doc/herbstluftwm.txt b/doc/herbstluftwm.txt
index 54178f6..fd52ae2 100644
--- a/doc/herbstluftwm.txt
+++ b/doc/herbstluftwm.txt
@@ -503,15 +503,14 @@ detect_monitors::
     Xinerama extension is missing, it will fall back to one monitor across the
     entire screen.
 
-add_monitor 'RECT' ['TAG' ['PADUP' ['PADRIGHT' ['PADDOWN' ['PADLEFT']]]]]::
+add_monitor 'RECT' ['TAG' ['NAME']]::
     Adds a monitor on the specified rectangle 'RECT' and displays 'TAG' on it.
     'TAG' currently must not be displayed on any other monitor. 'RECT' is a
-    string of the form 'WxH±X±Y'. The padding specifies extra space around the
-    monitor for some statusbars/panels. If no or an empty padding is given, it
-    is set to 0. If no or an empty 'TAG' is given, then any free tag will be
-    chosen. Example:
+    string of the form 'WxH±X±Y'. If no or an empty 'TAG' is given, then any
+    free tag will be chosen. If a 'NAME' is given, you can reference to this
+    monitor by its name instead of using an index. Example:
 
-        * add_monitor 1024x768-20+0 mynewtag 16
+        * add_monitor 1024x768-20+0 mynewtag main
 
 
 remove_monitor 'INDEX'::
diff --git a/src/monitor.c b/src/monitor.c
index a3be74c..a08bb31 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <ctype.h>
 #ifdef XINERAMA
 #include <X11/extensions/Xinerama.h>
 #endif /* XINERAMA */
@@ -310,7 +311,7 @@ int set_monitor_rects(XRectangle* templates, size_t count) {
         if (!tag) {
             return HERBST_TAG_IN_USE;
         }
-        add_monitor(templates[i], tag);
+        add_monitor(templates[i], tag, NULL);
         frame_show_recursive(tag->frame);
     }
     // remove monitors if there are too much
@@ -321,11 +322,32 @@ int set_monitor_rects(XRectangle* templates, size_t count) {
     return 0;
 }
 
-HSMonitor* add_monitor(XRectangle rect, HSTag* tag) {
+int find_monitor_index_by_name(char* name) {
+    int i;
+    for (i = 0; i < g_monitors->len; i++) {
+        HSMonitor* mon = monitor_with_index(i);
+        if (mon != NULL && mon->name != NULL && !strcmp(mon->name->str, name)) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+HSMonitor* find_monitor_by_name(char* name) {
+    int i = find_monitor_index_by_name(name);
+    if (i == -1) {
+        return NULL;
+    } else {
+        return monitor_with_index(i);
+    }
+}
+
+HSMonitor* add_monitor(XRectangle rect, HSTag* tag, char* name) {
     assert(tag != NULL);
     HSMonitor* m = g_new0(HSMonitor, 1);
     m->rect = rect;
     m->tag = tag;
+    m->name = (name ? g_string_new(name) : NULL);
     m->mouse.x = 0;
     m->mouse.y = 0;
     m->dirty = true;
@@ -338,12 +360,13 @@ HSMonitor* add_monitor(XRectangle rect, HSTag* tag) {
 }
 
 int add_monitor_command(int argc, char** argv, GString* output) {
-    // usage: add_monitor RECTANGLE [TAG [PADUP [PADRIGHT [PADDOWN [PADLEFT]]]]]
+    // usage: add_monitor RECTANGLE [TAG [NAME]]
     if (argc < 2) {
         return HERBST_NEED_MORE_ARGS;
     }
     XRectangle rect = parse_rectangle(argv[1]);
     HSTag* tag = NULL;
+    char* name = NULL;
     if (argc == 2 || !strcmp("", argv[2])) {
         tag = find_unused_tag();
         if (!tag) {
@@ -365,11 +388,25 @@ int add_monitor_command(int argc, char** argv, GString* output) {
             "%s: The tag \"%s\" is already viewed on a monitor\n", argv[0], argv[2]);
         return HERBST_TAG_IN_USE;
     }
-    HSMonitor* monitor = add_monitor(rect, tag);
-    if (argc > 3 && argv[3][0] != '\0') monitor->pad_up       = atoi(argv[3]);
-    if (argc > 4 && argv[4][0] != '\0') monitor->pad_right    = atoi(argv[4]);
-    if (argc > 5 && argv[5][0] != '\0') monitor->pad_down     = atoi(argv[5]);
-    if (argc > 6 && argv[6][0] != '\0') monitor->pad_left     = atoi(argv[6]);
+    if (argc > 3) {
+        name = argv[3];
+        if (isdigit(name[0])) {
+            g_string_append_printf(output,
+                "%s: The monitor name may not start with a number\n", argv[0]);
+            return HERBST_INVALID_ARGUMENT;
+        }
+        if (!strcmp("", name)) {
+            g_string_append_printf(output,
+                "%s: An empty monitor name is not permitted\n", argv[0]);
+            return HERBST_INVALID_ARGUMENT;
+        }
+        if (find_monitor_by_name(name)) {
+            g_string_append_printf(output,
+                "%s: A monitor with the same name already exists\n", argv[0]);
+            return HERBST_INVALID_ARGUMENT;
+        }
+    }
+    HSMonitor* monitor = add_monitor(rect, tag, name);
     frame_show_recursive(tag->frame);
     monitor_apply_layout(monitor);
     emit_tag_changed(tag, g_monitors->len - 1);
@@ -546,7 +583,7 @@ void ensure_monitors_are_available() {
     };
     ensure_tags_are_available();
     // add monitor with first tag
-    HSMonitor* m = add_monitor(rect, g_array_index(g_tags, HSTag*, 0));
+    HSMonitor* m = add_monitor(rect, g_array_index(g_tags, HSTag*, 0), NULL);
     g_cur_monitor = 0;
     g_cur_frame = m->tag->frame;
 }
diff --git a/src/monitor.h b/src/monitor.h
index 1b7d9dd..ca846e1 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -21,6 +21,7 @@ struct HSStack;
 typedef struct HSMonitor {
     struct HSTag*      tag;    // currently viewed tag
     struct HSSlice*    slice;  // slice in the monitor stack
+    GString*    name;
     int         pad_up;
     int         pad_right;
     int         pad_down;
@@ -48,13 +49,15 @@ HSMonitor* monitor_with_frame(struct HSFrame* frame);
 HSMonitor* monitor_with_coordinate(int x, int y);
 HSMonitor* monitor_with_index(int index);
 HSMonitor* find_monitor_with_tag(struct HSTag* tag);
-HSMonitor* add_monitor(XRectangle rect, struct HSTag* tag);
+HSMonitor* add_monitor(XRectangle rect, struct HSTag* tag, char* name);
 void monitor_focus_by_index(int new_selection);
 int monitor_get_relative_x(HSMonitor* m, int x_root);
 int monitor_get_relative_y(HSMonitor* m, int y_root);
 int monitor_index_of(HSMonitor* monitor);
 int monitor_cycle_command(int argc, char** argv);
 int monitor_focus_command(int argc, char** argv);
+int find_monitor_index_by_name(char* name);
+HSMonitor* find_monitor_by_name(char* name);
 int add_monitor_command(int argc, char** argv, GString* output);
 int monitor_raise_command(int argc, char** argv, GString* output);
 int remove_monitor_command(int argc, char** argv, GString* output);
-- 
1.8.0.1

From c98302263ed022980fb49889c29b3f6794d722ad Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Mon, 26 Nov 2012 00:27:30 +0100
Subject: [PATCH 02/10] Add monitor names to stack command

---
 src/stack.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/stack.c b/src/stack.c
index 5915e89..5ca8e61 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -108,6 +108,7 @@ void stack_remove_slice(HSStack* s, HSSlice* elem) {
 
 static void slice_append_caption(HSTree root, GString* output) {
     HSSlice* slice = (HSSlice*)root;
+    GString* monitor_name = g_string_new("");
     switch (slice->type) {
         case SLICE_WINDOW:
             g_string_append_printf(output, "Window 0x%lx",
@@ -119,11 +120,17 @@ static void slice_append_caption(HSTree root, GString* output) {
                                    slice->data.client->title->str);
             break;
         case SLICE_MONITOR:
-            g_string_append_printf(output, "Monitor %d with tag \"%s\"",
+            if (slice->data.monitor->name != NULL) {
+                g_string_append_printf(monitor_name, " (\"%s\")",
+                                       slice->data.monitor->name->str);
+            }
+            g_string_append_printf(output, "Monitor %d%s with tag \"%s\"",
                                    monitor_index_of(slice->data.monitor),
+                                   monitor_name->str,
                                    slice->data.monitor->tag->name->str);
             break;
     }
+    g_string_free(monitor_name, true);
 }
 
 static struct HSTreeInterface slice_nth_child(HSTree root, size_t idx) {
-- 
1.8.0.1

From 80970c28664d34e3a8206393e695e17b0c33ff91 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Mon, 26 Nov 2012 07:12:42 +0100
Subject: [PATCH 03/10] Add monitor names to list_monitors

---
 MIGRATION            |  3 +++
 doc/herbstluftwm.txt |  4 ++--
 src/monitor.c        | 11 ++++++++++-
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/MIGRATION b/MIGRATION
index fe742af..c7e3e22 100644
--- a/MIGRATION
+++ b/MIGRATION
@@ -15,6 +15,9 @@ been added instead. If you add a monitor with padding, instead of 'hc
 add_monitor 1024x768+0+0 1 2 3 4' now use 'hc add_monitor 1024x768+0+0; hc pad N
 1 2 3 4'.
 
+As a result from adding monitor names, the output of list_monitors and stack
+changes a bit for named monitors.
+
 0.3 to 0.4
 ~~~~~~~~~~
 The setting window_gap is now called frame_gap. Simply replace all occurrences
diff --git a/doc/herbstluftwm.txt b/doc/herbstluftwm.txt
index fd52ae2..6183619 100644
--- a/doc/herbstluftwm.txt
+++ b/doc/herbstluftwm.txt
@@ -140,8 +140,8 @@ list_commands::
     Lists all available commands.
 
 [[list_monitors]]list_monitors::
-    List currently configured monitors with their index, area (as rectangle) and
-    currently viewed tag.
+    List currently configured monitors with their index, area (as rectangle),
+    name (if named) and currently viewed tag.
 
 list_keybinds::
     Lists all bound keys with their associated command. Each line consists of
diff --git a/src/monitor.c b/src/monitor.c
index a08bb31..be08055 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -104,16 +104,25 @@ int list_monitors(int argc, char** argv, GString* output) {
     (void)argc;
     (void)argv;
     int i;
+    GString* monitor_name = g_string_new("");
     for (i = 0; i < g_monitors->len; i++) {
         HSMonitor* monitor = monitor_with_index(i);
-        g_string_append_printf(output, "%d: %dx%d%+d%+d with tag \"%s\"%s%s\n",
+        if (monitor->name != NULL ) {
+            g_string_printf(monitor_name, ", named \"%s\"",
+                            monitor->name->str);
+        } else {
+            g_string_truncate(monitor_name, 0);
+        }
+        g_string_append_printf(output, "%d: %dx%d%+d%+d with tag \"%s\"%s%s%s\n",
             i,
             monitor->rect.width, monitor->rect.height,
             monitor->rect.x, monitor->rect.y,
             monitor->tag ? monitor->tag->name->str : "???",
+            monitor_name->str,
             (g_cur_monitor == i) ? " [FOCUS]" : "",
             monitor->lock_tag ? " [LOCKED]" : "");
     }
+    g_string_free(monitor_name, true);
     return 0;
 }
 
-- 
1.8.0.1

From 14ef2b4b0969d8390591de2000a5ef9fa610f718 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Tue, 27 Nov 2012 22:17:07 +0100
Subject: [PATCH 04/10] Add string_to_monitor/monitor_index functions

---
 src/monitor.c | 35 +++++++++++++++++++++++++++++++++++
 src/monitor.h |  2 ++
 2 files changed, 37 insertions(+)

diff --git a/src/monitor.c b/src/monitor.c
index be08055..41ecd95 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -351,6 +351,41 @@ HSMonitor* find_monitor_by_name(char* name) {
     }
 }
 
+int string_to_monitor_index(char* string) {
+    int idx = -1;
+    if (string[0] == '\0') {
+        return -1;
+    }
+    if (isdigit(string[0])) {
+        // monitor index
+        idx = atoi(string);
+        if (idx < 0 || idx >= g_monitors->len) {
+            return -1;
+        }
+        return idx;
+    } else {
+        // monitor string
+        return find_monitor_index_by_name(string);
+    }
+}
+
+HSMonitor* string_to_monitor(char* string) {
+    if (string[0] == '\0') {
+        return NULL;
+    }
+    if (isdigit(string[0])) {
+        // monitor index
+        int idx = atoi(string);
+        if (idx < 0 || idx >= g_monitors->len) {
+            return NULL;
+        }
+        return monitor_with_index(idx);
+    } else {
+        // monitor string
+        return find_monitor_by_name(string);
+    }
+}
+
 HSMonitor* add_monitor(XRectangle rect, HSTag* tag, char* name) {
     assert(tag != NULL);
     HSMonitor* m = g_new0(HSMonitor, 1);
diff --git a/src/monitor.h b/src/monitor.h
index ca846e1..7265139 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -58,6 +58,8 @@ int monitor_cycle_command(int argc, char** argv);
 int monitor_focus_command(int argc, char** argv);
 int find_monitor_index_by_name(char* name);
 HSMonitor* find_monitor_by_name(char* name);
+HSMonitor* string_to_monitor(char* string);
+int string_to_monitor_index(char* string);
 int add_monitor_command(int argc, char** argv, GString* output);
 int monitor_raise_command(int argc, char** argv, GString* output);
 int remove_monitor_command(int argc, char** argv, GString* output);
-- 
1.8.0.1

From 07be0f5c9ff73ac7557d02699221e6f23f43dc92 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Wed, 28 Nov 2012 23:19:12 +0100
Subject: [PATCH 05/10] Make focus_monitor accept output

---
 src/main.c    | 2 +-
 src/monitor.c | 2 +-
 src/monitor.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main.c b/src/main.c
index f375da9..d095227 100644
--- a/src/main.c
+++ b/src/main.c
@@ -118,7 +118,7 @@ CommandBinding g_commands[] = {
     CMD_BIND(             "toggle",         settings_toggle),
     CMD_BIND(             "cycle_value",    settings_cycle_value),
     CMD_BIND_NO_OUTPUT(   "cycle_monitor",  monitor_cycle_command),
-    CMD_BIND_NO_OUTPUT(   "focus_monitor",  monitor_focus_command),
+    CMD_BIND(             "focus_monitor",  monitor_focus_command),
     CMD_BIND(             "get",            settings_get),
     CMD_BIND(             "add",            tag_add_command),
     CMD_BIND(             "use",            monitor_set_tag_command),
diff --git a/src/monitor.c b/src/monitor.c
index 41ecd95..d901d45 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -769,7 +769,7 @@ int monitor_set_tag_by_index_command(int argc, char** argv, GString* output) {
     return ret;
 }
 
-int monitor_focus_command(int argc, char** argv) {
+int monitor_focus_command(int argc, char** argv, GString* output) {
     if (argc < 2) {
         return HERBST_NEED_MORE_ARGS;
     }
diff --git a/src/monitor.h b/src/monitor.h
index 7265139..bd4e6c5 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -55,7 +55,7 @@ int monitor_get_relative_x(HSMonitor* m, int x_root);
 int monitor_get_relative_y(HSMonitor* m, int y_root);
 int monitor_index_of(HSMonitor* monitor);
 int monitor_cycle_command(int argc, char** argv);
-int monitor_focus_command(int argc, char** argv);
+int monitor_focus_command(int argc, char** argv, GString* output);
 int find_monitor_index_by_name(char* name);
 HSMonitor* find_monitor_by_name(char* name);
 HSMonitor* string_to_monitor(char* string);
-- 
1.8.0.1

From d10d2a7eb1a97081fbcb2655737af2a14158c26d Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Tue, 27 Nov 2012 23:06:58 +0100
Subject: [PATCH 06/10] Add monitor names to all commands using monitors

---
 doc/herbstluftwm.txt | 55 ++++++++++++++++--------------
 src/main.c           | 12 +++++--
 src/monitor.c        | 94 ++++++++++++++++++++++++++++------------------------
 3 files changed, 90 insertions(+), 71 deletions(-)

diff --git a/doc/herbstluftwm.txt b/doc/herbstluftwm.txt
index 6183619..7b64dff 100644
--- a/doc/herbstluftwm.txt
+++ b/doc/herbstluftwm.txt
@@ -117,8 +117,18 @@ Tags are very similar to workspaces, virtual desktops or window groups. Each
 tag has one layout. There is a list of tags. You can add or remove tags
 dynamically.
 
-There is also a list of monitors. Each monitor displays exactly one tag on a
-specified rectangle on the screen.
+[[MONITORS]]
+MONITORS
+--------
+Monitors in *herbstluftwm* are totally independent of the actual physical
+screens. This means you can for example split your screen in two virtual
+monitors to view two tags at once on a big screen.
+
+Each monitor displays exactly one tag on a specified rectangle on the screen.
+
+A monitor can be referenced in two ways: by its 'INDEX' as listed in the
+*list_monitors* command, or by a name defined when adding the monitor.
+
 
 [[COMMANDS]]
 COMMANDS
@@ -413,9 +423,8 @@ cycle_value 'NAME' 'VALUES' ...::
 cycle_monitor ['DELTA']::
     Cycles monitor focused by 'DELTA'. 'DELTA' defaults to 1.
 
-focus_monitor 'INDEX'::
-    Puts focus to monitor with specified 'INDEX' (as specified by the
-    list_monitors command)
+focus_monitor 'MONITOR'::
+    Puts focus to specified monitor.
 
 add 'TAG'::
     Creates a new empty tag named 'TAG'.
@@ -448,8 +457,8 @@ move_index 'INDEX' [*--skip-visible*]::
     treated relative. If *--skip-visible* is passed with a relative index, then
     already visible tags are skipped.
 
-lock_tag ['INDEX']::
-    Lock the tag switching on the monitor specified by INDEX. If no
+lock_tag ['MONITOR']::
+    Lock the tag switching on the specified monitor. If no
     argument is given, the currently focused monitor is used. When the
     tag switching is disabled for a monitor, the commands *use* and
     *use_index* have no effect, when executed there. When
@@ -458,8 +467,8 @@ lock_tag ['INDEX']::
     stealing it from there. The lock state of a monitor is indicated
     by "[LOCKED]" in the *list_monitors* output.
 
-unlock_tag ['INDEX']::
-    Re-enables the tag switching on the monitor specified by INDEX. If no
+unlock_tag ['MONITOR']::
+    Re-enables the tag switching on the specified monitor. If no
     argument is given, the currently focused  monitor is used. This is the reverse
     operation to *lock_tag* and has no further side effects but removing this lock.
 
@@ -513,17 +522,15 @@ add_monitor 'RECT' ['TAG' ['NAME']]::
         * add_monitor 1024x768-20+0 mynewtag main
 
 
-remove_monitor 'INDEX'::
-    Removes the monitor with specified 'INDEX'. Its 'INDEX' can be found out via
-    the <<list_monitors,'list_monitors'>> command.
+remove_monitor 'MONITOR'::
+    Removes the specified monitor.
 
-move_monitor 'INDEX' 'RECT' ['PADUP' ['PADRIGHT' ['PADDOWN' ['PADLEFT']]]]::
-    Moves the monitor with specified 'INDEX' to rectangle 'RECT'. 'INDEX' and
-    'RECT' are defined as in 'remove_monitor' and 'add_monitor'. If no or an
-    empty pad is given, it is not changed.
+move_monitor 'MONITOR' 'RECT' ['PADUP' ['PADRIGHT' ['PADDOWN' ['PADLEFT']]]]::
+    Moves the specified monitor to rectangle 'RECT'. 'RECT' is defined as in
+    'add_monitor'. If no or an empty pad is given, it is not changed.
 
-raise_monitor ['INDEX']::
-    Raises the monitor with the given 'INDEX' or the current one if 'INDEX' is
+raise_monitor ['MONITOR']::
+    Raises the specified monitor or the current one if 'MONITOR' is
     omitted.
 
 stack::
@@ -531,15 +538,15 @@ stack::
     tree. The order printed stack is top to bottom. The style is configured by
     the 'tree_style' setting.
 
-monitor_rect [[-p] 'INDEX']::
-    Prints the rectangle of the specified 'INDEX' in the format: *X Y W H* +
-    If no 'INDEX' or 'cur' is given, then the current Monitor is used. If '-p'
+monitor_rect [[-p] 'MONITOR']::
+    Prints the rectangle of the specified monitor in the format: *X Y W H* +
+    If no 'MONITOR' or 'cur' is given, then the current Monitor is used. If '-p'
     is supplied, then the remaining rect without the pad around this monitor
     is printed.
 
-pad 'INDEX' ['PADUP' ['PADRIGHT' ['PADDOWN' ['PADLEFT']]]]::
-    Sets the pad of indexed monitor to the specified padding. If no or an empty
-    padding is given, it is not changed.
+pad 'MONITOR' ['PADUP' ['PADRIGHT' ['PADDOWN' ['PADLEFT']]]]::
+    Sets the pad of specified monitor to the specified padding. If no or an
+    empty padding is given, it is not changed.
 
 list_padding::
     Lists the padding of all monitors.
diff --git a/src/main.c b/src/main.c
index d095227..12501a3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -261,13 +261,19 @@ int load_command(int argc, char** argv, GString* output) {
 }
 
 int print_tag_status_command(int argc, char** argv, GString* output) {
+    HSMonitor* monitor;
     int monitor_index = g_cur_monitor;
     if (argc >= 2) {
-        monitor_index = atoi(argv[1]);
+        monitor = string_to_monitor(argv[1]);
+    } else {
+        monitor = monitor_with_index(g_cur_monitor);
+    }
+    if (monitor == NULL) {
+        g_string_append_printf(output,
+            "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
+        return HERBST_INVALID_ARGUMENT;
     }
-    monitor_index = CLAMP(monitor_index, 0, monitor_count() - 1);
     tag_update_flags();
-    HSMonitor* monitor = monitor_with_index(monitor_index);
     g_string_append_c(output, '\t');
     for (int i = 0; i < g_tags->len; i++) {
         HSTag* tag = g_array_index(g_tags, HSTag*, i);
diff --git a/src/monitor.c b/src/monitor.c
index d901d45..3d4db11 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -462,7 +462,12 @@ int remove_monitor_command(int argc, char** argv, GString* output) {
     if (argc < 2) {
         return HERBST_NEED_MORE_ARGS;
     }
-    int index = atoi(argv[1]);
+    int index = string_to_monitor_index(argv[1]);
+    if (index == -1) {
+        g_string_append_printf(output,
+            "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
+        return HERBST_INVALID_ARGUMENT;
+    }
     int ret = remove_monitor(index);
     if (ret == HERBST_INVALID_ARGUMENT) {
         g_string_append_printf(output,
@@ -512,10 +517,10 @@ int move_monitor_command(int argc, char** argv, GString* output) {
     if (argc < 3) {
         return HERBST_NEED_MORE_ARGS;
     }
-    int index = atoi(argv[1]);
-    if (index < 0 || index >= g_monitors->len) {
+    HSMonitor* monitor = string_to_monitor(argv[1]);
+    if (monitor == NULL) {
         g_string_append_printf(output,
-            "%s: Index %i is out of range\n", argv[0], index);
+            "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
         return HERBST_INVALID_ARGUMENT;
     }
     XRectangle rect = parse_rectangle(argv[2]);
@@ -525,7 +530,6 @@ int move_monitor_command(int argc, char** argv, GString* output) {
         return HERBST_INVALID_ARGUMENT;
     }
     // else: just move it:
-    HSMonitor* monitor = monitor_with_index(index);
     monitor->rect = rect;
     if (argc > 3 && argv[3][0] != '\0') monitor->pad_up       = atoi(argv[3]);
     if (argc > 4 && argv[4][0] != '\0') monitor->pad_right    = atoi(argv[4]);
@@ -537,17 +541,17 @@ int move_monitor_command(int argc, char** argv, GString* output) {
 
 int monitor_rect_command(int argc, char** argv, GString* output) {
     // usage: monitor_rect [[-p] INDEX]
-    char* index_str = NULL;
+    char* monitor_str = NULL;
     HSMonitor* m = NULL;
     bool with_pad = false;
 
-    // if index is supplied
+    // if monitor is supplied
     if (argc > 1) {
-        index_str = argv[1];
+        monitor_str = argv[1];
     }
     // if -p is supplied
     if (argc > 2) {
-        index_str = argv[2];
+        monitor_str = argv[2];
         if (!strcmp("-p", argv[1])) {
             with_pad = true;
         } else {
@@ -557,19 +561,14 @@ int monitor_rect_command(int argc, char** argv, GString* output) {
         }
     }
     // if an index is set
-    if (index_str) {
-        int index;
-        if (1 == sscanf(index_str, "%d", &index)) {
-            m = monitor_with_index(index);
-            if (!m) {
-                g_string_append_printf(output,
-                    "%s: Invalid index \"%s\"\n", argv[0], index_str);
-                return HERBST_INVALID_ARGUMENT;
-            }
+    if (monitor_str) {
+        m = string_to_monitor(monitor_str);
+        if (m == NULL) {
+            g_string_append_printf(output,
+                "%s: Monitor \"%s\" not found!\n", argv[0], monitor_str);
+            return HERBST_INVALID_ARGUMENT;
         }
-    }
-
-    if (!m) {
+    } else {
         m = get_current_monitor();
     }
     XRectangle rect = m->rect;
@@ -588,13 +587,12 @@ int monitor_set_pad_command(int argc, char** argv, GString* output) {
     if (argc < 2) {
         return HERBST_NEED_MORE_ARGS;
     }
-    int index = atoi(argv[1]);
-    if (index < 0 || index >= g_monitors->len) {
+    HSMonitor* monitor = string_to_monitor(argv[1]);
+    if (monitor == NULL) {
         g_string_append_printf(output,
-            "%s: Index %i is out of range\n", argv[0], index);
+            "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
         return HERBST_INVALID_ARGUMENT;
     }
-    HSMonitor* monitor = monitor_with_index(index);
     if (argc > 2 && argv[2][0] != '\0') monitor->pad_up       = atoi(argv[2]);
     if (argc > 3 && argv[3][0] != '\0') monitor->pad_right    = atoi(argv[3]);
     if (argc > 4 && argv[4][0] != '\0') monitor->pad_down     = atoi(argv[4]);
@@ -773,7 +771,12 @@ int monitor_focus_command(int argc, char** argv, GString* output) {
     if (argc < 2) {
         return HERBST_NEED_MORE_ARGS;
     }
-    int new_selection = atoi(argv[1]);
+    int new_selection = string_to_monitor_index(argv[1]);
+    if (new_selection == -1) {
+        g_string_append_printf(output,
+            "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
+        return HERBST_INVALID_ARGUMENT;
+    }
     // really change selection
     monitor_focus_by_index(new_selection);
     return 0;
@@ -934,35 +937,37 @@ void monitors_lock_changed() {
 }
 
 int monitor_lock_tag_command(int argc, char** argv, GString* output) {
+    char* cmd_name = argv[0];
     (void)SHIFT(argc, argv);
     HSMonitor *monitor;
     if (argc >= 1) {
-        monitor = monitor_with_index(atoi(argv[0]));
+        monitor = string_to_monitor(argv[0]);
+        if (monitor == NULL) {
+            g_string_append_printf(output,
+                "%s: Monitor \"%s\" not found!\n", cmd_name, argv[0]);
+            return HERBST_INVALID_ARGUMENT;
+        }
     } else {
         monitor = get_current_monitor();
     }
-    if (!monitor) {
-        g_string_append_printf(output,
-            "%s: Invalid monitor\n", argv[0]);
-        return HERBST_INVALID_ARGUMENT;
-    }
     monitor->lock_tag = true;
     return 0;
 }
 
 int monitor_unlock_tag_command(int argc, char** argv, GString* output) {
+    char* cmd_name = argv[0];
     (void)SHIFT(argc, argv);
     HSMonitor *monitor;
     if (argc >= 1) {
-        monitor = monitor_with_index(atoi(argv[0]));
+        monitor = string_to_monitor(argv[0]);
+        if (monitor == NULL) {
+            g_string_append_printf(output,
+                "%s: Monitor \"%s\" not found!\n", cmd_name, argv[0]);
+            return HERBST_INVALID_ARGUMENT;
+        }
     } else {
         monitor = get_current_monitor();
     }
-    if (!monitor) {
-        g_string_append_printf(output,
-            "%s: Invalid monitor\n", argv[0]);
-        return HERBST_INVALID_ARGUMENT;
-    }
     monitor->lock_tag = false;
     return 0;
 }
@@ -1070,18 +1075,19 @@ HSStack* get_monitor_stack() {
 }
 
 int monitor_raise_command(int argc, char** argv, GString* output) {
+    char* cmd_name = argv[0];
     (void)SHIFT(argc, argv);
     HSMonitor* monitor;
     if (argc >= 1) {
-        monitor = monitor_with_index(atoi(argv[0]));
+        monitor = string_to_monitor(argv[0]);
+        if (monitor == NULL) {
+            g_string_append_printf(output,
+                "%s: Monitor \"%s\" not found!\n", cmd_name, argv[0]);
+            return HERBST_INVALID_ARGUMENT;
+        }
     } else {
         monitor = get_current_monitor();
     }
-    if (!monitor) {
-        g_string_append_printf(output,
-            "%s: Invalid monitor\n", argv[0]);
-        return HERBST_INVALID_ARGUMENT;
-    }
     stack_raise_slide(g_monitor_stack, monitor->slice);
     return 0;
 }
-- 
1.8.0.1

From 158dc4a135e43cc85a47f66b847b8cbe14938c70 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Tue, 27 Nov 2012 23:18:04 +0100
Subject: [PATCH 07/10] Add monitor argument to list_padding

---
 MIGRATION            |  3 ++-
 doc/herbstluftwm.txt |  5 +++--
 src/command.c        |  2 +-
 src/monitor.c        | 26 +++++++++++++++-----------
 4 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/MIGRATION b/MIGRATION
index c7e3e22..17b4ecc 100644
--- a/MIGRATION
+++ b/MIGRATION
@@ -16,7 +16,8 @@ add_monitor 1024x768+0+0 1 2 3 4' now use 'hc add_monitor 1024x768+0+0; hc pad N
 1 2 3 4'.
 
 As a result from adding monitor names, the output of list_monitors and stack
-changes a bit for named monitors.
+changes a bit for named monitors. list_padding only outputs the padding for one
+monitor now.
 
 0.3 to 0.4
 ~~~~~~~~~~
diff --git a/doc/herbstluftwm.txt b/doc/herbstluftwm.txt
index 7b64dff..01890ce 100644
--- a/doc/herbstluftwm.txt
+++ b/doc/herbstluftwm.txt
@@ -548,8 +548,9 @@ pad 'MONITOR' ['PADUP' ['PADRIGHT' ['PADDOWN' ['PADLEFT']]]]::
     Sets the pad of specified monitor to the specified padding. If no or an
     empty padding is given, it is not changed.
 
-list_padding::
-    Lists the padding of all monitors.
+list_padding ['MONITOR']::
+    Lists the padding of the specified monitor, or the currently focused monitor
+    if no monitor is given.
 
 layout ['TAG' ['INDEX']]::
     Prints the layout of frame with 'INDEX' in 'TAG', in a nice tree style.
diff --git a/src/command.c b/src/command.c
index 5214ad8..e57500b 100644
--- a/src/command.c
+++ b/src/command.c
@@ -104,7 +104,7 @@ struct {
     { "stack",          2,  no_completion },
     { "monitor_rect",   3,  no_completion },
     { "pad",            6,  no_completion },
-    { "list_padding",   1,  no_completion },
+    { "list_padding",   2,  no_completion },
     { "layout",         3,  no_completion },
     { "dump",           3,  no_completion },
     { "load",           3,  no_completion },
diff --git a/src/monitor.c b/src/monitor.c
index 3d4db11..e31276f 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -127,18 +127,22 @@ int list_monitors(int argc, char** argv, GString* output) {
 }
 
 int list_padding(int argc, char** argv, GString* output) {
-    (void)argc;
-    (void)argv;
-    int i;
-    for (i = 0; i < g_monitors->len; i++) {
-        HSMonitor* monitor = monitor_with_index(i);
-        g_string_append_printf(output, "%d: %d %d %d %d\n",
-            i,
-            monitor->pad_up,
-            monitor->pad_right,
-            monitor->pad_down,
-            monitor->pad_left);
+    HSMonitor* monitor;
+    if (argc < 2) {
+        monitor = get_current_monitor();
+    } else {
+        monitor = string_to_monitor(argv[1]);
+        if (monitor == NULL) {
+            g_string_append_printf(output,
+                "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
+            return HERBST_INVALID_ARGUMENT;
+        }
     }
+    g_string_append_printf(output, "%d %d %d %d\n",
+        monitor->pad_up,
+        monitor->pad_right,
+        monitor->pad_down,
+        monitor->pad_left);
     return 0;
 }
 
-- 
1.8.0.1

From 78534587fa81f227bb73b861a1305eeef883502e Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Wed, 28 Nov 2012 00:11:32 +0100
Subject: [PATCH 08/10] Add new command name_monitor

---
 NEWS                 |  2 +-
 doc/herbstluftwm.txt |  4 ++++
 src/command.c        |  1 +
 src/main.c           |  1 +
 src/monitor.c        | 38 ++++++++++++++++++++++++++++++++++++++
 src/monitor.h        |  1 +
 6 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 75a5095..2ee6c5e 100644
--- a/NEWS
+++ b/NEWS
@@ -27,7 +27,7 @@ Changes:
     * add error messages for herbstclient
     * new command: shift_edge
     * new command: shift_to_monitor
-    * optional names for monitors
+    * optional names for monitors, new command name_monitor
 
 Release: 0.4.1 on 2012-08-30
 ----------------------------
diff --git a/doc/herbstluftwm.txt b/doc/herbstluftwm.txt
index 01890ce..c6ffc6e 100644
--- a/doc/herbstluftwm.txt
+++ b/doc/herbstluftwm.txt
@@ -533,6 +533,10 @@ raise_monitor ['MONITOR']::
     Raises the specified monitor or the current one if 'MONITOR' is
     omitted.
 
+name_monitor 'MONITOR' 'NAME'::
+    (Re)names an already existing monitor. If 'NAME' is empty, removes the
+    monitor's name.
+
 stack::
     Prints the stack of monitors with the visible tags and their layers as a
     tree. The order printed stack is top to bottom. The style is configured by
diff --git a/src/command.c b/src/command.c
index e57500b..71c1b00 100644
--- a/src/command.c
+++ b/src/command.c
@@ -98,6 +98,7 @@ struct {
     { "unlock_tag",     2,  no_completion },
     { "detect_monitors",1,  no_completion },
     { "add_monitor",    7,  no_completion },
+    { "name_monitor",   3,  no_completion },
     { "remove_monitor", 2,  no_completion },
     { "move_monitor",   7,  no_completion },
     { "raise_monitor",  2,  no_completion },
diff --git a/src/main.c b/src/main.c
index 12501a3..3d11c90 100644
--- a/src/main.c
+++ b/src/main.c
@@ -137,6 +137,7 @@ CommandBinding g_commands[] = {
     CMD_BIND(             "raise_monitor",  monitor_raise_command),
     CMD_BIND(             "remove_monitor", remove_monitor_command),
     CMD_BIND(             "move_monitor",   move_monitor_command),
+    CMD_BIND(             "name_monitor",   name_monitor_command),
     CMD_BIND(             "monitor_rect",   monitor_rect_command),
     CMD_BIND(             "pad",            monitor_set_pad_command),
     CMD_BIND(             "raise",          raise_command),
diff --git a/src/monitor.c b/src/monitor.c
index e31276f..9a8bcf3 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -543,6 +543,44 @@ int move_monitor_command(int argc, char** argv, GString* output) {
     return 0;
 }
 
+int name_monitor_command(int argc, char** argv, GString* output) {
+    if (argc < 3) {
+        return HERBST_NEED_MORE_ARGS;
+    }
+    HSMonitor* mon = string_to_monitor(argv[1]);
+    if (mon == NULL) {
+        g_string_append_printf(output,
+            "%s: Monitor \"%s\" not found!\n", argv[0], argv[1]);
+        return HERBST_INVALID_ARGUMENT;
+    }
+    if (isdigit(argv[2][0])) {
+        g_string_append_printf(output,
+            "%s: The monitor name may not start with a number\n", argv[0]);
+        return HERBST_INVALID_ARGUMENT;
+    } else if (!strcmp("", argv[2])) {
+        // empty name -> clear name
+        if (mon->name != NULL) {
+            g_string_free(mon->name, true);
+            mon->name = NULL;
+        }
+        return 0;
+    }
+    if (find_monitor_by_name(argv[2])) {
+        g_string_append_printf(output,
+            "%s: A monitor with the same name already exists\n", argv[0]);
+        return HERBST_INVALID_ARGUMENT;
+    }
+    if (mon->name == NULL) {
+        // not named before
+        GString* name = g_string_new(argv[2]);
+        mon->name = name;
+    } else {
+        // already named
+        g_string_assign(mon->name, argv[2]);
+    }
+    return 0;
+}
+
 int monitor_rect_command(int argc, char** argv, GString* output) {
     // usage: monitor_rect [[-p] INDEX]
     char* monitor_str = NULL;
diff --git a/src/monitor.h b/src/monitor.h
index bd4e6c5..4fd6836 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -70,6 +70,7 @@ int set_monitor_rects_command(int argc, char** argv, GString* output);
 int disjoin_rects_command(int argc, char** argv, GString* output);
 int set_monitor_rects(XRectangle* templates, size_t count);
 int move_monitor_command(int argc, char** argv, GString* output);
+int name_monitor_command(int argc, char** argv, GString* output);
 int monitor_rect_command(int argc, char** argv, GString* output);
 HSMonitor* get_current_monitor();
 int monitor_count();
-- 
1.8.0.1

From ccee8d40e930ade8cb0945a8b840b00b8df711d6 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Wed, 28 Nov 2012 00:24:40 +0100
Subject: [PATCH 09/10] Implement completion for monitor names

---
 src/command.c | 32 ++++++++++++++++++++++++++++++++
 src/command.h |  1 +
 src/monitor.c |  1 -
 src/monitor.h |  2 ++
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/src/command.c b/src/command.c
index 71c1b00..a4cb743 100644
--- a/src/command.c
+++ b/src/command.c
@@ -10,6 +10,7 @@
 #include "layout.h"
 #include "key.h"
 #include "clientlist.h"
+#include "monitor.h"
 
 #include <glib.h>
 #include <string.h>
@@ -102,6 +103,7 @@ struct {
     { "remove_monitor", 2,  no_completion },
     { "move_monitor",   7,  no_completion },
     { "raise_monitor",  2,  no_completion },
+    { "name_monitor",   3,  no_completion },
     { "stack",          2,  no_completion },
     { "monitor_rect",   3,  no_completion },
     { "pad",            6,  no_completion },
@@ -197,6 +199,17 @@ struct {
     { "use",            EQ, 1,  .function = complete_against_tags },
     { "use_index",      EQ, 1,  .list = completion_pm_one },
     { "use_index",      EQ, 2,  .list = completion_use_index_args },
+    { "focus_monitor",  EQ, 1,  .function = complete_against_monitors },
+    { "lock_tag",       EQ, 1,  .function = complete_against_monitors },
+    { "unlock_tag",     EQ, 1,  .function = complete_against_monitors },
+    { "remove_monitor", EQ, 1,  .function = complete_against_monitors },
+    { "move_monitor",   EQ, 1,  .function = complete_against_monitors },
+    { "raise_monitor",  EQ, 1,  .function = complete_against_monitors },
+    { "name_monitor",   EQ, 1,  .function = complete_against_monitors },
+    { "monitor_rect",   EQ, 1,  .function = complete_against_monitors },
+    { "pad",            EQ, 1,  .function = complete_against_monitors },
+    { "list_padding",   EQ, 1,  .function = complete_against_monitors },
+    { "tag_status",     EQ, 1,  .function = complete_against_monitors },
     { 0 },
 };
 
@@ -286,6 +299,25 @@ void complete_negate(int argc, char** argv, int pos, GString* output) {
     complete_against_commands(argc, argv, pos, output);
 }
 
+void complete_against_monitors(int argc, char** argv, int pos, GString* output) {
+    char* needle;
+    if (pos >= argc) {
+        needle = "";
+    } else {
+        needle = argv[pos];
+    }
+    size_t len = strlen(needle);
+    for (int i = 0; i < g_monitors->len; i++) {
+        GString* name = g_array_index(g_monitors, HSMonitor*, i)->name;
+        if (name != NULL) {
+            if (!strncmp(needle, name->str, len)) {
+                g_string_append(output, name->str);
+                g_string_append(output, "\n");
+            }
+        }
+    }
+}
+
 struct wcd { /* window id completion data */
     char* needle;
     size_t needlelen;
diff --git a/src/command.h b/src/command.h
index a4e329e..759c1ff 100644
--- a/src/command.h
+++ b/src/command.h
@@ -43,6 +43,7 @@ int complete_command(int argc, char** argv, GString* output);
 void complete_settings(char* str, GString* output);
 void complete_against_list(char* needle, char** list, GString* output);
 void complete_against_tags(int argc, char** argv, int pos, GString* output);
+void complete_against_monitors(int argc, char** argv, int pos, GString* output);
 void complete_against_winids(int argc, char** argv, int pos, GString* output);
 void complete_merge_tag(int argc, char** argv, int pos, GString* output);
 void complete_negate(int argc, char** argv, int pos, GString* output);
diff --git a/src/monitor.c b/src/monitor.c
index 9a8bcf3..73ad0c9 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -30,7 +30,6 @@ int* g_swap_monitors_to_get_tag;
 int* g_smart_frame_surroundings;
 int* g_mouse_recenter_gap;
 HSStack* g_monitor_stack;
-GArray*     g_monitors; // Array of HSMonitor*
 
 typedef struct RectList {
     XRectangle rect;
diff --git a/src/monitor.h b/src/monitor.h
index 4fd6836..ba9235d 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -18,6 +18,8 @@ struct HSFrame;
 struct HSSlice;
 struct HSStack;
 
+GArray*     g_monitors; // Array of HSMonitor*
+
 typedef struct HSMonitor {
     struct HSTag*      tag;    // currently viewed tag
     struct HSSlice*    slice;  // slice in the monitor stack
-- 
1.8.0.1

From 2dc8296d0d7960a57948084fc47a67bdf2db7fb7 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org>
Date: Sun, 9 Dec 2012 23:56:08 +0100
Subject: [PATCH 10/10] Add monitor names to shift_to_monitor

---
 src/monitor.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/monitor.c b/src/monitor.c
index 73ad0c9..ef2e848 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -1156,17 +1156,20 @@ int shift_to_monitor(int argc, char** argv, GString* output) {
     if (argc <= 1) {
         return HERBST_NEED_MORE_ARGS;
     }
-    char* index_str = argv[1];
-    bool is_relative = array_find("+-", 2, sizeof(char), &index_str[0]) >= 0;
-    int i = atoi(index_str);
+    HSMonitor* monitor = NULL;
+    char* monitor_str = argv[1];
+    bool is_relative = array_find("+-", 2, sizeof(char), &monitor_str[0]) >= 0;
     if (is_relative) {
+        int i = atoi(monitor_str);
         i += g_cur_monitor;
         i = MOD(i, g_monitors->len);
+        monitor = monitor_with_index(i);
+    } else {
+        monitor = string_to_monitor(monitor_str);
     }
-    HSMonitor* monitor = monitor_with_index(i);
     if (!monitor) {
         g_string_append_printf(output,
-            "%s: Invalid monitor\n", index_str);
+            "%s: Invalid monitor\n", monitor_str);
         return HERBST_INVALID_ARGUMENT;
     }
     tag_move_focused_client(monitor->tag);
-- 
1.8.0.1

Attachment: pgp1UIJ0YK71V.pgp
Description: PGP signature