aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/ui/browser.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/ui/browser.c')
-rw-r--r--tools/perf/util/ui/browser.c228
1 files changed, 155 insertions, 73 deletions
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 611219f80680..a54b926efe2b 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -1,4 +1,7 @@
1#include "../util.h"
2#include "../../perf.h"
1#include "libslang.h" 3#include "libslang.h"
4#include <newt.h>
2#include "ui.h" 5#include "ui.h"
3#include <linux/compiler.h> 6#include <linux/compiler.h>
4#include <linux/list.h> 7#include <linux/list.h>
@@ -8,8 +11,8 @@
8#include "browser.h" 11#include "browser.h"
9#include "helpline.h" 12#include "helpline.h"
10#include "../color.h" 13#include "../color.h"
11#include "../util.h" 14
12#include <stdio.h> 15int newtGetKey(void);
13 16
14static int ui_browser__percent_color(double percent, bool current) 17static int ui_browser__percent_color(double percent, bool current)
15{ 18{
@@ -39,31 +42,62 @@ void ui_browser__gotorc(struct ui_browser *self, int y, int x)
39 SLsmg_gotorc(self->y + y, self->x + x); 42 SLsmg_gotorc(self->y + y, self->x + x);
40} 43}
41 44
45static struct list_head *
46ui_browser__list_head_filter_entries(struct ui_browser *browser,
47 struct list_head *pos)
48{
49 do {
50 if (!browser->filter || !browser->filter(browser, pos))
51 return pos;
52 pos = pos->next;
53 } while (pos != browser->entries);
54
55 return NULL;
56}
57
58static struct list_head *
59ui_browser__list_head_filter_prev_entries(struct ui_browser *browser,
60 struct list_head *pos)
61{
62 do {
63 if (!browser->filter || !browser->filter(browser, pos))
64 return pos;
65 pos = pos->prev;
66 } while (pos != browser->entries);
67
68 return NULL;
69}
70
42void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence) 71void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
43{ 72{
44 struct list_head *head = self->entries; 73 struct list_head *head = self->entries;
45 struct list_head *pos; 74 struct list_head *pos;
46 75
76 if (self->nr_entries == 0)
77 return;
78
47 switch (whence) { 79 switch (whence) {
48 case SEEK_SET: 80 case SEEK_SET:
49 pos = head->next; 81 pos = ui_browser__list_head_filter_entries(self, head->next);
50 break; 82 break;
51 case SEEK_CUR: 83 case SEEK_CUR:
52 pos = self->top; 84 pos = self->top;
53 break; 85 break;
54 case SEEK_END: 86 case SEEK_END:
55 pos = head->prev; 87 pos = ui_browser__list_head_filter_prev_entries(self, head->prev);
56 break; 88 break;
57 default: 89 default:
58 return; 90 return;
59 } 91 }
60 92
93 assert(pos != NULL);
94
61 if (offset > 0) { 95 if (offset > 0) {
62 while (offset-- != 0) 96 while (offset-- != 0)
63 pos = pos->next; 97 pos = ui_browser__list_head_filter_entries(self, pos->next);
64 } else { 98 } else {
65 while (offset++ != 0) 99 while (offset++ != 0)
66 pos = pos->prev; 100 pos = ui_browser__list_head_filter_prev_entries(self, pos->prev);
67 } 101 }
68 102
69 self->top = pos; 103 self->top = pos;
@@ -127,11 +161,8 @@ bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
127 161
128void ui_browser__refresh_dimensions(struct ui_browser *self) 162void ui_browser__refresh_dimensions(struct ui_browser *self)
129{ 163{
130 int cols, rows; 164 self->width = SLtt_Screen_Cols - 1;
131 newtGetScreenSize(&cols, &rows); 165 self->height = SLtt_Screen_Rows - 2;
132
133 self->width = cols - 1;
134 self->height = rows - 2;
135 self->y = 1; 166 self->y = 1;
136 self->x = 0; 167 self->x = 0;
137} 168}
@@ -142,26 +173,11 @@ void ui_browser__reset_index(struct ui_browser *self)
142 self->seek(self, 0, SEEK_SET); 173 self->seek(self, 0, SEEK_SET);
143} 174}
144 175
145void ui_browser__add_exit_key(struct ui_browser *self, int key)
146{
147 newtFormAddHotKey(self->form, key);
148}
149
150void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
151{
152 int i = 0;
153
154 while (keys[i] && i < 64) {
155 ui_browser__add_exit_key(self, keys[i]);
156 ++i;
157 }
158}
159
160void __ui_browser__show_title(struct ui_browser *browser, const char *title) 176void __ui_browser__show_title(struct ui_browser *browser, const char *title)
161{ 177{
162 SLsmg_gotorc(0, 0); 178 SLsmg_gotorc(0, 0);
163 ui_browser__set_color(browser, NEWT_COLORSET_ROOT); 179 ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
164 slsmg_write_nstring(title, browser->width); 180 slsmg_write_nstring(title, browser->width + 1);
165} 181}
166 182
167void ui_browser__show_title(struct ui_browser *browser, const char *title) 183void ui_browser__show_title(struct ui_browser *browser, const char *title)
@@ -174,77 +190,143 @@ void ui_browser__show_title(struct ui_browser *browser, const char *title)
174int ui_browser__show(struct ui_browser *self, const char *title, 190int ui_browser__show(struct ui_browser *self, const char *title,
175 const char *helpline, ...) 191 const char *helpline, ...)
176{ 192{
193 int err;
177 va_list ap; 194 va_list ap;
178 int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
179 NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
180 NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
181
182 if (self->form != NULL)
183 newtFormDestroy(self->form);
184 195
185 ui_browser__refresh_dimensions(self); 196 ui_browser__refresh_dimensions(self);
186 self->form = newtForm(NULL, NULL, 0);
187 if (self->form == NULL)
188 return -1;
189
190 self->sb = newtVerticalScrollbar(self->width, 1, self->height,
191 HE_COLORSET_NORMAL,
192 HE_COLORSET_SELECTED);
193 if (self->sb == NULL)
194 return -1;
195 197
196 pthread_mutex_lock(&ui__lock); 198 pthread_mutex_lock(&ui__lock);
197 __ui_browser__show_title(self, title); 199 __ui_browser__show_title(self, title);
198 200
199 ui_browser__add_exit_keys(self, keys); 201 self->title = title;
200 newtFormAddComponent(self->form, self->sb); 202 free(self->helpline);
203 self->helpline = NULL;
201 204
202 va_start(ap, helpline); 205 va_start(ap, helpline);
203 ui_helpline__vpush(helpline, ap); 206 err = vasprintf(&self->helpline, helpline, ap);
204 va_end(ap); 207 va_end(ap);
208 if (err > 0)
209 ui_helpline__push(self->helpline);
205 pthread_mutex_unlock(&ui__lock); 210 pthread_mutex_unlock(&ui__lock);
206 return 0; 211 return err ? 0 : -1;
207} 212}
208 213
209void ui_browser__hide(struct ui_browser *self) 214void ui_browser__hide(struct ui_browser *browser __used)
210{ 215{
211 pthread_mutex_lock(&ui__lock); 216 pthread_mutex_lock(&ui__lock);
212 newtFormDestroy(self->form);
213 self->form = NULL;
214 ui_helpline__pop(); 217 ui_helpline__pop();
215 pthread_mutex_unlock(&ui__lock); 218 pthread_mutex_unlock(&ui__lock);
216} 219}
217 220
218int ui_browser__refresh(struct ui_browser *self) 221static void ui_browser__scrollbar_set(struct ui_browser *browser)
222{
223 int height = browser->height, h = 0, pct = 0,
224 col = browser->width,
225 row = browser->y - 1;
226
227 if (browser->nr_entries > 1) {
228 pct = ((browser->index * (browser->height - 1)) /
229 (browser->nr_entries - 1));
230 }
231
232 while (h < height) {
233 ui_browser__gotorc(browser, row++, col);
234 SLsmg_set_char_set(1);
235 SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_BOARD_CHAR);
236 SLsmg_set_char_set(0);
237 ++h;
238 }
239}
240
241static int __ui_browser__refresh(struct ui_browser *browser)
219{ 242{
220 int row; 243 int row;
221 244
245 row = browser->refresh(browser);
246 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
247 SLsmg_fill_region(browser->y + row, browser->x,
248 browser->height - row, browser->width, ' ');
249 ui_browser__scrollbar_set(browser);
250
251 return 0;
252}
253
254int ui_browser__refresh(struct ui_browser *browser)
255{
222 pthread_mutex_lock(&ui__lock); 256 pthread_mutex_lock(&ui__lock);
223 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); 257 __ui_browser__refresh(browser);
224 row = self->refresh(self);
225 ui_browser__set_color(self, HE_COLORSET_NORMAL);
226 SLsmg_fill_region(self->y + row, self->x,
227 self->height - row, self->width, ' ');
228 pthread_mutex_unlock(&ui__lock); 258 pthread_mutex_unlock(&ui__lock);
229 259
230 return 0; 260 return 0;
231} 261}
232 262
233int ui_browser__run(struct ui_browser *self) 263/*
264 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
265 * forget about any reference to any entry in the underlying data structure,
266 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
267 * after an output_resort and hist decay.
268 */
269void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
270{
271 off_t offset = nr_entries - browser->nr_entries;
272
273 browser->nr_entries = nr_entries;
274
275 if (offset < 0) {
276 if (browser->top_idx < (u64)-offset)
277 offset = -browser->top_idx;
278
279 browser->index += offset;
280 browser->top_idx += offset;
281 }
282
283 browser->top = NULL;
284 browser->seek(browser, browser->top_idx, SEEK_SET);
285}
286
287int ui_browser__run(struct ui_browser *self, int delay_secs)
234{ 288{
235 struct newtExitStruct es; 289 int err, key;
290 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
236 291
237 if (ui_browser__refresh(self) < 0) 292 pthread__unblock_sigwinch();
238 return -1;
239 293
240 while (1) { 294 while (1) {
241 off_t offset; 295 off_t offset;
296 fd_set read_set;
242 297
243 newtFormRun(self->form, &es); 298 pthread_mutex_lock(&ui__lock);
299 err = __ui_browser__refresh(self);
300 SLsmg_refresh();
301 pthread_mutex_unlock(&ui__lock);
302 if (err < 0)
303 break;
304
305 FD_ZERO(&read_set);
306 FD_SET(0, &read_set);
307
308 if (delay_secs) {
309 timeout.tv_sec = delay_secs;
310 timeout.tv_usec = 0;
311 }
244 312
245 if (es.reason != NEWT_EXIT_HOTKEY) 313 err = select(1, &read_set, NULL, NULL, ptimeout);
314 if (err > 0 && FD_ISSET(0, &read_set))
315 key = newtGetKey();
316 else if (err == 0)
246 break; 317 break;
247 switch (es.u.key) { 318 else {
319 pthread_mutex_lock(&ui__lock);
320 SLtt_get_screen_size();
321 SLsmg_reinit_smg();
322 pthread_mutex_unlock(&ui__lock);
323 ui_browser__refresh_dimensions(self);
324 __ui_browser__show_title(self, self->title);
325 ui_helpline__puts(self->helpline);
326 continue;
327 }
328
329 switch (key) {
248 case NEWT_KEY_DOWN: 330 case NEWT_KEY_DOWN:
249 if (self->index == self->nr_entries - 1) 331 if (self->index == self->nr_entries - 1)
250 break; 332 break;
@@ -301,10 +383,8 @@ int ui_browser__run(struct ui_browser *self)
301 self->seek(self, -offset, SEEK_END); 383 self->seek(self, -offset, SEEK_END);
302 break; 384 break;
303 default: 385 default:
304 return es.u.key; 386 return key;
305 } 387 }
306 if (ui_browser__refresh(self) < 0)
307 return -1;
308 } 388 }
309 return -1; 389 return -1;
310} 390}
@@ -316,27 +396,29 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
316 int row = 0; 396 int row = 0;
317 397
318 if (self->top == NULL || self->top == self->entries) 398 if (self->top == NULL || self->top == self->entries)
319 self->top = head->next; 399 self->top = ui_browser__list_head_filter_entries(self, head->next);
320 400
321 pos = self->top; 401 pos = self->top;
322 402
323 list_for_each_from(pos, head) { 403 list_for_each_from(pos, head) {
324 ui_browser__gotorc(self, row, 0); 404 if (!self->filter || !self->filter(self, pos)) {
325 self->write(self, pos, row); 405 ui_browser__gotorc(self, row, 0);
326 if (++row == self->height) 406 self->write(self, pos, row);
327 break; 407 if (++row == self->height)
408 break;
409 }
328 } 410 }
329 411
330 return row; 412 return row;
331} 413}
332 414
333static struct newtPercentTreeColors { 415static struct ui_browser__colors {
334 const char *topColorFg, *topColorBg; 416 const char *topColorFg, *topColorBg;
335 const char *mediumColorFg, *mediumColorBg; 417 const char *mediumColorFg, *mediumColorBg;
336 const char *normalColorFg, *normalColorBg; 418 const char *normalColorFg, *normalColorBg;
337 const char *selColorFg, *selColorBg; 419 const char *selColorFg, *selColorBg;
338 const char *codeColorFg, *codeColorBg; 420 const char *codeColorFg, *codeColorBg;
339} defaultPercentTreeColors = { 421} ui_browser__default_colors = {
340 "red", "lightgray", 422 "red", "lightgray",
341 "green", "lightgray", 423 "green", "lightgray",
342 "black", "lightgray", 424 "black", "lightgray",
@@ -346,7 +428,7 @@ static struct newtPercentTreeColors {
346 428
347void ui_browser__init(void) 429void ui_browser__init(void)
348{ 430{
349 struct newtPercentTreeColors *c = &defaultPercentTreeColors; 431 struct ui_browser__colors *c = &ui_browser__default_colors;
350 432
351 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); 433 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
352 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); 434 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);