Remove newline from startupnotify description
[mikachu/openbox.git] / openbox / actions / desktop.c
1 #include "openbox/actions.h"
2 #include "openbox/screen.h"
3 #include "openbox/client.h"
4 #include <glib.h>
5
6 typedef enum {
7     LAST,
8     RELATIVE,
9     ABSOLUTE
10 } SwitchType;
11
12 typedef struct {
13     SwitchType type;
14     union {
15         struct {
16             guint desktop;
17         } abs;
18
19         struct {
20             gboolean linear;
21             gboolean wrap;
22             ObDirection dir;
23         } rel;
24     } u;
25     gboolean send;
26     gboolean follow;
27 } Options;
28
29 static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
30                                   xmlNodePtr node);
31 static gpointer setup_send_func(ObParseInst *i, xmlDocPtr doc,
32                                 xmlNodePtr node);
33 static gboolean run_func(ObActionsData *data, gpointer options);
34
35 void action_desktop_startup(void)
36 {
37     actions_register("GoToDesktop", setup_go_func, g_free, run_func,
38                      NULL, NULL);
39     actions_register("SendToDesktop", setup_send_func, g_free, run_func,
40                      NULL, NULL);
41 }
42
43 static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
44                                   xmlNodePtr node)
45 {
46     xmlNodePtr n;
47     Options *o;
48
49     o = g_new0(Options, 1);
50     /* don't go anywhere if theres no options given */
51     o->type = ABSOLUTE;
52     o->u.abs.desktop = screen_desktop;
53     /* wrap by default - it's handy! */
54     o->u.rel.wrap = TRUE;
55
56     if ((n = parse_find_node("to", node))) {
57         gchar *s = parse_string(doc, n);
58         if (!g_ascii_strcasecmp(s, "last"))
59             o->type = LAST;
60         else if (!g_ascii_strcasecmp(s, "next")) {
61             o->type = RELATIVE;
62             o->u.rel.linear = TRUE;
63             o->u.rel.dir = OB_DIRECTION_EAST;
64         }
65         else if (!g_ascii_strcasecmp(s, "previous")) {
66             o->type = RELATIVE;
67             o->u.rel.linear = TRUE;
68             o->u.rel.dir = OB_DIRECTION_WEST;
69         }
70         else if (!g_ascii_strcasecmp(s, "north") ||
71                  !g_ascii_strcasecmp(s, "up")) {
72             o->type = RELATIVE;
73             o->u.rel.dir = OB_DIRECTION_NORTH;
74         }
75         else if (!g_ascii_strcasecmp(s, "south") ||
76                  !g_ascii_strcasecmp(s, "down")) {
77             o->type = RELATIVE;
78             o->u.rel.dir = OB_DIRECTION_SOUTH;
79         }
80         else if (!g_ascii_strcasecmp(s, "west") ||
81                  !g_ascii_strcasecmp(s, "left")) {
82             o->type = RELATIVE;
83             o->u.rel.dir = OB_DIRECTION_WEST;
84         }
85         else if (!g_ascii_strcasecmp(s, "east") ||
86                  !g_ascii_strcasecmp(s, "right")) {
87             o->type = RELATIVE;
88             o->u.rel.dir = OB_DIRECTION_EAST;
89         }
90         else {
91             o->type = ABSOLUTE;
92             o->u.abs.desktop = atoi(s) - 1;
93         }
94         g_free(s);
95     }
96
97     if ((n = parse_find_node("wrap", node)))
98         o->u.rel.wrap = parse_bool(doc, n);
99
100     return o;
101 }
102
103 static gpointer setup_send_func(ObParseInst *i, xmlDocPtr doc,
104                                 xmlNodePtr node)
105 {
106     xmlNodePtr n;
107     Options *o;
108
109     o = setup_go_func(i, doc, node);
110     o->send = TRUE;
111     o->follow = TRUE;
112
113     if ((n = parse_find_node("follow", node)))
114         o->follow = parse_bool(doc, n);
115
116     return o;
117 }
118
119 /* Always return FALSE because its not interactive */
120 static gboolean run_func(ObActionsData *data, gpointer options)
121 {
122     Options *o = options;
123     guint d;
124
125     switch (o->type) {
126     case LAST:
127         d = screen_last_desktop;
128         break;
129     case ABSOLUTE:
130         d = o->u.abs.desktop;
131         break;
132     case RELATIVE:
133         d = screen_find_desktop(screen_desktop,
134                                 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
135         break;
136     }
137
138     if (d < screen_num_desktops && d != screen_desktop) {
139         gboolean go = TRUE;
140
141         actions_client_move(data, TRUE);
142         if (o->send && data->client && client_normal(data->client)) {
143             client_set_desktop(data->client, d, o->follow, FALSE);
144             go = o->follow;
145         }
146
147         if (go) {
148             screen_set_desktop(d, TRUE);
149             if (data->client)
150                 client_bring_helper_windows(data->client);
151         }
152
153         actions_client_move(data, FALSE);
154     }
155     return FALSE;
156 }