diff options
Diffstat (limited to 'swaybar/bar.c')
-rw-r--r-- | swaybar/bar.c | 122 |
1 files changed, 79 insertions, 43 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c index d80c9af3..b6329123 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -1,9 +1,10 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <unistd.h> | 2 | #include <unistd.h> |
3 | #include <string.h> | ||
3 | #include <fcntl.h> | 4 | #include <fcntl.h> |
4 | #include <errno.h> | 5 | #include <errno.h> |
5 | #include <sys/types.h> | ||
6 | #include <sys/wait.h> | 6 | #include <sys/wait.h> |
7 | #include <poll.h> | ||
7 | 8 | ||
8 | #include "ipc-client.h" | 9 | #include "ipc-client.h" |
9 | #include "list.h" | 10 | #include "list.h" |
@@ -17,11 +18,7 @@ | |||
17 | static void bar_init(struct bar *bar) { | 18 | static void bar_init(struct bar *bar) { |
18 | bar->config = init_config(); | 19 | bar->config = init_config(); |
19 | bar->status = init_status_line(); | 20 | bar->status = init_status_line(); |
20 | bar->output = malloc(sizeof(struct output)); | 21 | bar->outputs = create_list(); |
21 | bar->output->window = NULL; | ||
22 | bar->output->registry = NULL; | ||
23 | bar->output->workspaces = create_list(); | ||
24 | bar->output->name = NULL; | ||
25 | } | 22 | } |
26 | 23 | ||
27 | static void spawn_status_cmd_proc(struct bar *bar) { | 24 | static void spawn_status_cmd_proc(struct bar *bar) { |
@@ -49,78 +46,109 @@ static void spawn_status_cmd_proc(struct bar *bar) { | |||
49 | } | 46 | } |
50 | } | 47 | } |
51 | 48 | ||
49 | struct output *new_output(const char *name) { | ||
50 | struct output *output = malloc(sizeof(struct output)); | ||
51 | output->name = strdup(name); | ||
52 | output->window = NULL; | ||
53 | output->registry = NULL; | ||
54 | output->workspaces = create_list(); | ||
55 | return output; | ||
56 | } | ||
52 | 57 | ||
53 | void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id, int desired_output) { | 58 | void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { |
54 | /* initialize bar with default values */ | 59 | /* initialize bar with default values */ |
55 | bar_init(bar); | 60 | bar_init(bar); |
56 | 61 | ||
57 | bar->output->registry = registry_poll(); | ||
58 | |||
59 | if (!bar->output->registry->desktop_shell) { | ||
60 | sway_abort("swaybar requires the compositor to support the desktop-shell extension."); | ||
61 | } | ||
62 | |||
63 | /* connect to sway ipc */ | 62 | /* connect to sway ipc */ |
64 | bar->ipc_socketfd = ipc_open_socket(socket_path); | 63 | bar->ipc_socketfd = ipc_open_socket(socket_path); |
65 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); | 64 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); |
66 | 65 | ||
67 | ipc_bar_init(bar, desired_output, bar_id); | 66 | ipc_bar_init(bar, bar_id); |
68 | 67 | ||
69 | struct output_state *output = bar->output->registry->outputs->items[desired_output]; | 68 | int i; |
69 | for (i = 0; i < bar->outputs->length; ++i) { | ||
70 | struct output *bar_output = bar->outputs->items[i]; | ||
70 | 71 | ||
71 | bar->output->window = window_setup(bar->output->registry, output->width, 30, false); | 72 | bar_output->registry = registry_poll(); |
72 | if (!bar->output->window) { | ||
73 | sway_abort("Failed to create window."); | ||
74 | } | ||
75 | desktop_shell_set_panel(bar->output->registry->desktop_shell, output->output, bar->output->window->surface); | ||
76 | desktop_shell_set_panel_position(bar->output->registry->desktop_shell, bar->config->position); | ||
77 | 73 | ||
78 | /* set font */ | 74 | if (!bar_output->registry->desktop_shell) { |
79 | bar->output->window->font = bar->config->font; | 75 | sway_abort("swaybar requires the compositor to support the desktop-shell extension."); |
76 | } | ||
80 | 77 | ||
81 | /* set window height */ | 78 | struct output_state *output = bar_output->registry->outputs->items[bar_output->idx]; |
82 | set_window_height(bar->output->window, bar->config->height); | ||
83 | 79 | ||
80 | bar_output->window = window_setup(bar_output->registry, output->width, 30, false); | ||
81 | if (!bar_output->window) { | ||
82 | sway_abort("Failed to create window."); | ||
83 | } | ||
84 | desktop_shell_set_panel(bar_output->registry->desktop_shell, output->output, bar_output->window->surface); | ||
85 | desktop_shell_set_panel_position(bar_output->registry->desktop_shell, bar->config->position); | ||
86 | |||
87 | /* set font */ | ||
88 | bar_output->window->font = bar->config->font; | ||
89 | |||
90 | /* set window height */ | ||
91 | set_window_height(bar_output->window, bar->config->height); | ||
92 | } | ||
84 | /* spawn status command */ | 93 | /* spawn status command */ |
85 | spawn_status_cmd_proc(bar); | 94 | spawn_status_cmd_proc(bar); |
86 | } | 95 | } |
87 | 96 | ||
88 | void bar_run(struct bar *bar) { | 97 | void bar_run(struct bar *bar) { |
89 | fd_set readfds; | 98 | int pfds = bar->outputs->length + 2; |
90 | int activity; | 99 | struct pollfd *pfd = malloc(pfds * sizeof(struct pollfd)); |
91 | bool dirty = true; | 100 | bool dirty = true; |
92 | 101 | ||
102 | pfd[0].fd = bar->ipc_event_socketfd; | ||
103 | pfd[0].events = POLLIN; | ||
104 | pfd[1].fd = bar->status_read_fd; | ||
105 | pfd[1].events = POLLIN; | ||
106 | |||
107 | int i; | ||
108 | for (i = 0; i < bar->outputs->length; ++i) { | ||
109 | struct output *output = bar->outputs->items[i]; | ||
110 | pfd[i+2].fd = wl_display_get_fd(output->registry->display); | ||
111 | pfd[i+2].events = POLLIN; | ||
112 | } | ||
113 | |||
93 | while (1) { | 114 | while (1) { |
94 | if (dirty) { | 115 | if (dirty) { |
95 | struct output *output = bar->output; | 116 | int i; |
96 | if (window_prerender(output->window) && output->window->cairo) { | 117 | for (i = 0; i < bar->outputs->length; ++i) { |
97 | render(output, bar->config, bar->status); | 118 | struct output *output = bar->outputs->items[i]; |
98 | window_render(output->window); | 119 | if (window_prerender(output->window) && output->window->cairo) { |
99 | if (wl_display_dispatch(output->registry->display) == -1) { | 120 | render(output, bar->config, bar->status); |
100 | break; | 121 | window_render(output->window); |
122 | wl_display_flush(output->registry->display); | ||
101 | } | 123 | } |
102 | } | 124 | } |
103 | } | 125 | } |
104 | 126 | ||
105 | dirty = false; | 127 | dirty = false; |
106 | FD_ZERO(&readfds); | ||
107 | FD_SET(bar->ipc_event_socketfd, &readfds); | ||
108 | FD_SET(bar->status_read_fd, &readfds); | ||
109 | 128 | ||
110 | activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); | 129 | poll(pfd, pfds, -1); |
111 | if (activity < 0) { | ||
112 | sway_log(L_ERROR, "polling failed: %d", errno); | ||
113 | } | ||
114 | 130 | ||
115 | if (FD_ISSET(bar->ipc_event_socketfd, &readfds)) { | 131 | if (pfd[0].revents & POLLIN) { |
116 | sway_log(L_DEBUG, "Got IPC event."); | 132 | sway_log(L_DEBUG, "Got IPC event."); |
117 | dirty = handle_ipc_event(bar); | 133 | dirty = handle_ipc_event(bar); |
118 | } | 134 | } |
119 | 135 | ||
120 | if (bar->config->status_command && FD_ISSET(bar->status_read_fd, &readfds)) { | 136 | if (bar->config->status_command && pfd[1].revents & POLLIN) { |
121 | sway_log(L_DEBUG, "Got update from status command."); | 137 | sway_log(L_DEBUG, "Got update from status command."); |
122 | dirty = handle_status_line(bar); | 138 | dirty = handle_status_line(bar); |
123 | } | 139 | } |
140 | |||
141 | // dispatch wl_display events | ||
142 | for (i = 0; i < bar->outputs->length; ++i) { | ||
143 | struct output *output = bar->outputs->items[i]; | ||
144 | if (pfd[i+2].revents & POLLIN) { | ||
145 | if (wl_display_dispatch(output->registry->display) == -1) { | ||
146 | sway_log(L_ERROR, "failed to dispatch wl: %d", errno); | ||
147 | } | ||
148 | } else { | ||
149 | wl_display_dispatch_pending(output->registry->display); | ||
150 | } | ||
151 | } | ||
124 | } | 152 | } |
125 | } | 153 | } |
126 | 154 | ||
@@ -149,6 +177,14 @@ static void free_output(struct output *output) { | |||
149 | free(output); | 177 | free(output); |
150 | } | 178 | } |
151 | 179 | ||
180 | static void free_outputs(list_t *outputs) { | ||
181 | int i; | ||
182 | for (i = 0; i < outputs->length; ++i) { | ||
183 | free_output(outputs->items[i]); | ||
184 | } | ||
185 | list_free(outputs); | ||
186 | } | ||
187 | |||
152 | static void terminate_status_command(pid_t pid) { | 188 | static void terminate_status_command(pid_t pid) { |
153 | if (pid) { | 189 | if (pid) { |
154 | // terminate status_command process | 190 | // terminate status_command process |
@@ -164,7 +200,7 @@ static void terminate_status_command(pid_t pid) { | |||
164 | 200 | ||
165 | void bar_teardown(struct bar *bar) { | 201 | void bar_teardown(struct bar *bar) { |
166 | free_config(bar->config); | 202 | free_config(bar->config); |
167 | free_output(bar->output); | 203 | free_outputs(bar->outputs); |
168 | free_status_line(bar->status); | 204 | free_status_line(bar->status); |
169 | 205 | ||
170 | /* close sockets/pipes */ | 206 | /* close sockets/pipes */ |