rofi  1.7.3
view.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
29 #define G_LOG_DOMAIN "View"
30 
31 #include "config.h"
32 #include <errno.h>
33 #include <locale.h>
34 #include <signal.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40 #include <unistd.h>
41 #include <xcb/xcb_ewmh.h>
42 #include <xcb/xcb_icccm.h>
43 #include <xcb/xkb.h>
44 #include <xkbcommon/xkbcommon-x11.h>
45 
46 #include <cairo-xcb.h>
47 #include <cairo.h>
48 
50 #define SN_API_NOT_YET_FROZEN
51 #include "rofi.h"
52 #include <libsn/sn.h>
53 
54 #include "settings.h"
55 #include "timings.h"
56 
57 #include "dialogs/dialogs.h"
58 #include "display.h"
59 #include "helper-theme.h"
60 #include "helper.h"
61 #include "mode.h"
62 #include "xcb-internal.h"
63 #include "xrmoptions.h"
64 
65 #include "view-internal.h"
66 #include "view.h"
67 
68 #include "theme.h"
69 
70 #include "xcb.h"
71 
78 void rofi_view_update(RofiViewState *state, gboolean qr);
79 
80 static int rofi_view_calculate_height(RofiViewState *state);
81 
83 GThreadPool *tpool = NULL;
84 
87 
91 struct {
93  xcb_window_t main_window;
95  cairo_surface_t *fake_bg;
97  xcb_gcontext_t gc;
99  xcb_pixmap_t edit_pixmap;
101  cairo_surface_t *edit_surf;
103  cairo_t *edit_draw;
109  GQueue views;
117  unsigned long long count;
121  gboolean fullscreen;
124 } CacheState = {
125  .main_window = XCB_WINDOW_NONE,
126  .fake_bg = NULL,
127  .edit_surf = NULL,
128  .edit_draw = NULL,
129  .fake_bgrel = FALSE,
130  .flags = MENU_NORMAL,
131  .views = G_QUEUE_INIT,
132  .idle_timeout = 0,
133  .user_timeout = 0,
134  .count = 0L,
135  .repaint_source = 0,
136  .fullscreen = FALSE,
137 };
138 
139 void rofi_view_get_current_monitor(int *width, int *height) {
140  if (width) {
141  *width = CacheState.mon.w;
142  }
143  if (height) {
144  *height = CacheState.mon.h;
145  }
146 }
147 static char *get_matching_state(void) {
148  if (config.case_sensitive) {
149  if (config.sort) {
150  return "±";
151  }
152  return "-";
153  }
154  if (config.sort) {
155  return "+";
156  }
157  return " ";
158 }
159 
163 static int lev_sort(const void *p1, const void *p2, void *arg) {
164  const int *a = p1;
165  const int *b = p2;
166  int *distances = arg;
167 
168  return distances[*a] - distances[*b];
169 }
170 
175  const char *outp = g_getenv("ROFI_PNG_OUTPUT");
176  if (CacheState.edit_surf == NULL) {
177  // Nothing to store.
178  g_warning("There is no rofi surface to store");
179  return;
180  }
181  const char *xdg_pict_dir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
182  if (outp == NULL && xdg_pict_dir == NULL) {
183  g_warning("XDG user picture directory or ROFI_PNG_OUTPUT is not set. "
184  "Cannot store screenshot.");
185  return;
186  }
187  // Get current time.
188  GDateTime *now = g_date_time_new_now_local();
189  // Format filename.
190  char *timestmp = g_date_time_format(now, "rofi-%Y-%m-%d-%H%M");
191  char *filename = g_strdup_printf("%s-%05d.png", timestmp, 0);
192  // Build full path
193  char *fpath = NULL;
194  if (outp == NULL) {
195  int index = 0;
196  fpath = g_build_filename(xdg_pict_dir, filename, NULL);
197  while (g_file_test(fpath, G_FILE_TEST_EXISTS) && index < 99) {
198  g_free(fpath);
199  g_free(filename);
200  // Try the next index.
201  index++;
202  // Format filename.
203  filename = g_strdup_printf("%s-%05d.png", timestmp, index);
204  // Build full path
205  fpath = g_build_filename(xdg_pict_dir, filename, NULL);
206  }
207  } else {
208  fpath = g_strdup(outp);
209  }
210  fprintf(stderr, color_green "Storing screenshot %s\n" color_reset, fpath);
211  cairo_status_t status =
212  cairo_surface_write_to_png(CacheState.edit_surf, fpath);
213  if (status != CAIRO_STATUS_SUCCESS) {
214  g_warning("Failed to produce screenshot '%s', got error: '%s'", fpath,
215  cairo_status_to_string(status));
216  }
217  g_free(fpath);
218  g_free(filename);
219  g_free(timestmp);
220  g_date_time_unref(now);
221 }
222 
227 gboolean do_bench = TRUE;
228 
232 static struct {
234  GTimer *time;
236  uint64_t draws;
238  double last_ts;
240  double min;
241 } BenchMark = {.time = NULL, .draws = 0, .last_ts = 0.0, .min = G_MAXDOUBLE};
242 
243 static gboolean bench_update(void) {
244  if (!config.benchmark_ui) {
245  return FALSE;
246  }
247  BenchMark.draws++;
248  if (BenchMark.time == NULL) {
249  BenchMark.time = g_timer_new();
250  }
251 
252  if ((BenchMark.draws & 1023) == 0) {
253  double ts = g_timer_elapsed(BenchMark.time, NULL);
254  double fps = 1024 / (ts - BenchMark.last_ts);
255 
256  if (fps < BenchMark.min) {
257  BenchMark.min = fps;
258  }
259  printf("current: %.2f fps, avg: %.2f fps, min: %.2f fps, %lu draws\r\n",
260  fps, BenchMark.draws / ts, BenchMark.min, BenchMark.draws);
261 
262  BenchMark.last_ts = ts;
263  }
264  return TRUE;
265 }
266 
267 static gboolean rofi_view_repaint(G_GNUC_UNUSED void *data) {
268  if (current_active_menu) {
269  // Repaint the view (if needed).
270  // After a resize the edit_pixmap surface might not contain anything
271  // anymore. If we already re-painted, this does nothing.
273  g_debug("expose event");
274  TICK_N("Expose");
275  xcb_copy_area(xcb->connection, CacheState.edit_pixmap,
276  CacheState.main_window, CacheState.gc, 0, 0, 0, 0,
278  xcb_flush(xcb->connection);
279  TICK_N("flush");
280  CacheState.repaint_source = 0;
281  }
282  return (bench_update() == TRUE) ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
283 }
284 
286  if (state->prompt) {
287  const char *str = mode_get_display_name(state->sw);
288  textbox_text(state->prompt, str);
289  }
290 }
291 
304 static const int loc_transtable[9] = {
307  WL_WEST};
309  int location = rofi_theme_get_position(WIDGET(state->main_window), "location",
311  int anchor = location;
313  anchor = location;
314  if (location == WL_CENTER) {
315  anchor = WL_NORTH;
316  } else if (location == WL_EAST) {
317  anchor = WL_NORTH_EAST;
318  } else if (location == WL_WEST) {
319  anchor = WL_NORTH_WEST;
320  }
321  }
322  anchor =
323  rofi_theme_get_position(WIDGET(state->main_window), "anchor", anchor);
324 
325  if (CacheState.fullscreen) {
326  state->x = CacheState.mon.x;
327  state->y = CacheState.mon.y;
328  return;
329  }
330  state->y = CacheState.mon.y + (CacheState.mon.h) / 2;
331  state->x = CacheState.mon.x + (CacheState.mon.w) / 2;
332  // Determine window location
333  switch (location) {
334  case WL_NORTH_WEST:
335  state->x = CacheState.mon.x;
336  /* FALLTHRU */
337  case WL_NORTH:
338  state->y = CacheState.mon.y;
339  break;
340  case WL_NORTH_EAST:
341  state->y = CacheState.mon.y;
342  /* FALLTHRU */
343  case WL_EAST:
344  state->x = CacheState.mon.x + CacheState.mon.w;
345  break;
346  case WL_SOUTH_EAST:
347  state->x = CacheState.mon.x + CacheState.mon.w;
348  /* FALLTHRU */
349  case WL_SOUTH:
350  state->y = CacheState.mon.y + CacheState.mon.h;
351  break;
352  case WL_SOUTH_WEST:
353  state->y = CacheState.mon.y + CacheState.mon.h;
354  /* FALLTHRU */
355  case WL_WEST:
356  state->x = CacheState.mon.x;
357  break;
358  case WL_CENTER:;
359  /* FALLTHRU */
360  default:
361  break;
362  }
363  switch (anchor) {
364  case WL_SOUTH_WEST:
365  state->y -= state->height;
366  break;
367  case WL_SOUTH:
368  state->x -= state->width / 2;
369  state->y -= state->height;
370  break;
371  case WL_SOUTH_EAST:
372  state->x -= state->width;
373  state->y -= state->height;
374  break;
375  case WL_NORTH_EAST:
376  state->x -= state->width;
377  break;
378  case WL_NORTH_WEST:
379  break;
380  case WL_NORTH:
381  state->x -= state->width / 2;
382  break;
383  case WL_EAST:
384  state->x -= state->width;
385  state->y -= state->height / 2;
386  break;
387  case WL_WEST:
388  state->y -= state->height / 2;
389  break;
390  case WL_CENTER:
391  state->y -= state->height / 2;
392  state->x -= state->width / 2;
393  break;
394  default:
395  break;
396  }
397  // Apply offset.
399  "x-offset", config.x_offset);
401  "y-offset", config.y_offset);
404 }
405 
407  if (state == NULL) {
408  return;
409  }
410  uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
411  XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
412  uint32_t vals[] = {state->x, state->y, state->width, state->height};
413 
414  // Display it.
415  xcb_configure_window(xcb->connection, CacheState.main_window, mask, vals);
416  cairo_destroy(CacheState.edit_draw);
417  cairo_surface_destroy(CacheState.edit_surf);
418 
419  xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
420  CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
421  xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
422  CacheState.main_window, state->width, state->height);
423 
424  CacheState.edit_surf =
425  cairo_xcb_surface_create(xcb->connection, CacheState.edit_pixmap, visual,
426  state->width, state->height);
427  CacheState.edit_draw = cairo_create(CacheState.edit_surf);
428 
429  g_debug("Re-size window based internal request: %dx%d.", state->width,
430  state->height);
431  // Should wrap main window in a widget.
432  widget_resize(WIDGET(state->main_window), state->width, state->height);
433 }
434 
436  if (state->mesg_box == NULL) {
437  return;
438  }
439  char *msg = mode_get_message(state->sw);
440  if (msg) {
441  textbox_text(state->mesg_tb, msg);
442  widget_enable(WIDGET(state->mesg_box));
443  g_free(msg);
444  } else {
445  widget_disable(WIDGET(state->mesg_box));
446  }
447 }
448 
449 static gboolean rofi_view_reload_idle(G_GNUC_UNUSED gpointer data) {
450  if (current_active_menu) {
451  current_active_menu->reload = TRUE;
454  }
455  CacheState.idle_timeout = 0;
456  return G_SOURCE_REMOVE;
457 }
458 
459 static void rofi_view_take_action(const char *name) {
460  ThemeWidget *wid = rofi_config_find_widget(name, NULL, TRUE);
461  if (wid) {
463  Property *p = rofi_theme_find_property(wid, P_STRING, "action", TRUE);
464  if (p != NULL && p->type == P_STRING) {
465  const char *action = p->value.s;
466  guint id = key_binding_get_action_from_name(action);
467  if (id != UINT32_MAX) {
469  } else {
470  g_warning("Failed to parse keybinding: %s\r\n", action);
471  }
472  }
473  }
474 }
475 static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data) {
476  CacheState.user_timeout = 0;
477  rofi_view_take_action("timeout");
478  return G_SOURCE_REMOVE;
479 }
480 
481 static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data) {
482  if (CacheState.user_timeout > 0) {
483  g_source_remove(CacheState.user_timeout);
484  CacheState.user_timeout = 0;
485  }
486  {
488  ThemeWidget *wid = rofi_config_find_widget("timeout", NULL, TRUE);
489  if (wid) {
491  Property *p = rofi_theme_find_property(wid, P_INTEGER, "delay", TRUE);
492  if (p != NULL && p->type == P_INTEGER && p->value.i > 0) {
493  int delay = p->value.i;
494  CacheState.user_timeout =
495  g_timeout_add(delay * 1000, rofi_view_user_timeout, NULL);
496  }
497  }
498  }
499 }
500 
501 void rofi_view_reload(void) {
502  // @TODO add check if current view is equal to the callee
503  if (CacheState.idle_timeout == 0) {
504  CacheState.idle_timeout =
505  g_timeout_add(1000 / 10, rofi_view_reload_idle, NULL);
506  }
507 }
509  if (current_active_menu && CacheState.repaint_source == 0) {
510  CacheState.count++;
511  g_debug("redraw %llu", CacheState.count);
512  CacheState.repaint_source =
513  g_idle_add_full(G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL);
514  }
515 }
516 
518  state->quit = FALSE;
519  state->retv = MENU_CANCEL;
520 }
521 
523 
525  if (state == current_active_menu) {
526  rofi_view_set_active(NULL);
527  } else if (state) {
528  g_queue_remove(&(CacheState.views), state);
529  }
530 }
532  if (current_active_menu != NULL && state != NULL) {
533  g_queue_push_head(&(CacheState.views), current_active_menu);
534  // TODO check.
535  current_active_menu = state;
536  g_debug("stack view.");
539  return;
540  }
541  if (state == NULL && !g_queue_is_empty(&(CacheState.views))) {
542  g_debug("pop view.");
543  current_active_menu = g_queue_pop_head(&(CacheState.views));
546  return;
547  }
548  g_assert((current_active_menu == NULL && state != NULL) ||
549  (current_active_menu != NULL && state == NULL));
550  current_active_menu = state;
552 }
553 
555  unsigned int selected_line) {
556  state->selected_line = selected_line;
557  // Find the line.
558  unsigned int selected = 0;
559  for (unsigned int i = 0; ((state->selected_line)) < UINT32_MAX && !selected &&
560  i < state->filtered_lines;
561  i++) {
562  if (state->line_map[i] == (state->selected_line)) {
563  selected = i;
564  break;
565  }
566  }
567  listview_set_selected(state->list_view, selected);
568  xcb_clear_area(xcb->connection, CacheState.main_window, 1, 0, 0, 1, 1);
569  xcb_flush(xcb->connection);
570 }
571 
573  if (state->tokens) {
575  state->tokens = NULL;
576  }
577  // Do this here?
578  // Wait for final release?
579  widget_free(WIDGET(state->main_window));
580 
581  g_free(state->line_map);
582  g_free(state->distance);
583  // Free the switcher boxes.
584  // When state is free'ed we should no longer need these.
585  g_free(state->modi);
586  state->num_modi = 0;
587  g_free(state);
588 }
589 
591  return state->retv;
592 }
593 
594 unsigned int rofi_view_get_selected_line(const RofiViewState *state) {
595  return state->selected_line;
596 }
597 
598 unsigned int rofi_view_get_next_position(const RofiViewState *state) {
599  unsigned int next_pos = state->selected_line;
600  unsigned int selected = listview_get_selected(state->list_view);
601  if ((selected + 1) < state->num_lines) {
602  (next_pos) = state->line_map[selected + 1];
603  }
604  return next_pos;
605 }
606 
607 unsigned int rofi_view_get_completed(const RofiViewState *state) {
608  return state->quit;
609 }
610 
611 const char *rofi_view_get_user_input(const RofiViewState *state) {
612  if (state->text) {
613  return state->text->text;
614  }
615  return NULL;
616 }
617 
624  return g_malloc0(sizeof(RofiViewState));
625 }
626 
630 typedef struct _thread_state_view {
633 
635  GCond *cond;
637  GMutex *mutex;
639  unsigned int *acount;
640 
644  unsigned int start;
646  unsigned int stop;
648  unsigned int count;
649 
651  const char *pattern;
653  glong plen;
661 static void rofi_view_call_thread(gpointer data, gpointer user_data) {
662  thread_state *t = (thread_state *)data;
663  t->callback(t, user_data);
664 }
665 
667  G_GNUC_UNUSED gpointer user_data) {
669  for (unsigned int i = t->start; i < t->stop; i++) {
670  int match = mode_token_match(t->state->sw, t->state->tokens, i);
671  // If each token was matched, add it to list.
672  if (match) {
673  t->state->line_map[t->start + t->count] = i;
674  if (config.sort) {
675  // This is inefficient, need to fix it.
676  char *str = mode_get_completion(t->state->sw, i);
677  glong slen = g_utf8_strlen(str, -1);
678  switch (config.sorting_method_enum) {
679  case SORT_FZF:
680  t->state->distance[i] =
681  rofi_scorer_fuzzy_evaluate(t->pattern, t->plen, str, slen);
682  break;
683  case SORT_NORMAL:
684  default:
685  t->state->distance[i] = levenshtein(t->pattern, t->plen, str, slen);
686  break;
687  }
688  g_free(str);
689  }
690  t->count++;
691  }
692  }
693  if (t->acount != NULL) {
694  g_mutex_lock(t->mutex);
695  (*(t->acount))--;
696  g_cond_signal(t->cond);
697  g_mutex_unlock(t->mutex);
698  }
699 }
700 
701 static void
703  const char *const fake_background) {
704  if (CacheState.fake_bg == NULL) {
705  cairo_surface_t *s = NULL;
710  TICK_N("Fake start");
711  if (g_strcmp0(fake_background, "real") == 0) {
712  return;
713  }
714  if (g_strcmp0(fake_background, "screenshot") == 0) {
716  } else if (g_strcmp0(fake_background, "background") == 0) {
718  } else {
719  char *fpath = rofi_expand_path(fake_background);
720  g_debug("Opening %s to use as background.", fpath);
721  s = cairo_image_surface_create_from_png(fpath);
722  CacheState.fake_bgrel = TRUE;
723  g_free(fpath);
724  }
725  TICK_N("Get surface.");
726  if (s != NULL) {
727  if (cairo_surface_status(s) != CAIRO_STATUS_SUCCESS) {
728  g_debug("Failed to open surface fake background: %s",
729  cairo_status_to_string(cairo_surface_status(s)));
730  cairo_surface_destroy(s);
731  s = NULL;
732  } else {
733  CacheState.fake_bg = cairo_image_surface_create(
734  CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h);
735 
736  int blur = rofi_theme_get_integer(WIDGET(win), "blur", 0);
737  cairo_t *dr = cairo_create(CacheState.fake_bg);
738  if (CacheState.fake_bgrel) {
739  cairo_set_source_surface(dr, s, 0, 0);
740  } else {
741  cairo_set_source_surface(dr, s, -CacheState.mon.x, -CacheState.mon.y);
742  }
743  cairo_paint(dr);
744  cairo_destroy(dr);
745  cairo_surface_destroy(s);
746  if (blur > 0) {
747  cairo_image_surface_blur(CacheState.fake_bg, (double)blur, 0);
748  TICK_N("BLUR");
749  }
750  }
751  }
752  TICK_N("Fake transparency");
753  }
754 }
755 void __create_window(MenuFlags menu_flags) {
756  uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
757  XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
758  XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
759  uint32_t xcb_event_masks =
760  XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
761  XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_KEY_PRESS |
762  XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
763  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE |
764  XCB_EVENT_MASK_BUTTON_1_MOTION | XCB_EVENT_MASK_POINTER_MOTION;
765 
766  uint32_t selval[] = {XCB_BACK_PIXMAP_NONE, 0,
767  XCB_GRAVITY_STATIC, XCB_BACKING_STORE_NOT_USEFUL,
768  xcb_event_masks, map};
769 
770  xcb_window_t box_window = xcb_generate_id(xcb->connection);
771  xcb_void_cookie_t cc = xcb_create_window_checked(
772  xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window(), 0,
773  0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visual_id, selmask,
774  selval);
775  xcb_generic_error_t *error;
776  error = xcb_request_check(xcb->connection, cc);
777  if (error) {
778  g_error("xcb_create_window() failed error=0x%x\n", error->error_code);
779  exit(EXIT_FAILURE);
780  }
781  TICK_N("xcb create window");
782  CacheState.gc = xcb_generate_id(xcb->connection);
783  xcb_create_gc(xcb->connection, CacheState.gc, box_window, 0, 0);
784 
785  TICK_N("xcb create gc");
786  // Create a drawable.
787  CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
788  xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
789  CacheState.main_window, 200, 100);
790 
791  CacheState.edit_surf = cairo_xcb_surface_create(
792  xcb->connection, CacheState.edit_pixmap, visual, 200, 100);
793  CacheState.edit_draw = cairo_create(CacheState.edit_surf);
794 
795  TICK_N("create cairo surface");
796  // Set up pango context.
797  cairo_font_options_t *fo = cairo_font_options_create();
798  // Take font description from xlib surface
799  cairo_surface_get_font_options(CacheState.edit_surf, fo);
800  // TODO should we update the drawable each time?
801  PangoContext *p = pango_cairo_create_context(CacheState.edit_draw);
802  // Set the font options from the xlib surface
803  pango_cairo_context_set_font_options(p, fo);
804  TICK_N("pango cairo font setup");
805 
806  CacheState.main_window = box_window;
807  CacheState.flags = menu_flags;
808  monitor_active(&(CacheState.mon));
809  // Setup dpi
810  if (config.dpi > 1) {
811  PangoFontMap *font_map = pango_cairo_font_map_get_default();
812  pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map,
813  (double)config.dpi);
814  } else if (config.dpi == 0 || config.dpi == 1) {
815  // Auto-detect mode.
816  double dpi = 96;
817  if (CacheState.mon.mh > 0 && config.dpi == 1) {
818  dpi = (CacheState.mon.h * 25.4) / (double)(CacheState.mon.mh);
819  } else {
820  dpi = (xcb->screen->height_in_pixels * 25.4) /
821  (double)(xcb->screen->height_in_millimeters);
822  }
823 
824  g_debug("Auto-detected DPI: %.2lf", dpi);
825  PangoFontMap *font_map = pango_cairo_font_map_get_default();
826  pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map, dpi);
827  config.dpi = dpi;
828  } else {
829  // default pango is 96.
830  PangoFontMap *font_map = pango_cairo_font_map_get_default();
831  config.dpi =
832  pango_cairo_font_map_get_resolution((PangoCairoFontMap *)font_map);
833  }
834  // Setup font.
835  // Dummy widget.
836  box *win = box_create(NULL, "window", ROFI_ORIENTATION_HORIZONTAL);
837  const char *font =
839  if (font) {
840  PangoFontDescription *pfd = pango_font_description_from_string(font);
841  if (helper_validate_font(pfd, font)) {
842  pango_context_set_font_description(p, pfd);
843  }
844  pango_font_description_free(pfd);
845  }
846  PangoLanguage *l = pango_language_get_default();
847  pango_context_set_language(p, l);
848  TICK_N("configure font");
849 
850  // Tell textbox to use this context.
851  textbox_set_pango_context(font, p);
852  // cleanup
853  g_object_unref(p);
854  cairo_font_options_destroy(fo);
855 
856  TICK_N("textbox setup");
857  // // make it an unmanaged window
858  if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
859  window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE,
860  &(xcb->ewmh._NET_WM_STATE_ABOVE), 1);
861  uint32_t values[] = {1};
862  xcb_change_window_attributes(xcb->connection, box_window,
863  XCB_CW_OVERRIDE_REDIRECT, values);
864  } else {
865  window_set_atom_prop(box_window, xcb->ewmh._NET_WM_WINDOW_TYPE,
866  &(xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL), 1);
867  x11_disable_decoration(box_window);
868  }
869 
870  TICK_N("setup window attributes");
871  CacheState.fullscreen =
872  rofi_theme_get_boolean(WIDGET(win), "fullscreen", FALSE);
873  if (CacheState.fullscreen) {
874  xcb_atom_t atoms[] = {xcb->ewmh._NET_WM_STATE_FULLSCREEN,
875  xcb->ewmh._NET_WM_STATE_ABOVE};
876  window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE, atoms,
877  sizeof(atoms) / sizeof(xcb_atom_t));
878  }
879 
880  xcb_atom_t protocols[] = {netatoms[WM_TAKE_FOCUS]};
881  xcb_icccm_set_wm_protocols(xcb->connection, box_window,
882  xcb->ewmh.WM_PROTOCOLS, G_N_ELEMENTS(protocols),
883  protocols);
884 
885  TICK_N("setup window fullscreen");
886  // Set the WM_NAME
888  const char wm_class_name[] = "rofi\0Rofi";
889  xcb_icccm_set_wm_class(xcb->connection, box_window, sizeof(wm_class_name),
890  wm_class_name);
891 
892  TICK_N("setup window name and class");
893  const char *transparency =
894  rofi_theme_get_string(WIDGET(win), "transparency", NULL);
895  if (transparency) {
896  rofi_view_setup_fake_transparency(WIDGET(win), transparency);
897  }
898  if (xcb->sncontext != NULL) {
899  sn_launchee_context_setup_window(xcb->sncontext, CacheState.main_window);
900  }
901  TICK_N("setup startup notification");
902  widget_free(WIDGET(win));
903  TICK_N("done");
904 
905  // Set the PID.
906  pid_t pid = getpid();
907  xcb_ewmh_set_wm_pid(&(xcb->ewmh), CacheState.main_window, pid);
908 
909  // Get hostname
910  const char *hostname = g_get_host_name();
911  char *ahost = g_hostname_to_ascii(hostname);
912  if (ahost != NULL) {
913  xcb_icccm_set_wm_client_machine(xcb->connection, CacheState.main_window,
914  XCB_ATOM_STRING, 8, strlen(ahost), ahost);
915  g_free(ahost);
916  }
917 }
918 
925  if (CacheState.fullscreen) {
926  state->width = CacheState.mon.w;
927  return;
928  }
929  // Calculate as float to stop silly, big rounding down errors.
930  state->width = (CacheState.mon.w / 100.0f) * DEFAULT_MENU_WIDTH;
931  // Use theme configured width, if set.
933  "width", state->width);
935 }
936 
947  if (state->filtered_lines == 1) {
948  state->retv = MENU_OK;
949  (state->selected_line) =
950  state->line_map[listview_get_selected(state->list_view)];
951  state->quit = 1;
952  return;
953  }
954 
955  // Double tab!
956  if (state->filtered_lines == 0 && ROW_TAB == state->prev_action) {
957  state->retv = MENU_NEXT;
958  (state->selected_line) = 0;
959  state->quit = TRUE;
960  } else {
962  }
963  state->prev_action = ROW_TAB;
964 }
970 inline static void rofi_view_nav_row_select(RofiViewState *state) {
971  if (state->list_view == NULL) {
972  return;
973  }
974  unsigned int selected = listview_get_selected(state->list_view);
975  // If a valid item is selected, return that..
976  if (selected < state->filtered_lines) {
977  char *str = mode_get_completion(state->sw, state->line_map[selected]);
978  textbox_text(state->text, str);
979  g_free(str);
981  state->refilter = TRUE;
982  }
983 }
984 
990 inline static void rofi_view_nav_first(RofiViewState *state) {
991  // state->selected = 0;
992  listview_set_selected(state->list_view, 0);
993 }
994 
1000 inline static void rofi_view_nav_last(RofiViewState *state) {
1001  // If no lines, do nothing.
1002  if (state->filtered_lines == 0) {
1003  return;
1004  }
1005  // state->selected = state->filtered_lines - 1;
1006  listview_set_selected(state->list_view, -1);
1007 }
1008 
1009 static void update_callback(textbox *t, icon *ico, unsigned int index,
1010  void *udata, TextBoxFontType *type, gboolean full) {
1011  RofiViewState *state = (RofiViewState *)udata;
1012  if (full) {
1013  GList *add_list = NULL;
1014  int fstate = 0;
1015  char *text = mode_get_display_value(state->sw, state->line_map[index],
1016  &fstate, &add_list, TRUE);
1017  (*type) |= fstate;
1018  // TODO needed for markup.
1019  textbox_font(t, *type);
1020  // Move into list view.
1021  textbox_text(t, text);
1022  PangoAttrList *list = textbox_get_pango_attributes(t);
1023  if (list != NULL) {
1024  pango_attr_list_ref(list);
1025  } else {
1026  list = pango_attr_list_new();
1027  }
1028  if (ico) {
1029  int icon_height = widget_get_desired_height(WIDGET(ico), WIDGET(ico)->w);
1030  cairo_surface_t *icon =
1031  mode_get_icon(state->sw, state->line_map[index], icon_height);
1032  icon_set_surface(ico, icon);
1033  }
1034 
1035  if (state->tokens) {
1037  {0.0, 0.0, 0.0, 0.0}};
1038  th = rofi_theme_get_highlight(WIDGET(t), "highlight", th);
1040  textbox_get_visible_text(t), list);
1041  }
1042  for (GList *iter = g_list_first(add_list); iter != NULL;
1043  iter = g_list_next(iter)) {
1044  pango_attr_list_insert(list, (PangoAttribute *)(iter->data));
1045  }
1047  pango_attr_list_unref(list);
1048  g_list_free(add_list);
1049  g_free(text);
1050  } else {
1051  int fstate = 0;
1052  mode_get_display_value(state->sw, state->line_map[index], &fstate, NULL,
1053  FALSE);
1054  (*type) |= fstate;
1055  // TODO needed for markup.
1056  textbox_font(t, *type);
1057  }
1058 }
1059 
1060 void rofi_view_update(RofiViewState *state, gboolean qr) {
1061  if (!widget_need_redraw(WIDGET(state->main_window))) {
1062  return;
1063  }
1064  g_debug("Redraw view");
1065  TICK();
1066  cairo_t *d = CacheState.edit_draw;
1067  cairo_set_operator(d, CAIRO_OPERATOR_SOURCE);
1068  if (CacheState.fake_bg != NULL) {
1069  if (CacheState.fake_bgrel) {
1070  cairo_set_source_surface(d, CacheState.fake_bg, 0.0, 0.0);
1071  } else {
1072  cairo_set_source_surface(d, CacheState.fake_bg,
1073  -(double)(state->x - CacheState.mon.x),
1074  -(double)(state->y - CacheState.mon.y));
1075  }
1076  cairo_paint(d);
1077  cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1078  } else {
1079  // Paint the background transparent.
1080  cairo_set_source_rgba(d, 0, 0, 0, 0.0);
1081  cairo_paint(d);
1082  }
1083  TICK_N("Background");
1084 
1085  // Always paint as overlay over the background.
1086  cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1087  widget_draw(WIDGET(state->main_window), d);
1088 
1089  TICK_N("widgets");
1090  cairo_surface_flush(CacheState.edit_surf);
1091  if (qr) {
1093  }
1094 }
1095 
1097  g_free(state->line_map);
1098  g_free(state->distance);
1099  state->num_lines = mode_get_num_entries(state->sw);
1100  state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
1101  state->distance = g_malloc0_n(state->num_lines, sizeof(int));
1102  listview_set_max_lines(state->list_view, state->num_lines);
1104 }
1105 
1106 static void rofi_view_refilter(RofiViewState *state) {
1107  if (state->sw == NULL) {
1108  return;
1109  }
1110  TICK_N("Filter start");
1111  if (state->reload) {
1112  _rofi_view_reload_row(state);
1113  state->reload = FALSE;
1114  }
1115  TICK_N("Filter reload rows");
1116  if (state->tokens) {
1117  helper_tokenize_free(state->tokens);
1118  state->tokens = NULL;
1119  }
1120  TICK_N("Filter tokenize");
1121  if (state->text && strlen(state->text->text) > 0) {
1122  unsigned int j = 0;
1123  gchar *pattern = mode_preprocess_input(state->sw, state->text->text);
1124  glong plen = pattern ? g_utf8_strlen(pattern, -1) : 0;
1125  state->tokens = helper_tokenize(pattern, config.case_sensitive);
1133  unsigned int nt = MAX(1, state->num_lines / 500);
1134  thread_state_view states[nt];
1135  GCond cond;
1136  GMutex mutex;
1137  g_mutex_init(&mutex);
1138  g_cond_init(&cond);
1139  unsigned int count = nt;
1140  unsigned int steps = (state->num_lines + nt) / nt;
1141  for (unsigned int i = 0; i < nt; i++) {
1142  states[i].state = state;
1143  states[i].start = i * steps;
1144  states[i].stop = MIN(state->num_lines, (i + 1) * steps);
1145  states[i].count = 0;
1146  states[i].cond = &cond;
1147  states[i].mutex = &mutex;
1148  states[i].acount = &count;
1149  states[i].plen = plen;
1150  states[i].pattern = pattern;
1151  states[i].st.callback = filter_elements;
1152  if (i > 0) {
1153  g_thread_pool_push(tpool, &states[i], NULL);
1154  }
1155  }
1156  // Run one in this thread.
1157  rofi_view_call_thread(&states[0], NULL);
1158  // No need to do this with only one thread.
1159  if (nt > 1) {
1160  g_mutex_lock(&mutex);
1161  while (count > 0) {
1162  g_cond_wait(&cond, &mutex);
1163  }
1164  g_mutex_unlock(&mutex);
1165  }
1166  g_cond_clear(&cond);
1167  g_mutex_clear(&mutex);
1168  for (unsigned int i = 0; i < nt; i++) {
1169  if (j != states[i].start) {
1170  memmove(&(state->line_map[j]), &(state->line_map[states[i].start]),
1171  sizeof(unsigned int) * (states[i].count));
1172  }
1173  j += states[i].count;
1174  }
1175  if (config.sort) {
1176  g_qsort_with_data(state->line_map, j, sizeof(int), lev_sort,
1177  state->distance);
1178  }
1179 
1180  // Cleanup + bookkeeping.
1181  state->filtered_lines = j;
1182  g_free(pattern);
1183  } else {
1184  for (unsigned int i = 0; i < state->num_lines; i++) {
1185  state->line_map[i] = i;
1186  }
1187  state->filtered_lines = state->num_lines;
1188  }
1189  TICK_N("Filter matching done");
1191 
1192  if (state->tb_filtered_rows) {
1193  char *r = g_strdup_printf("%u", state->filtered_lines);
1194  textbox_text(state->tb_filtered_rows, r);
1195  g_free(r);
1196  }
1197  if (state->tb_total_rows) {
1198  char *r = g_strdup_printf("%u", state->num_lines);
1199  textbox_text(state->tb_total_rows, r);
1200  g_free(r);
1201  }
1202  TICK_N("Update filter lines");
1203 
1204  if (config.auto_select == TRUE && state->filtered_lines == 1 &&
1205  state->num_lines > 1) {
1206  (state->selected_line) =
1207  state->line_map[listview_get_selected(state->list_view)];
1208  state->retv = MENU_OK;
1209  state->quit = TRUE;
1210  }
1211 
1212  // Size the window.
1213  int height = rofi_view_calculate_height(state);
1214  if (height != state->height) {
1215  state->height = height;
1218  g_debug("Resize based on re-filter");
1219  }
1220  TICK_N("Filter resize window based on window ");
1221  state->refilter = FALSE;
1222  TICK_N("Filter done");
1223 }
1229 void process_result(RofiViewState *state);
1231  if (state && state->finalize != NULL) {
1232  state->finalize(state);
1233  }
1234 }
1235 
1240 static void rofi_view_input_changed() { rofi_view_take_action("inputchange"); }
1241 
1244  switch (action) {
1245  // Handling of paste
1246  case PASTE_PRIMARY:
1247  xcb_convert_selection(xcb->connection, CacheState.main_window,
1248  XCB_ATOM_PRIMARY, xcb->ewmh.UTF8_STRING,
1249  xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1250  xcb_flush(xcb->connection);
1251  break;
1252  case PASTE_SECONDARY:
1253  xcb_convert_selection(xcb->connection, CacheState.main_window,
1254  netatoms[CLIPBOARD], xcb->ewmh.UTF8_STRING,
1255  xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1256  xcb_flush(xcb->connection);
1257  break;
1258  case SCREENSHOT:
1260  break;
1261  case CHANGE_ELLIPSIZE:
1262  if (state->list_view) {
1264  }
1265  break;
1266  case TOGGLE_SORT:
1267  if (state->case_indicator != NULL) {
1268  config.sort = !config.sort;
1269  state->refilter = TRUE;
1271  }
1272  break;
1273  case MODE_PREVIOUS:
1274  state->retv = MENU_PREVIOUS;
1275  (state->selected_line) = 0;
1276  state->quit = TRUE;
1277  break;
1278  // Menu navigation.
1279  case MODE_NEXT:
1280  state->retv = MENU_NEXT;
1281  (state->selected_line) = 0;
1282  state->quit = TRUE;
1283  break;
1284  case MODE_COMPLETE: {
1285  unsigned int selected = listview_get_selected(state->list_view);
1286  state->selected_line = UINT32_MAX;
1287  if (selected < state->filtered_lines) {
1288  state->selected_line = state->line_map[selected];
1289  }
1290  state->retv = MENU_COMPLETE;
1291  state->quit = TRUE;
1292  break;
1293  }
1294  // Toggle case sensitivity.
1296  if (state->case_indicator != NULL) {
1298  (state->selected_line) = 0;
1299  state->refilter = TRUE;
1301  }
1302  break;
1303  // Special delete entry command.
1304  case DELETE_ENTRY: {
1305  unsigned int selected = listview_get_selected(state->list_view);
1306  if (selected < state->filtered_lines) {
1307  (state->selected_line) = state->line_map[selected];
1308  state->retv = MENU_ENTRY_DELETE;
1309  state->quit = TRUE;
1310  }
1311  break;
1312  }
1313  case SELECT_ELEMENT_1:
1314  case SELECT_ELEMENT_2:
1315  case SELECT_ELEMENT_3:
1316  case SELECT_ELEMENT_4:
1317  case SELECT_ELEMENT_5:
1318  case SELECT_ELEMENT_6:
1319  case SELECT_ELEMENT_7:
1320  case SELECT_ELEMENT_8:
1321  case SELECT_ELEMENT_9:
1322  case SELECT_ELEMENT_10: {
1323  unsigned int index = action - SELECT_ELEMENT_1;
1324  if (index < state->filtered_lines) {
1325  state->selected_line = state->line_map[index];
1326  state->retv = MENU_OK;
1327  state->quit = TRUE;
1328  }
1329  break;
1330  }
1331  case CUSTOM_1:
1332  case CUSTOM_2:
1333  case CUSTOM_3:
1334  case CUSTOM_4:
1335  case CUSTOM_5:
1336  case CUSTOM_6:
1337  case CUSTOM_7:
1338  case CUSTOM_8:
1339  case CUSTOM_9:
1340  case CUSTOM_10:
1341  case CUSTOM_11:
1342  case CUSTOM_12:
1343  case CUSTOM_13:
1344  case CUSTOM_14:
1345  case CUSTOM_15:
1346  case CUSTOM_16:
1347  case CUSTOM_17:
1348  case CUSTOM_18:
1349  case CUSTOM_19: {
1350  state->selected_line = UINT32_MAX;
1351  unsigned int selected = listview_get_selected(state->list_view);
1352  if (selected < state->filtered_lines) {
1353  (state->selected_line) = state->line_map[selected];
1354  }
1355  state->retv = MENU_CUSTOM_COMMAND | ((action - CUSTOM_1) & MENU_LOWER_MASK);
1356  state->quit = TRUE;
1357  break;
1358  }
1359  // If you add a binding here, make sure to add it to
1360  // rofi_view_keyboard_navigation too
1361  case CANCEL:
1362  state->retv = MENU_CANCEL;
1363  state->quit = TRUE;
1364  break;
1365  case ROW_UP:
1366  listview_nav_up(state->list_view);
1367  break;
1368  case ROW_TAB:
1369  rofi_view_nav_row_tab(state);
1370  break;
1371  case ROW_DOWN:
1372  listview_nav_down(state->list_view);
1373  break;
1374  case ROW_LEFT:
1375  listview_nav_left(state->list_view);
1376  break;
1377  case ROW_RIGHT:
1378  listview_nav_right(state->list_view);
1379  break;
1380  case PAGE_PREV:
1382  break;
1383  case PAGE_NEXT:
1385  break;
1386  case ROW_FIRST:
1387  rofi_view_nav_first(state);
1388  break;
1389  case ROW_LAST:
1390  rofi_view_nav_last(state);
1391  break;
1392  case ROW_SELECT:
1393  rofi_view_nav_row_select(state);
1394  break;
1395  // If you add a binding here, make sure to add it to textbox_keybinding too
1396  case MOVE_CHAR_BACK: {
1397  if (textbox_keybinding(state->text, action) == 0) {
1398  listview_nav_left(state->list_view);
1399  }
1400  break;
1401  }
1402  case MOVE_CHAR_FORWARD: {
1403  if (textbox_keybinding(state->text, action) == 0) {
1404  listview_nav_right(state->list_view);
1405  }
1406  break;
1407  }
1408  case CLEAR_LINE:
1409  case MOVE_FRONT:
1410  case MOVE_END:
1411  case REMOVE_TO_EOL:
1412  case REMOVE_TO_SOL:
1413  case REMOVE_WORD_BACK:
1414  case REMOVE_WORD_FORWARD:
1415  case REMOVE_CHAR_FORWARD:
1416  case MOVE_WORD_BACK:
1417  case MOVE_WORD_FORWARD:
1418  case REMOVE_CHAR_BACK: {
1419  int rc = textbox_keybinding(state->text, action);
1420  if (rc == 1) {
1421  // Entry changed.
1422  state->refilter = TRUE;
1424  } else if (rc == 2) {
1425  // Movement.
1426  }
1427  break;
1428  }
1429  case ACCEPT_ALT: {
1430  unsigned int selected = listview_get_selected(state->list_view);
1431  state->selected_line = UINT32_MAX;
1432  if (selected < state->filtered_lines) {
1433  (state->selected_line) = state->line_map[selected];
1434  state->retv = MENU_OK;
1435  } else {
1436  // Nothing entered and nothing selected.
1437  state->retv = MENU_CUSTOM_INPUT;
1438  }
1439  state->retv |= MENU_CUSTOM_ACTION;
1440  state->quit = TRUE;
1441  break;
1442  }
1443  case ACCEPT_CUSTOM: {
1444  state->selected_line = UINT32_MAX;
1445  state->retv = MENU_CUSTOM_INPUT;
1446  state->quit = TRUE;
1447  break;
1448  }
1449  case ACCEPT_CUSTOM_ALT: {
1450  state->selected_line = UINT32_MAX;
1452  state->quit = TRUE;
1453  break;
1454  }
1455  case ACCEPT_ENTRY: {
1456  // If a valid item is selected, return that..
1457  unsigned int selected = listview_get_selected(state->list_view);
1458  state->selected_line = UINT32_MAX;
1459  if (selected < state->filtered_lines) {
1460  (state->selected_line) = state->line_map[selected];
1461  state->retv = MENU_OK;
1462  } else {
1463  // Nothing entered and nothing selected.
1464  state->retv = MENU_CUSTOM_INPUT;
1465  }
1466 
1467  state->quit = TRUE;
1468  break;
1469  }
1470  }
1471 }
1472 
1474  guint action) {
1475  switch (scope) {
1476  case SCOPE_GLOBAL:
1477  return TRUE;
1478  case SCOPE_MOUSE_LISTVIEW:
1480  case SCOPE_MOUSE_EDITBOX:
1481  case SCOPE_MOUSE_SCROLLBAR:
1483  gint x = state->mouse.x, y = state->mouse.y;
1485  (WidgetType)scope, x, y);
1486  if (target == NULL) {
1487  return FALSE;
1488  }
1489  widget_xy_to_relative(target, &x, &y);
1490  switch (widget_check_action(target, action, x, y)) {
1492  return FALSE;
1496  return TRUE;
1497  }
1498  break;
1499  }
1500  }
1501  return FALSE;
1502 }
1503 
1505  guint action) {
1507  switch (scope) {
1508  case SCOPE_GLOBAL:
1510  return;
1511  case SCOPE_MOUSE_LISTVIEW:
1513  case SCOPE_MOUSE_EDITBOX:
1514  case SCOPE_MOUSE_SCROLLBAR:
1516  gint x = state->mouse.x, y = state->mouse.y;
1518  (WidgetType)scope, x, y);
1519  if (target == NULL) {
1520  return;
1521  }
1522  widget_xy_to_relative(target, &x, &y);
1523  switch (widget_trigger_action(target, action, x, y)) {
1525  return;
1527  target = NULL;
1528  /* FALLTHRU */
1530  state->mouse.motion_target = target;
1531  /* FALLTHRU */
1533  return;
1534  }
1535  break;
1536  }
1537  }
1538 }
1539 
1540 void rofi_view_handle_text(RofiViewState *state, char *text) {
1541  if (textbox_append_text(state->text, text, strlen(text))) {
1542  state->refilter = TRUE;
1544  }
1545 }
1546 
1548  switch (type) {
1549  case ROFI_CURSOR_DEFAULT:
1550  return CURSOR_DEFAULT;
1551 
1552  case ROFI_CURSOR_POINTER:
1553  return CURSOR_POINTER;
1554 
1555  case ROFI_CURSOR_TEXT:
1556  return CURSOR_TEXT;
1557  }
1558 
1559  return CURSOR_DEFAULT;
1560 }
1561 
1563  gint y) {
1565  WIDGET_TYPE_UNKNOWN, x, y);
1566 
1567  return target != NULL ? target->cursor_type : ROFI_CURSOR_DEFAULT;
1568 }
1569 
1572 
1573  if (x11_type == CacheState.cursor_type) {
1574  return;
1575  }
1576 
1577  CacheState.cursor_type = x11_type;
1578 
1579  x11_set_cursor(CacheState.main_window, x11_type);
1580 }
1581 
1582 void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y,
1583  gboolean find_mouse_target) {
1584  state->mouse.x = x;
1585  state->mouse.y = y;
1586 
1588 
1590 
1591  if (find_mouse_target) {
1592  widget *target = widget_find_mouse_target(
1594 
1595  if (target != NULL) {
1596  state->mouse.motion_target = target;
1597  }
1598  }
1599 
1600  if (state->mouse.motion_target != NULL) {
1601  widget_xy_to_relative(state->mouse.motion_target, &x, &y);
1603 
1604  if (find_mouse_target) {
1605  state->mouse.motion_target = NULL;
1606  }
1607  }
1608 }
1609 
1611  if (rofi_view_get_completed(state)) {
1612  // This menu is done.
1613  rofi_view_finalize(state);
1614  // If there a state. (for example error) reload it.
1615  state = rofi_view_get_active();
1616 
1617  // cleanup, if no more state to display.
1618  if (state == NULL) {
1619  // Quit main-loop.
1621  return;
1622  }
1623  }
1624 
1625  // Update if requested.
1626  if (state->refilter) {
1627  rofi_view_refilter(state);
1628  }
1629  rofi_view_update(state, TRUE);
1630 }
1631 
1637  xcb_configure_notify_event_t *xce) {
1638  if (xce->window == CacheState.main_window) {
1639  if (state->x != xce->x || state->y != xce->y) {
1640  state->x = xce->x;
1641  state->y = xce->y;
1643  }
1644  if (state->width != xce->width || state->height != xce->height) {
1645  state->width = xce->width;
1646  state->height = xce->height;
1647 
1648  cairo_destroy(CacheState.edit_draw);
1649  cairo_surface_destroy(CacheState.edit_surf);
1650 
1651  xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
1652  CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
1653  xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
1654  CacheState.main_window, state->width, state->height);
1655 
1656  CacheState.edit_surf =
1657  cairo_xcb_surface_create(xcb->connection, CacheState.edit_pixmap,
1658  visual, state->width, state->height);
1659  CacheState.edit_draw = cairo_create(CacheState.edit_surf);
1660  g_debug("Re-size window based external request: %d %d", state->width,
1661  state->height);
1662  widget_resize(WIDGET(state->main_window), state->width, state->height);
1663  }
1664  }
1665 }
1666 
1670 void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target) {
1671  if ((CacheState.flags & MENU_NORMAL_WINDOW) == 0) {
1672  if (target != CacheState.main_window) {
1673  state->quit = TRUE;
1674  state->retv = MENU_CANCEL;
1675  }
1676  }
1677 }
1678 
1680  if (CacheState.repaint_source == 0) {
1681  CacheState.repaint_source =
1682  g_idle_add_full(G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL);
1683  }
1684 }
1685 
1687  if (CacheState.fullscreen == TRUE) {
1688  return CacheState.mon.h;
1689  }
1690 
1691  RofiDistance h =
1692  rofi_theme_get_distance(WIDGET(state->main_window), "height", 0);
1693  unsigned int height = distance_get_pixel(h, ROFI_ORIENTATION_VERTICAL);
1694  // If height is set, return it.
1695  if (height > 0) {
1696  return height;
1697  }
1698  // Autosize based on widgets.
1699  widget *main_window = WIDGET(state->main_window);
1701 }
1702 
1704  widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1705  G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1706  RofiViewState *state = (RofiViewState *)user_data;
1707  switch (action) {
1708  case MOUSE_CLICK_DOWN: {
1709  const char *type = rofi_theme_get_string(wid, "action", NULL);
1710  if (type) {
1711  if (state->list_view) {
1712  (state->selected_line) =
1713  state->line_map[listview_get_selected(state->list_view)];
1714  } else {
1715  (state->selected_line) = UINT32_MAX;
1716  }
1717  guint id = key_binding_get_action_from_name(type);
1718  if (id != UINT32_MAX) {
1720  }
1721  state->skip_absorb = TRUE;
1723  }
1724  }
1725  case MOUSE_CLICK_UP:
1726  case MOUSE_DCLICK_DOWN:
1727  case MOUSE_DCLICK_UP:
1728  break;
1729  }
1731 }
1733  widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1734  G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1735  RofiViewState *state = (RofiViewState *)user_data;
1736  unsigned int i;
1737  for (i = 0; i < state->num_modi; i++) {
1738  if (WIDGET(state->modi[i]) == wid) {
1739  break;
1740  }
1741  }
1742  if (i == state->num_modi) {
1744  }
1745 
1746  switch (action) {
1747  case MOUSE_CLICK_DOWN:
1748  state->retv = MENU_QUICK_SWITCH | (i & MENU_LOWER_MASK);
1749  state->quit = TRUE;
1750  state->skip_absorb = TRUE;
1752  case MOUSE_CLICK_UP:
1753  case MOUSE_DCLICK_DOWN:
1754  case MOUSE_DCLICK_UP:
1755  break;
1756  }
1758 }
1759 
1760 // @TODO don't like this construction.
1761 static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom,
1762  void *udata) {
1763  RofiViewState *state = (RofiViewState *)udata;
1764  state->retv = MENU_OK;
1765  if (custom) {
1766  state->retv |= MENU_CUSTOM_ACTION;
1767  }
1768  (state->selected_line) = state->line_map[listview_get_selected(lv)];
1769  // Quit
1770  state->quit = TRUE;
1771  state->skip_absorb = TRUE;
1772 }
1773 
1774 static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget,
1775  const char *name) {
1776  char *defaults = NULL;
1777  widget *wid = NULL;
1778 
1782  if (strcmp(name, "mainbox") == 0) {
1783  wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1784  box_add((box *)parent_widget, WIDGET(wid), TRUE);
1785  if (config.sidebar_mode) {
1786  defaults = "inputbar,message,listview,mode-switcher";
1787  } else {
1788  defaults = "inputbar,message,listview";
1789  }
1790  }
1794  else if (strcmp(name, "inputbar") == 0) {
1795  wid =
1796  (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1797  defaults = "prompt,entry,overlay,case-indicator";
1798  box_add((box *)parent_widget, WIDGET(wid), FALSE);
1799  }
1803  else if (strcmp(name, "prompt") == 0) {
1804  if (state->prompt != NULL) {
1805  g_error("Prompt widget can only be added once to the layout.");
1806  return;
1807  }
1808  // Prompt box.
1809  state->prompt =
1810  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1811  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1812  rofi_view_update_prompt(state);
1813  box_add((box *)parent_widget, WIDGET(state->prompt), FALSE);
1814  defaults = NULL;
1815  } else if (strcmp(name, "num-rows") == 0) {
1816  state->tb_total_rows =
1817  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1818  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1819  box_add((box *)parent_widget, WIDGET(state->tb_total_rows), FALSE);
1820  defaults = NULL;
1821  } else if (strcmp(name, "num-filtered-rows") == 0) {
1822  state->tb_filtered_rows =
1823  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1824  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1825  box_add((box *)parent_widget, WIDGET(state->tb_filtered_rows), FALSE);
1826  defaults = NULL;
1827  }
1831  else if (strcmp(name, "case-indicator") == 0) {
1832  if (state->case_indicator != NULL) {
1833  g_error("Case indicator widget can only be added once to the layout.");
1834  return;
1835  }
1836  state->case_indicator =
1837  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1838  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*", 0, 0);
1839  // Add small separator between case indicator and text box.
1840  box_add((box *)parent_widget, WIDGET(state->case_indicator), FALSE);
1842  }
1846  else if (strcmp(name, "entry") == 0) {
1847  if (state->text != NULL) {
1848  g_error("Entry textbox widget can only be added once to the layout.");
1849  return;
1850  }
1851  // Entry box
1852  TextboxFlags tfl = TB_EDITABLE;
1853  tfl |= ((state->menu_flags & MENU_PASSWORD) == MENU_PASSWORD) ? TB_PASSWORD
1854  : 0;
1855  state->text = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1856  tfl | TB_AUTOHEIGHT, NORMAL, NULL, 0, 0);
1857  box_add((box *)parent_widget, WIDGET(state->text), TRUE);
1858  }
1862  else if (strcmp(name, "message") == 0) {
1863  if (state->mesg_box != NULL) {
1864  g_error("Message widget can only be added once to the layout.");
1865  return;
1866  }
1867  state->mesg_box = container_create(parent_widget, name);
1868  state->mesg_tb = textbox_create(
1869  WIDGET(state->mesg_box), WIDGET_TYPE_TEXTBOX_TEXT, "textbox",
1870  TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL, 0, 0);
1871  container_add(state->mesg_box, WIDGET(state->mesg_tb));
1873  box_add((box *)parent_widget, WIDGET(state->mesg_box), FALSE);
1874  }
1878  else if (strcmp(name, "listview") == 0) {
1879  if (state->list_view != NULL) {
1880  g_error("Listview widget can only be added once to the layout.");
1881  return;
1882  }
1883  state->list_view = listview_create(parent_widget, name, update_callback,
1884  state, config.element_height, 0);
1885  box_add((box *)parent_widget, WIDGET(state->list_view), TRUE);
1886  // Set configuration
1888  (state->menu_flags & MENU_INDICATOR) ==
1889  MENU_INDICATOR);
1893 
1894  int lines = rofi_theme_get_integer(WIDGET(state->list_view), "lines",
1896  listview_set_num_lines(state->list_view, lines);
1897  listview_set_max_lines(state->list_view, state->num_lines);
1898  }
1902  else if (strcmp(name, "mode-switcher") == 0 || strcmp(name, "sidebar") == 0) {
1903  if (state->sidebar_bar != NULL) {
1904  g_error("Mode-switcher can only be added once to the layout.");
1905  return;
1906  }
1907  state->sidebar_bar =
1908  box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1909  box_add((box *)parent_widget, WIDGET(state->sidebar_bar), FALSE);
1911  state->modi = g_malloc0(state->num_modi * sizeof(textbox *));
1912  for (unsigned int j = 0; j < state->num_modi; j++) {
1913  const Mode *mode = rofi_get_mode(j);
1914  state->modi[j] = textbox_create(
1915  WIDGET(state->sidebar_bar), WIDGET_TYPE_MODE_SWITCHER, "button",
1916  TB_AUTOHEIGHT, (mode == state->sw) ? HIGHLIGHT : NORMAL,
1917  mode_get_display_name(mode), 0.5, 0.5);
1918  box_add(state->sidebar_bar, WIDGET(state->modi[j]), TRUE);
1920  WIDGET(state->modi[j]), textbox_sidebar_modi_trigger_action, state);
1921  }
1922  } else if (g_ascii_strcasecmp(name, "overlay") == 0) {
1923  state->overlay = textbox_create(
1924  WIDGET(parent_widget), WIDGET_TYPE_TEXTBOX_TEXT, "overlay",
1925  TB_AUTOWIDTH | TB_AUTOHEIGHT, URGENT, "blaat", 0.5, 0);
1926  box_add((box *)parent_widget, WIDGET(state->overlay), FALSE);
1927  widget_disable(WIDGET(state->overlay));
1928  } else if (g_ascii_strncasecmp(name, "textbox", 7) == 0) {
1929  textbox *t = textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1930  TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
1931  box_add((box *)parent_widget, WIDGET(t), TRUE);
1932  } else if (g_ascii_strncasecmp(name, "button", 6) == 0) {
1933  textbox *t = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1934  TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
1935  box_add((box *)parent_widget, WIDGET(t), TRUE);
1937  state);
1938  } else if (g_ascii_strncasecmp(name, "icon", 4) == 0) {
1939  icon *t = icon_create(parent_widget, name);
1940  /* small hack to make it clickable */
1941  const char *type = rofi_theme_get_string(WIDGET(t), "action", NULL);
1942  if (type) {
1943  WIDGET(t)->type = WIDGET_TYPE_EDITBOX;
1944  }
1945  box_add((box *)parent_widget, WIDGET(t), TRUE);
1947  state);
1948  } else {
1949  wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1950  box_add((box *)parent_widget, WIDGET(wid), TRUE);
1951  // g_error("The widget %s does not exists. Invalid layout.", name);
1952  }
1953  if (wid) {
1954  GList *list = rofi_theme_get_list_strings(wid, "children");
1955  if (list == NULL) {
1956  if (defaults) {
1957  char **a = g_strsplit(defaults, ",", 0);
1958  for (int i = 0; a && a[i]; i++) {
1959  rofi_view_add_widget(state, wid, a[i]);
1960  }
1961  g_strfreev(a);
1962  }
1963  } else {
1964  for (const GList *iter = g_list_first(list); iter != NULL;
1965  iter = g_list_next(iter)) {
1966  rofi_view_add_widget(state, wid, (const char *)iter->data);
1967  }
1968  g_list_free_full(list, g_free);
1969  }
1970  }
1971 }
1972 
1974  xcb_query_pointer_cookie_t pointer_cookie =
1975  xcb_query_pointer(xcb->connection, CacheState.main_window);
1976  xcb_query_pointer_reply_t *pointer_reply =
1977  xcb_query_pointer_reply(xcb->connection, pointer_cookie, NULL);
1978 
1979  if (pointer_reply == NULL) {
1980  return;
1981  }
1982 
1983  rofi_view_handle_mouse_motion(state, pointer_reply->win_x,
1984  pointer_reply->win_y, config.hover_select);
1985 
1986  free(pointer_reply);
1987 }
1988 
1989 RofiViewState *rofi_view_create(Mode *sw, const char *input,
1990  MenuFlags menu_flags,
1991  void (*finalize)(RofiViewState *)) {
1992  TICK();
1994  state->menu_flags = menu_flags;
1995  state->sw = sw;
1996  state->selected_line = UINT32_MAX;
1997  state->retv = MENU_CANCEL;
1998  state->distance = NULL;
1999  state->quit = FALSE;
2000  state->skip_absorb = FALSE;
2001  // We want to filter on the first run.
2002  state->refilter = TRUE;
2003  state->finalize = finalize;
2004  state->mouse_seen = FALSE;
2005 
2006  // Request the lines to show.
2007  state->num_lines = mode_get_num_entries(sw);
2008 
2009  if (state->sw) {
2010  char *title =
2011  g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
2013  g_free(title);
2014  } else {
2016  }
2017  TICK_N("Startup notification");
2018 
2019  // Get active monitor size.
2020  TICK_N("Get active monitor");
2021 
2022  state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
2023  // Get children.
2024  GList *list =
2025  rofi_theme_get_list_strings(WIDGET(state->main_window), "children");
2026  if (list == NULL) {
2027  rofi_view_add_widget(state, WIDGET(state->main_window), "mainbox");
2028  } else {
2029  for (const GList *iter = list; iter != NULL; iter = g_list_next(iter)) {
2030  rofi_view_add_widget(state, WIDGET(state->main_window),
2031  (const char *)iter->data);
2032  }
2033  g_list_free_full(list, g_free);
2034  }
2035 
2036  if (state->text && input) {
2037  textbox_text(state->text, input);
2038  textbox_cursor_end(state->text);
2039  }
2040 
2041  // filtered list
2042  state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
2043  state->distance = (int *)g_malloc0_n(state->num_lines, sizeof(int));
2044 
2046  // Only needed when window is fixed size.
2049  }
2050 
2051  state->height = rofi_view_calculate_height(state);
2052  // Move the window to the correct x,y position.
2055 
2056  state->quit = FALSE;
2057  rofi_view_refilter(state);
2058  rofi_view_update(state, TRUE);
2059  xcb_map_window(xcb->connection, CacheState.main_window);
2061  rofi_view_ping_mouse(state);
2062  xcb_flush(xcb->connection);
2063 
2065  /* When Override Redirect, the WM will not let us know we can take focus, so
2066  * just steal it */
2067  if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
2068  rofi_xcb_set_input_focus(CacheState.main_window);
2069  }
2070 
2071  if (xcb->sncontext != NULL) {
2072  sn_launchee_context_complete(xcb->sncontext);
2073  }
2074  return state;
2075 }
2076 
2077 int rofi_view_error_dialog(const char *msg, int markup) {
2079  state->retv = MENU_CANCEL;
2080  state->menu_flags = MENU_ERROR_DIALOG;
2081  state->finalize = process_result;
2082 
2083  state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
2084  box *box = box_create(WIDGET(state->main_window), "error-message",
2086  box_add(state->main_window, WIDGET(box), TRUE);
2087  state->text =
2089  (TB_AUTOHEIGHT | TB_WRAP) + ((markup) ? TB_MARKUP : 0),
2090  NORMAL, (msg != NULL) ? msg : "", 0, 0);
2091  box_add(box, WIDGET(state->text), TRUE);
2092 
2093  // Make sure we enable fixed num lines when in normal window mode.
2096  }
2098  state->height = rofi_view_calculate_height(state);
2099 
2100  // Calculate window position.
2102 
2103  // Move the window to the correct x,y position.
2105 
2106  // Display it.
2107  xcb_map_window(xcb->connection, CacheState.main_window);
2109 
2110  if (xcb->sncontext != NULL) {
2111  sn_launchee_context_complete(xcb->sncontext);
2112  }
2113 
2114  // Set it as current window.
2115  rofi_view_set_active(state);
2116  return TRUE;
2117 }
2118 
2119 void rofi_view_hide(void) {
2120  if (CacheState.main_window != XCB_WINDOW_NONE) {
2122  xcb_unmap_window(xcb->connection, CacheState.main_window);
2124  }
2125 }
2126 
2128  g_debug("Cleanup.");
2129  if (CacheState.idle_timeout > 0) {
2130  g_source_remove(CacheState.idle_timeout);
2131  CacheState.idle_timeout = 0;
2132  }
2133  if (CacheState.user_timeout > 0) {
2134  g_source_remove(CacheState.user_timeout);
2135  CacheState.user_timeout = 0;
2136  }
2137  if (CacheState.repaint_source > 0) {
2138  g_source_remove(CacheState.repaint_source);
2139  CacheState.repaint_source = 0;
2140  }
2141  if (CacheState.fake_bg) {
2142  cairo_surface_destroy(CacheState.fake_bg);
2143  CacheState.fake_bg = NULL;
2144  }
2145  if (CacheState.edit_draw) {
2146  cairo_destroy(CacheState.edit_draw);
2147  CacheState.edit_draw = NULL;
2148  }
2149  if (CacheState.edit_surf) {
2150  cairo_surface_destroy(CacheState.edit_surf);
2151  CacheState.edit_surf = NULL;
2152  }
2153  if (CacheState.main_window != XCB_WINDOW_NONE) {
2154  g_debug("Unmapping and free'ing window");
2155  xcb_unmap_window(xcb->connection, CacheState.main_window);
2157  xcb_free_gc(xcb->connection, CacheState.gc);
2158  xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
2159  xcb_destroy_window(xcb->connection, CacheState.main_window);
2160  CacheState.main_window = XCB_WINDOW_NONE;
2161  }
2162  if (map != XCB_COLORMAP_NONE) {
2163  xcb_free_colormap(xcb->connection, map);
2164  map = XCB_COLORMAP_NONE;
2165  }
2166  xcb_flush(xcb->connection);
2167  g_assert(g_queue_is_empty(&(CacheState.views)));
2168 }
2170  TICK_N("Setup Threadpool, start");
2171  if (config.threads == 0) {
2172  config.threads = 1;
2173  long procs = sysconf(_SC_NPROCESSORS_CONF);
2174  if (procs > 0) {
2175  config.threads = MIN(procs, 128l);
2176  }
2177  }
2178  // Create thread pool
2179  GError *error = NULL;
2180  tpool = g_thread_pool_new(rofi_view_call_thread, NULL, config.threads, FALSE,
2181  &error);
2182  if (error == NULL) {
2183  // Idle threads should stick around for a max of 60 seconds.
2184  g_thread_pool_set_max_idle_time(60000);
2185  // We are allowed to have
2186  g_thread_pool_set_max_threads(tpool, config.threads, &error);
2187  }
2188  // If error occurred during setup of pool, tell user and exit.
2189  if (error != NULL) {
2190  g_warning("Failed to setup thread pool: '%s'", error->message);
2191  g_error_free(error);
2192  exit(EXIT_FAILURE);
2193  }
2194  TICK_N("Setup Threadpool, done");
2195 }
2197  if (tpool) {
2198  g_thread_pool_free(tpool, TRUE, TRUE);
2199  tpool = NULL;
2200  }
2201 }
2202 Mode *rofi_view_get_mode(RofiViewState *state) { return state->sw; }
2203 
2204 void rofi_view_set_overlay(RofiViewState *state, const char *text) {
2205  if (state->overlay == NULL || state->list_view == NULL) {
2206  return;
2207  }
2208  if (text == NULL) {
2209  widget_disable(WIDGET(state->overlay));
2210  return;
2211  }
2212  widget_enable(WIDGET(state->overlay));
2213  textbox_text(state->overlay, text);
2214  // We want to queue a repaint.
2216 }
2217 
2219  if (state->text) {
2220  textbox_text(state->text, "");
2221  rofi_view_set_selected_line(state, 0);
2222  }
2223 }
2224 
2227 }
2228 
2230  state->sw = mode;
2231  // Update prompt;
2232  if (state->prompt) {
2233  rofi_view_update_prompt(state);
2234  }
2235  if (state->sw) {
2236  char *title =
2237  g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
2239  g_free(title);
2240  } else {
2242  }
2243  if (state->sidebar_bar) {
2244  for (unsigned int j = 0; j < state->num_modi; j++) {
2245  const Mode *tb_mode = rofi_get_mode(j);
2246  textbox_font(state->modi[j], (tb_mode == state->sw) ? HIGHLIGHT : NORMAL);
2247  }
2248  }
2249  rofi_view_restart(state);
2250  state->reload = TRUE;
2251  state->refilter = TRUE;
2252  rofi_view_refilter(state);
2253  rofi_view_update(state, TRUE);
2254 }
2255 
2256 xcb_window_t rofi_view_get_window(void) { return CacheState.main_window; }
2257 
2258 void rofi_view_set_window_title(const char *title) {
2259  ssize_t len = strlen(title);
2260  xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
2261  CacheState.main_window, xcb->ewmh._NET_WM_NAME,
2262  xcb->ewmh.UTF8_STRING, 8, len, title);
2263  xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
2264  CacheState.main_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
2265  8, len, title);
2266 }
@ WL_SOUTH_EAST
Definition: rofi-types.h:247
@ WL_CENTER
Definition: rofi-types.h:233
@ WL_NORTH_WEST
Definition: rofi-types.h:243
@ WL_SOUTH
Definition: rofi-types.h:239
@ WL_NORTH_EAST
Definition: rofi-types.h:245
@ WL_WEST
Definition: rofi-types.h:241
@ WL_NORTH
Definition: rofi-types.h:235
@ WL_EAST
Definition: rofi-types.h:237
@ WL_SOUTH_WEST
Definition: rofi-types.h:249
PangoAttrList * helper_token_match_get_pango_attr(RofiHighlightColorStyle th, rofi_int_matcher **tokens, const char *input, PangoAttrList *retv)
Definition: helper.c:418
gboolean helper_validate_font(PangoFontDescription *pfd, const char *font)
Definition: helper.c:605
void helper_tokenize_free(rofi_int_matcher **tokens)
Definition: helper.c:119
unsigned int levenshtein(const char *needle, const glong needlelen, const char *haystack, const glong haystacklen)
Definition: helper.c:749
int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, glong slen)
Definition: helper.c:897
char * rofi_expand_path(const char *input)
Definition: helper.c:717
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition: helper.c:263
guint key_binding_get_action_from_name(const char *name)
Definition: keyb.c:155
BindingsScope
Definition: keyb.h:43
KeyBindingAction
Definition: keyb.h:58
MouseBindingMouseDefaultAction
Definition: keyb.h:166
@ SCOPE_MOUSE_LISTVIEW_ELEMENT
Definition: keyb.h:46
@ SCOPE_MOUSE_EDITBOX
Definition: keyb.h:49
@ SCOPE_MOUSE_LISTVIEW
Definition: keyb.h:45
@ SCOPE_MOUSE_SCROLLBAR
Definition: keyb.h:50
@ SCOPE_GLOBAL
Definition: keyb.h:44
@ SCOPE_MOUSE_MODE_SWITCHER
Definition: keyb.h:51
@ ROW_LAST
Definition: keyb.h:107
@ CUSTOM_4
Definition: keyb.h:113
@ CUSTOM_17
Definition: keyb.h:126
@ CUSTOM_12
Definition: keyb.h:121
@ CUSTOM_9
Definition: keyb.h:118
@ REMOVE_TO_SOL
Definition: keyb.h:88
@ ROW_RIGHT
Definition: keyb.h:100
@ ROW_UP
Definition: keyb.h:101
@ CUSTOM_8
Definition: keyb.h:117
@ SELECT_ELEMENT_9
Definition: keyb.h:140
@ MOVE_FRONT
Definition: keyb.h:66
@ REMOVE_WORD_FORWARD
Definition: keyb.h:80
@ CHANGE_ELLIPSIZE
Definition: keyb.h:130
@ ACCEPT_CUSTOM_ALT
Definition: keyb.h:93
@ REMOVE_WORD_BACK
Definition: keyb.h:78
@ TOGGLE_SORT
Definition: keyb.h:131
@ ACCEPT_ENTRY
Definition: keyb.h:90
@ ROW_TAB
Definition: keyb.h:103
@ PAGE_NEXT
Definition: keyb.h:105
@ TOGGLE_CASE_SENSITIVITY
Definition: keyb.h:97
@ MOVE_CHAR_FORWARD
Definition: keyb.h:76
@ MOVE_WORD_FORWARD
Definition: keyb.h:72
@ MODE_COMPLETE
Definition: keyb.h:95
@ CUSTOM_1
Definition: keyb.h:110
@ SELECT_ELEMENT_6
Definition: keyb.h:137
@ CUSTOM_18
Definition: keyb.h:127
@ CUSTOM_15
Definition: keyb.h:124
@ CUSTOM_11
Definition: keyb.h:120
@ ACCEPT_CUSTOM
Definition: keyb.h:92
@ CUSTOM_5
Definition: keyb.h:114
@ CUSTOM_19
Definition: keyb.h:128
@ REMOVE_TO_EOL
Definition: keyb.h:86
@ SELECT_ELEMENT_3
Definition: keyb.h:134
@ ROW_SELECT
Definition: keyb.h:108
@ PASTE_PRIMARY
Definition: keyb.h:60
@ ROW_DOWN
Definition: keyb.h:102
@ CUSTOM_13
Definition: keyb.h:122
@ PASTE_SECONDARY
Definition: keyb.h:62
@ SELECT_ELEMENT_10
Definition: keyb.h:141
@ PAGE_PREV
Definition: keyb.h:104
@ CUSTOM_3
Definition: keyb.h:112
@ CUSTOM_7
Definition: keyb.h:116
@ SELECT_ELEMENT_5
Definition: keyb.h:136
@ ROW_FIRST
Definition: keyb.h:106
@ CUSTOM_6
Definition: keyb.h:115
@ ROW_LEFT
Definition: keyb.h:99
@ CUSTOM_14
Definition: keyb.h:123
@ SELECT_ELEMENT_4
Definition: keyb.h:135
@ MOVE_WORD_BACK
Definition: keyb.h:70
@ MOVE_END
Definition: keyb.h:68
@ CUSTOM_10
Definition: keyb.h:119
@ MODE_NEXT
Definition: keyb.h:94
@ REMOVE_CHAR_BACK
Definition: keyb.h:84
@ DELETE_ENTRY
Definition: keyb.h:98
@ SELECT_ELEMENT_1
Definition: keyb.h:132
@ CLEAR_LINE
Definition: keyb.h:64
@ CUSTOM_2
Definition: keyb.h:111
@ SELECT_ELEMENT_2
Definition: keyb.h:133
@ SCREENSHOT
Definition: keyb.h:129
@ CANCEL
Definition: keyb.h:109
@ MODE_PREVIOUS
Definition: keyb.h:96
@ ACCEPT_ALT
Definition: keyb.h:91
@ SELECT_ELEMENT_7
Definition: keyb.h:138
@ MOVE_CHAR_BACK
Definition: keyb.h:74
@ SELECT_ELEMENT_8
Definition: keyb.h:139
@ REMOVE_CHAR_FORWARD
Definition: keyb.h:82
@ CUSTOM_16
Definition: keyb.h:125
@ MOUSE_CLICK_DOWN
Definition: keyb.h:167
@ MOUSE_DCLICK_UP
Definition: keyb.h:170
@ MOUSE_CLICK_UP
Definition: keyb.h:168
@ MOUSE_DCLICK_DOWN
Definition: keyb.h:169
char * mode_get_completion(const Mode *mode, unsigned int selected_line)
Definition: mode.c:81
unsigned int mode_get_num_entries(const Mode *mode)
Definition: mode.c:54
const char * mode_get_display_name(const Mode *mode)
Definition: mode.c:144
char * mode_get_display_value(const Mode *mode, unsigned int selected_line, int *state, GList **attribute_list, int get_entry)
Definition: mode.c:60
char * mode_preprocess_input(Mode *mode, const char *input)
Definition: mode.c:167
MenuReturn
Definition: mode.h:65
int mode_token_match(const Mode *mode, rofi_int_matcher **tokens, unsigned int selected_line)
Definition: mode.c:110
char * mode_get_message(const Mode *mode)
Definition: mode.c:173
cairo_surface_t * mode_get_icon(const Mode *mode, unsigned int selected_line, int height)
Definition: mode.c:71
@ MENU_CUSTOM_COMMAND
Definition: mode.h:79
@ MENU_COMPLETE
Definition: mode.h:83
@ MENU_LOWER_MASK
Definition: mode.h:87
@ MENU_PREVIOUS
Definition: mode.h:81
@ MENU_CANCEL
Definition: mode.h:69
@ MENU_QUICK_SWITCH
Definition: mode.h:77
@ MENU_ENTRY_DELETE
Definition: mode.h:75
@ MENU_NEXT
Definition: mode.h:71
@ MENU_CUSTOM_ACTION
Definition: mode.h:85
@ MENU_OK
Definition: mode.h:67
@ MENU_CUSTOM_INPUT
Definition: mode.h:73
void rofi_quit_main_loop(void)
Definition: rofi.c:667
#define color_reset
Definition: rofi.h:95
unsigned int rofi_get_num_enabled_modi(void)
Definition: rofi.c:133
const Mode * rofi_get_mode(unsigned int index)
Definition: rofi.c:135
#define color_green
Definition: rofi.h:101
#define TICK()
Definition: timings.h:64
#define TICK_N(a)
Definition: timings.h:69
void textbox_font(textbox *tb, TextBoxFontType tbft)
Definition: textbox.c:273
TextboxFlags
Definition: textbox.h:89
int textbox_keybinding(textbox *tb, KeyBindingAction action)
Definition: textbox.c:751
TextBoxFontType
Definition: textbox.h:101
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
Definition: textbox.c:337
const char * textbox_get_visible_text(const textbox *tb)
Definition: textbox.c:325
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
Definition: textbox.c:331
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
Definition: textbox.c:191
void textbox_set_pango_context(const char *font, PangoContext *p)
Definition: textbox.c:851
void textbox_cursor_end(textbox *tb)
Definition: textbox.c:623
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
Definition: textbox.c:813
void textbox_text(textbox *tb, const char *text)
Definition: textbox.c:345
@ TB_AUTOHEIGHT
Definition: textbox.h:90
@ TB_PASSWORD
Definition: textbox.h:95
@ TB_MARKUP
Definition: textbox.h:93
@ TB_WRAP
Definition: textbox.h:94
@ TB_EDITABLE
Definition: textbox.h:92
@ TB_AUTOWIDTH
Definition: textbox.h:91
@ URGENT
Definition: textbox.h:105
@ HIGHLIGHT
Definition: textbox.h:116
@ NORMAL
Definition: textbox.h:103
void rofi_view_cleanup()
Definition: view.c:2127
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition: view.c:2204
void __create_window(MenuFlags menu_flags)
Definition: view.c:755
void rofi_view_clear_input(RofiViewState *state)
Definition: view.c:2218
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition: view.c:2229
void rofi_view_hide(void)
Definition: view.c:2119
void rofi_view_reload(void)
Definition: view.c:501
Mode * rofi_view_get_mode(RofiViewState *state)
Definition: view.c:2202
xcb_window_t rofi_view_get_window(void)
Definition: view.c:2256
void rofi_view_remove_active(RofiViewState *state)
Definition: view.c:524
RofiViewState * rofi_view_get_active(void)
Definition: view.c:522
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:2077
void rofi_view_set_active(RofiViewState *state)
Definition: view.c:531
void rofi_view_queue_redraw(void)
Definition: view.c:508
void rofi_view_restart(RofiViewState *state)
Definition: view.c:517
MenuFlags
Definition: view.h:48
void rofi_view_handle_text(RofiViewState *state, char *text)
Definition: view.c:1540
void rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1504
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition: view.c:590
unsigned int rofi_view_get_completed(const RofiViewState *state)
Definition: view.c:607
gboolean rofi_view_check_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1473
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
Definition: view.c:1582
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
Definition: view.c:1670
void rofi_view_finalize(RofiViewState *state)
Definition: view.c:1230
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition: view.c:554
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
Definition: view.c:1636
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition: view.c:1989
void rofi_view_frame_callback(void)
Definition: view.c:1679
void rofi_view_free(RofiViewState *state)
Definition: view.c:572
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition: view.c:611
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition: view.c:594
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition: view.c:598
void rofi_view_maybe_update(RofiViewState *state)
Definition: view.c:1610
@ MENU_PASSWORD
Definition: view.h:52
@ MENU_INDICATOR
Definition: view.h:58
@ MENU_NORMAL_WINDOW
Definition: view.h:54
@ MENU_ERROR_DIALOG
Definition: view.h:56
@ MENU_NORMAL
Definition: view.h:50
void rofi_view_ellipsize_start(RofiViewState *state)
Definition: view.c:2225
void rofi_capture_screenshot(void)
Definition: view.c:174
void rofi_view_workers_initialize(void)
Definition: view.c:2169
void rofi_view_set_window_title(const char *title)
Definition: view.c:2258
void rofi_view_get_current_monitor(int *width, int *height)
Definition: view.c:139
void rofi_view_workers_finalize(void)
Definition: view.c:2196
void box_add(box *box, widget *child, gboolean expand)
Definition: box.c:286
box * box_create(widget *parent, const char *name, RofiOrientation type)
Definition: box.c:346
container * container_create(widget *parent, const char *name)
Definition: container.c:102
void container_add(container *container, widget *child)
Definition: container.c:67
void icon_set_surface(icon *icon, cairo_surface_t *surf)
Definition: icon.c:140
icon * icon_create(widget *parent, const char *name)
Definition: icon.c:153
void listview_nav_page_next(listview *lv)
Definition: listview.c:877
void listview_set_fixed_num_lines(listview *lv)
Definition: listview.c:966
void listview_set_num_lines(listview *lv, unsigned int num_lines)
Definition: listview.c:948
void listview_set_num_elements(listview *lv, unsigned int rows)
Definition: listview.c:523
listview * listview_create(widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse)
Definition: listview.c:667
void listview_nav_right(listview *lv)
Definition: listview.c:794
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
Definition: listview.c:935
void listview_toggle_ellipsizing(listview *lv)
Definition: listview.c:981
void listview_set_selected(listview *lv, unsigned int selected)
Definition: listview.c:544
void listview_set_max_lines(listview *lv, unsigned int max_lines)
Definition: listview.c:954
void listview_nav_left(listview *lv)
Definition: listview.c:781
void listview_set_scroll_type(listview *lv, ScrollType type)
Definition: listview.c:929
gboolean listview_get_fixed_num_lines(listview *lv)
Definition: listview.c:960
void listview_set_ellipsize_start(listview *lv)
Definition: listview.c:972
unsigned int listview_get_selected(listview *lv)
Definition: listview.c:537
void listview_set_multi_select(listview *lv, gboolean enable)
Definition: listview.c:943
void listview_nav_up(listview *lv)
Definition: listview.c:760
void listview_nav_page_prev(listview *lv)
Definition: listview.c:867
void listview_nav_down(listview *lv)
Definition: listview.c:770
WidgetTriggerActionResult widget_trigger_action(widget *wid, guint action, gint x, gint y)
Definition: widget.c:544
void widget_queue_redraw(widget *wid)
Definition: widget.c:487
void widget_free(widget *wid)
Definition: widget.c:425
static void widget_disable(widget *widget)
Definition: widget.h:170
void widget_resize(widget *widget, short w, short h)
Definition: widget.c:87
WidgetType
Definition: widget.h:56
static void widget_enable(widget *widget)
Definition: widget.h:178
WidgetTriggerActionResult widget_check_action(widget *wid, guint action, gint x, gint y)
Definition: widget.c:529
void widget_draw(widget *widget, cairo_t *d)
Definition: widget.c:135
void widget_xy_to_relative(widget *widget, gint *x, gint *y)
Definition: widget.c:468
#define WIDGET(a)
Definition: widget.h:119
WidgetTriggerActionResult
Definition: widget.h:76
widget * widget_find_mouse_target(widget *wid, WidgetType type, gint x, gint y)
Definition: widget.c:510
void widget_set_trigger_action_handler(widget *wid, widget_trigger_action_cb cb, void *cb_data)
Definition: widget.c:555
int widget_get_desired_height(widget *wid, const int width)
Definition: widget.c:642
gboolean widget_motion_notify(widget *wid, gint x, gint y)
Definition: widget.c:564
gboolean widget_need_redraw(widget *wid)
Definition: widget.c:500
@ WIDGET_TYPE_UNKNOWN
Definition: widget.h:58
@ WIDGET_TYPE_LISTVIEW_ELEMENT
Definition: widget.h:62
@ WIDGET_TYPE_TEXTBOX_TEXT
Definition: widget.h:70
@ WIDGET_TYPE_MODE_SWITCHER
Definition: widget.h:68
@ WIDGET_TYPE_EDITBOX
Definition: widget.h:64
@ WIDGET_TRIGGER_ACTION_RESULT_HANDLED
Definition: widget.h:80
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_END
Definition: widget.h:84
@ WIDGET_TRIGGER_ACTION_RESULT_GRAB_MOTION_BEGIN
Definition: widget.h:82
@ WIDGET_TRIGGER_ACTION_RESULT_IGNORED
Definition: widget.h:78
@ P_INTEGER
Definition: rofi-types.h:12
@ P_STRING
Definition: rofi-types.h:16
@ ROFI_ORIENTATION_HORIZONTAL
Definition: rofi-types.h:139
@ ROFI_ORIENTATION_VERTICAL
Definition: rofi-types.h:138
RofiCursorType
Definition: rofi-types.h:145
@ ROFI_CURSOR_POINTER
Definition: rofi-types.h:147
@ ROFI_CURSOR_TEXT
Definition: rofi-types.h:148
@ ROFI_CURSOR_DEFAULT
Definition: rofi-types.h:146
@ ROFI_HL_UNDERLINE
Definition: rofi-types.h:58
@ ROFI_HL_BOLD
Definition: rofi-types.h:56
Settings config
#define DEFAULT_MENU_LINES
Definition: settings.h:183
#define DEFAULT_MENU_WIDTH
Definition: settings.h:187
@ SORT_FZF
Definition: settings.h:49
@ SORT_NORMAL
Definition: settings.h:49
PropertyValue value
Definition: rofi-types.h:293
PropertyType type
Definition: rofi-types.h:291
unsigned int filtered_lines
Definition: view-internal.h:80
container * mesg_box
Definition: view-internal.h:68
textbox * text
Definition: view-internal.h:59
widget * motion_target
textbox * mesg_tb
Definition: view-internal.h:70
textbox * overlay
Definition: view-internal.h:66
struct RofiViewState::@7 mouse
listview * list_view
Definition: view-internal.h:64
textbox ** modi
unsigned int num_lines
Definition: view-internal.h:77
MenuReturn retv
Definition: view-internal.h:94
void(* finalize)(struct RofiViewState *state)
textbox * prompt
Definition: view-internal.h:57
unsigned int num_modi
unsigned int * line_map
Definition: view-internal.h:75
textbox * tb_filtered_rows
rofi_int_matcher ** tokens
textbox * tb_total_rows
unsigned int selected_line
Definition: view-internal.h:92
KeyBindingAction prev_action
Definition: view-internal.h:83
textbox * case_indicator
Definition: view-internal.h:61
MenuFlags menu_flags
WindowLocation location
Definition: settings.h:84
unsigned int threads
Definition: settings.h:143
int x_offset
Definition: settings.h:88
unsigned int scroll_method
Definition: settings.h:144
int y_offset
Definition: settings.h:86
unsigned int auto_select
Definition: settings.h:126
unsigned int case_sensitive
Definition: settings.h:114
unsigned int sort
Definition: settings.h:96
char * menu_font
Definition: settings.h:59
unsigned int sidebar_mode
Definition: settings.h:120
gboolean benchmark_ui
Definition: settings.h:173
int dpi
Definition: settings.h:141
SortingMethod sorting_method_enum
Definition: settings.h:98
gboolean hover_select
Definition: settings.h:122
int element_height
Definition: settings.h:118
Definition: box.c:40
Definition: icon.c:39
const char * pattern
Definition: view.c:651
unsigned int count
Definition: view.c:648
GMutex * mutex
Definition: view.c:637
unsigned int stop
Definition: view.c:646
thread_state st
Definition: view.c:632
RofiViewState * state
Definition: view.c:642
unsigned int * acount
Definition: view.c:639
unsigned int start
Definition: view.c:644
GCond * cond
Definition: view.c:635
void(* callback)(struct _thread_state *t, gpointer data)
Definition: rofi-types.h:317
RofiCursorType cursor_type
Definition: xcb.h:94
xcb_connection_t * connection
Definition: xcb-internal.h:47
SnLauncheeContext * sncontext
Definition: xcb-internal.h:52
xcb_ewmh_connection_t ewmh
Definition: xcb-internal.h:48
xcb_screen_t * screen
Definition: xcb-internal.h:49
char * text
Definition: textbox.h:65
GList * rofi_theme_get_list_strings(const widget *widget, const char *property)
Definition: theme.c:1255
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:865
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition: theme.c:766
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition: theme.c:891
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:1403
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition: theme.c:728
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition: theme.c:1308
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition: theme.c:828
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition: theme.c:803
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition: theme.c:978
static void rofi_view_call_thread(gpointer data, gpointer user_data)
Definition: view.c:661
cairo_surface_t * fake_bg
Definition: view.c:95
static void rofi_view_nav_last(RofiViewState *state)
Definition: view.c:1000
static gboolean rofi_view_repaint(G_GNUC_UNUSED void *data)
Definition: view.c:267
static WidgetTriggerActionResult textbox_button_trigger_action(widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data)
Definition: view.c:1703
static char * get_matching_state(void)
Definition: view.c:147
static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data)
Definition: view.c:481
static gboolean rofi_view_reload_idle(G_GNUC_UNUSED gpointer data)
Definition: view.c:449
static gboolean bench_update(void)
Definition: view.c:243
struct _thread_state_view thread_state_view
static RofiViewState * __rofi_view_state_create(void)
Definition: view.c:623
guint idle_timeout
Definition: view.c:113
static void rofi_view_nav_row_select(RofiViewState *state)
Definition: view.c:970
GQueue views
Definition: view.c:109
static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom, void *udata)
Definition: view.c:1761
static void rofi_view_input_changed()
Definition: view.c:1240
GTimer * time
Definition: view.c:234
cairo_surface_t * edit_surf
Definition: view.c:101
static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, const char *name)
Definition: view.c:1774
static void update_callback(textbox *t, icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full)
Definition: view.c:1009
static void rofi_view_nav_row_tab(RofiViewState *state)
Definition: view.c:946
static void rofi_view_setup_fake_transparency(widget *win, const char *const fake_background)
Definition: view.c:702
static struct @2 BenchMark
static void rofi_view_reload_message_bar(RofiViewState *state)
Definition: view.c:435
static void rofi_view_nav_first(RofiViewState *state)
Definition: view.c:990
gboolean do_bench
Definition: view.c:227
xcb_window_t main_window
Definition: view.c:93
xcb_gcontext_t gc
Definition: view.c:97
guint user_timeout
Definition: view.c:115
cairo_t * edit_draw
Definition: view.c:103
void rofi_view_update(RofiViewState *state, gboolean qr)
Definition: view.c:1060
static const int loc_transtable[9]
Definition: view.c:304
xcb_pixmap_t edit_pixmap
Definition: view.c:99
static void rofi_view_trigger_global_action(KeyBindingAction action)
Definition: view.c:1242
workarea mon
Definition: view.c:111
int fake_bgrel
Definition: view.c:105
static void filter_elements(thread_state *ts, G_GNUC_UNUSED gpointer user_data)
Definition: view.c:666
void process_result(RofiViewState *state)
Definition: rofi.c:202
static void rofi_view_update_prompt(RofiViewState *state)
Definition: view.c:285
static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data)
Definition: view.c:475
static void rofi_view_refilter(RofiViewState *state)
Definition: view.c:1106
X11CursorType cursor_type
Definition: view.c:123
static int rofi_view_calculate_height(RofiViewState *state)
Definition: view.c:1686
GThreadPool * tpool
Definition: view.c:83
double min
Definition: view.c:240
RofiViewState * current_active_menu
Definition: view.c:86
MenuFlags flags
Definition: view.c:107
unsigned long long count
Definition: view.c:117
static void rofi_view_calculate_window_position(RofiViewState *state)
Definition: view.c:308
uint64_t draws
Definition: view.c:236
static WidgetTriggerActionResult textbox_sidebar_modi_trigger_action(widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data)
Definition: view.c:1732
double last_ts
Definition: view.c:238
static void rofi_view_set_cursor(RofiCursorType type)
Definition: view.c:1570
static void rofi_view_take_action(const char *name)
Definition: view.c:459
static void rofi_view_ping_mouse(RofiViewState *state)
Definition: view.c:1973
static void rofi_view_window_update_size(RofiViewState *state)
Definition: view.c:406
gboolean fullscreen
Definition: view.c:121
static void rofi_view_calculate_window_width(RofiViewState *state)
Definition: view.c:924
static X11CursorType rofi_cursor_type_to_x11_cursor_type(RofiCursorType type)
Definition: view.c:1547
static RofiCursorType rofi_view_resolve_cursor(RofiViewState *state, gint x, gint y)
Definition: view.c:1562
static int lev_sort(const void *p1, const void *p2, void *arg)
Definition: view.c:163
struct @1 CacheState
static void _rofi_view_reload_row(RofiViewState *state)
Definition: view.c:1096
guint repaint_source
Definition: view.c:119
xcb_colormap_t map
Definition: xcb.c:98
int monitor_active(workarea *mon)
Definition: xcb.c:973
void display_early_cleanup(void)
Definition: xcb.c:1724
cairo_surface_t * x11_helper_get_screenshot_surface(void)
Definition: xcb.c:337
xcb_stuff * xcb
Definition: xcb.c:91
xcb_depth_t * depth
Definition: xcb.c:96
void rofi_xcb_revert_input_focus(void)
Definition: xcb.c:1333
void rofi_xcb_set_input_focus(xcb_window_t w)
Definition: xcb.c:1310
void x11_set_cursor(xcb_window_t window, X11CursorType type)
Definition: xcb.c:1781
cairo_surface_t * x11_helper_get_bg_surface(void)
Definition: xcb.c:363
xcb_window_t xcb_stuff_get_root_window(void)
Definition: xcb.c:1722
void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count)
Definition: xcb.c:403
void cairo_image_surface_blur(cairo_surface_t *surface, double radius, double deviation)
Definition: xcb.c:167
void x11_disable_decoration(xcb_window_t window)
Definition: xcb.c:1757
xcb_atom_t netatoms[NUM_NETATOMS]
Definition: xcb.c:103
xcb_visualtype_t * visual
Definition: xcb.c:97
X11CursorType
Definition: xcb.h:174
@ CURSOR_POINTER
Definition: xcb.h:178
@ CURSOR_DEFAULT
Definition: xcb.h:176
@ CURSOR_TEXT
Definition: xcb.h:180