rofi  1.7.0
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 static gboolean rofi_view_user_timeout(G_GNUC_UNUSED gpointer data) {
459  CacheState.user_timeout = 0;
460  ThemeWidget *wid = rofi_config_find_widget("timeout", 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  return G_SOURCE_REMOVE;
475 }
476 
477 static void rofi_view_set_user_timeout(G_GNUC_UNUSED gpointer data) {
478  if (CacheState.user_timeout > 0) {
479  g_source_remove(CacheState.user_timeout);
480  CacheState.user_timeout = 0;
481  }
482  {
484  ThemeWidget *wid = rofi_config_find_widget("timeout", NULL, TRUE);
485  if (wid) {
487  Property *p = rofi_theme_find_property(wid, P_INTEGER, "delay", TRUE);
488  if (p != NULL && p->type == P_INTEGER && p->value.i > 0) {
489  int delay = p->value.i;
490  CacheState.user_timeout =
491  g_timeout_add(delay * 1000, rofi_view_user_timeout, NULL);
492  }
493  }
494  }
495 }
496 
497 void rofi_view_reload(void) {
498  // @TODO add check if current view is equal to the callee
499  if (CacheState.idle_timeout == 0) {
500  CacheState.idle_timeout =
501  g_timeout_add(1000 / 10, rofi_view_reload_idle, NULL);
502  }
503 }
505  if (current_active_menu && CacheState.repaint_source == 0) {
506  CacheState.count++;
507  g_debug("redraw %llu", CacheState.count);
508  CacheState.repaint_source =
509  g_idle_add_full(G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL);
510  }
511 }
512 
514  state->quit = FALSE;
515  state->retv = MENU_CANCEL;
516 }
517 
519 
521  if (state == current_active_menu) {
522  rofi_view_set_active(NULL);
523  } else if (state) {
524  g_queue_remove(&(CacheState.views), state);
525  }
526 }
528  if (current_active_menu != NULL && state != NULL) {
529  g_queue_push_head(&(CacheState.views), current_active_menu);
530  // TODO check.
531  current_active_menu = state;
532  g_debug("stack view.");
535  return;
536  }
537  if (state == NULL && !g_queue_is_empty(&(CacheState.views))) {
538  g_debug("pop view.");
539  current_active_menu = g_queue_pop_head(&(CacheState.views));
542  return;
543  }
544  g_assert((current_active_menu == NULL && state != NULL) ||
545  (current_active_menu != NULL && state == NULL));
546  current_active_menu = state;
548 }
549 
551  unsigned int selected_line) {
552  state->selected_line = selected_line;
553  // Find the line.
554  unsigned int selected = 0;
555  for (unsigned int i = 0; ((state->selected_line)) < UINT32_MAX && !selected &&
556  i < state->filtered_lines;
557  i++) {
558  if (state->line_map[i] == (state->selected_line)) {
559  selected = i;
560  break;
561  }
562  }
563  listview_set_selected(state->list_view, selected);
564  xcb_clear_area(xcb->connection, CacheState.main_window, 1, 0, 0, 1, 1);
565  xcb_flush(xcb->connection);
566 }
567 
569  if (state->tokens) {
571  state->tokens = NULL;
572  }
573  // Do this here?
574  // Wait for final release?
575  widget_free(WIDGET(state->main_window));
576 
577  g_free(state->line_map);
578  g_free(state->distance);
579  // Free the switcher boxes.
580  // When state is free'ed we should no longer need these.
581  g_free(state->modi);
582  state->num_modi = 0;
583  g_free(state);
584 }
585 
587  return state->retv;
588 }
589 
590 unsigned int rofi_view_get_selected_line(const RofiViewState *state) {
591  return state->selected_line;
592 }
593 
594 unsigned int rofi_view_get_next_position(const RofiViewState *state) {
595  unsigned int next_pos = state->selected_line;
596  unsigned int selected = listview_get_selected(state->list_view);
597  if ((selected + 1) < state->num_lines) {
598  (next_pos) = state->line_map[selected + 1];
599  }
600  return next_pos;
601 }
602 
603 unsigned int rofi_view_get_completed(const RofiViewState *state) {
604  return state->quit;
605 }
606 
607 const char *rofi_view_get_user_input(const RofiViewState *state) {
608  if (state->text) {
609  return state->text->text;
610  }
611  return NULL;
612 }
613 
620  return g_malloc0(sizeof(RofiViewState));
621 }
622 
626 typedef struct _thread_state_view {
629 
631  GCond *cond;
633  GMutex *mutex;
635  unsigned int *acount;
636 
640  unsigned int start;
642  unsigned int stop;
644  unsigned int count;
645 
647  const char *pattern;
649  glong plen;
657 static void rofi_view_call_thread(gpointer data, gpointer user_data) {
658  thread_state *t = (thread_state *)data;
659  t->callback(t, user_data);
660 }
661 
663  G_GNUC_UNUSED gpointer user_data) {
665  for (unsigned int i = t->start; i < t->stop; i++) {
666  int match = mode_token_match(t->state->sw, t->state->tokens, i);
667  // If each token was matched, add it to list.
668  if (match) {
669  t->state->line_map[t->start + t->count] = i;
670  if (config.sort) {
671  // This is inefficient, need to fix it.
672  char *str = mode_get_completion(t->state->sw, i);
673  glong slen = g_utf8_strlen(str, -1);
674  switch (config.sorting_method_enum) {
675  case SORT_FZF:
676  t->state->distance[i] =
677  rofi_scorer_fuzzy_evaluate(t->pattern, t->plen, str, slen);
678  break;
679  case SORT_NORMAL:
680  default:
681  t->state->distance[i] = levenshtein(t->pattern, t->plen, str, slen);
682  break;
683  }
684  g_free(str);
685  }
686  t->count++;
687  }
688  }
689  if (t->acount != NULL) {
690  g_mutex_lock(t->mutex);
691  (*(t->acount))--;
692  g_cond_signal(t->cond);
693  g_mutex_unlock(t->mutex);
694  }
695 }
696 
697 static void
699  const char *const fake_background) {
700  if (CacheState.fake_bg == NULL) {
701  cairo_surface_t *s = NULL;
706  TICK_N("Fake start");
707  if (g_strcmp0(fake_background, "real") == 0) {
708  return;
709  }
710  if (g_strcmp0(fake_background, "screenshot") == 0) {
712  } else if (g_strcmp0(fake_background, "background") == 0) {
714  } else {
715  char *fpath = rofi_expand_path(fake_background);
716  g_debug("Opening %s to use as background.", fpath);
717  s = cairo_image_surface_create_from_png(fpath);
718  CacheState.fake_bgrel = TRUE;
719  g_free(fpath);
720  }
721  TICK_N("Get surface.");
722  if (s != NULL) {
723  if (cairo_surface_status(s) != CAIRO_STATUS_SUCCESS) {
724  g_debug("Failed to open surface fake background: %s",
725  cairo_status_to_string(cairo_surface_status(s)));
726  cairo_surface_destroy(s);
727  s = NULL;
728  } else {
729  CacheState.fake_bg = cairo_image_surface_create(
730  CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h);
731 
732  int blur = rofi_theme_get_integer(WIDGET(win), "blur", 0);
733  cairo_t *dr = cairo_create(CacheState.fake_bg);
734  if (CacheState.fake_bgrel) {
735  cairo_set_source_surface(dr, s, 0, 0);
736  } else {
737  cairo_set_source_surface(dr, s, -CacheState.mon.x, -CacheState.mon.y);
738  }
739  cairo_paint(dr);
740  cairo_destroy(dr);
741  cairo_surface_destroy(s);
742  if (blur > 0) {
743  cairo_image_surface_blur(CacheState.fake_bg, (double)blur, 0);
744  TICK_N("BLUR");
745  }
746  }
747  }
748  TICK_N("Fake transparency");
749  }
750 }
751 void __create_window(MenuFlags menu_flags) {
752  uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
753  XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
754  XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
755  uint32_t xcb_event_masks =
756  XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
757  XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_KEY_PRESS |
758  XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
759  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE |
760  XCB_EVENT_MASK_BUTTON_1_MOTION | XCB_EVENT_MASK_POINTER_MOTION;
761 
762  uint32_t selval[] = {XCB_BACK_PIXMAP_NONE, 0,
763  XCB_GRAVITY_STATIC, XCB_BACKING_STORE_NOT_USEFUL,
764  xcb_event_masks, map};
765 
766  xcb_window_t box_window = xcb_generate_id(xcb->connection);
767  xcb_void_cookie_t cc = xcb_create_window_checked(
768  xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window(), 0,
769  0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visual_id, selmask,
770  selval);
771  xcb_generic_error_t *error;
772  error = xcb_request_check(xcb->connection, cc);
773  if (error) {
774  g_error("xcb_create_window() failed error=0x%x\n", error->error_code);
775  exit(EXIT_FAILURE);
776  }
777  TICK_N("xcb create window");
778  CacheState.gc = xcb_generate_id(xcb->connection);
779  xcb_create_gc(xcb->connection, CacheState.gc, box_window, 0, 0);
780 
781  TICK_N("xcb create gc");
782  // Create a drawable.
783  CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
784  xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
785  CacheState.main_window, 200, 100);
786 
787  CacheState.edit_surf = cairo_xcb_surface_create(
788  xcb->connection, CacheState.edit_pixmap, visual, 200, 100);
789  CacheState.edit_draw = cairo_create(CacheState.edit_surf);
790 
791  TICK_N("create cairo surface");
792  // Set up pango context.
793  cairo_font_options_t *fo = cairo_font_options_create();
794  // Take font description from xlib surface
795  cairo_surface_get_font_options(CacheState.edit_surf, fo);
796  // TODO should we update the drawable each time?
797  PangoContext *p = pango_cairo_create_context(CacheState.edit_draw);
798  // Set the font options from the xlib surface
799  pango_cairo_context_set_font_options(p, fo);
800  TICK_N("pango cairo font setup");
801 
802  CacheState.main_window = box_window;
803  CacheState.flags = menu_flags;
804  monitor_active(&(CacheState.mon));
805  // Setup dpi
806  if (config.dpi > 1) {
807  PangoFontMap *font_map = pango_cairo_font_map_get_default();
808  pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map,
809  (double)config.dpi);
810  } else if (config.dpi == 0 || config.dpi == 1) {
811  // Auto-detect mode.
812  double dpi = 96;
813  if (CacheState.mon.mh > 0 && config.dpi == 1) {
814  dpi = (CacheState.mon.h * 25.4) / (double)(CacheState.mon.mh);
815  } else {
816  dpi = (xcb->screen->height_in_pixels * 25.4) /
817  (double)(xcb->screen->height_in_millimeters);
818  }
819 
820  g_debug("Auto-detected DPI: %.2lf", dpi);
821  PangoFontMap *font_map = pango_cairo_font_map_get_default();
822  pango_cairo_font_map_set_resolution((PangoCairoFontMap *)font_map, dpi);
823  config.dpi = dpi;
824  } else {
825  // default pango is 96.
826  PangoFontMap *font_map = pango_cairo_font_map_get_default();
827  config.dpi =
828  pango_cairo_font_map_get_resolution((PangoCairoFontMap *)font_map);
829  }
830  // Setup font.
831  // Dummy widget.
832  box *win = box_create(NULL, "window", ROFI_ORIENTATION_HORIZONTAL);
833  const char *font =
835  if (font) {
836  PangoFontDescription *pfd = pango_font_description_from_string(font);
837  if (helper_validate_font(pfd, font)) {
838  pango_context_set_font_description(p, pfd);
839  }
840  pango_font_description_free(pfd);
841  }
842  PangoLanguage *l = pango_language_get_default();
843  pango_context_set_language(p, l);
844  TICK_N("configure font");
845 
846  // Tell textbox to use this context.
847  textbox_set_pango_context(font, p);
848  // cleanup
849  g_object_unref(p);
850  cairo_font_options_destroy(fo);
851 
852  TICK_N("textbox setup");
853  // // make it an unmanaged window
854  if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
855  window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE,
856  &(xcb->ewmh._NET_WM_STATE_ABOVE), 1);
857  uint32_t values[] = {1};
858  xcb_change_window_attributes(xcb->connection, box_window,
859  XCB_CW_OVERRIDE_REDIRECT, values);
860  } else {
861  window_set_atom_prop(box_window, xcb->ewmh._NET_WM_WINDOW_TYPE,
862  &(xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL), 1);
863  x11_disable_decoration(box_window);
864  }
865 
866  TICK_N("setup window attributes");
867  CacheState.fullscreen =
868  rofi_theme_get_boolean(WIDGET(win), "fullscreen", FALSE);
869  if (CacheState.fullscreen) {
870  xcb_atom_t atoms[] = {xcb->ewmh._NET_WM_STATE_FULLSCREEN,
871  xcb->ewmh._NET_WM_STATE_ABOVE};
872  window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE, atoms,
873  sizeof(atoms) / sizeof(xcb_atom_t));
874  }
875 
876  xcb_atom_t protocols[] = {netatoms[WM_TAKE_FOCUS]};
877  xcb_icccm_set_wm_protocols(xcb->connection, box_window,
878  xcb->ewmh.WM_PROTOCOLS, G_N_ELEMENTS(protocols),
879  protocols);
880 
881  TICK_N("setup window fullscreen");
882  // Set the WM_NAME
884  const char wm_class_name[] = "rofi\0Rofi";
885  xcb_icccm_set_wm_class(xcb->connection, box_window, sizeof(wm_class_name),
886  wm_class_name);
887 
888  TICK_N("setup window name and class");
889  const char *transparency =
890  rofi_theme_get_string(WIDGET(win), "transparency", NULL);
891  if (transparency) {
892  rofi_view_setup_fake_transparency(WIDGET(win), transparency);
893  }
894  if (xcb->sncontext != NULL) {
895  sn_launchee_context_setup_window(xcb->sncontext, CacheState.main_window);
896  }
897  TICK_N("setup startup notification");
898  widget_free(WIDGET(win));
899  TICK_N("done");
900 
901  // Set the PID.
902  pid_t pid = getpid();
903  xcb_ewmh_set_wm_pid(&(xcb->ewmh), CacheState.main_window, pid);
904 
905  // Get hostname
906  const char *hostname = g_get_host_name();
907  char *ahost = g_hostname_to_ascii(hostname);
908  if (ahost != NULL) {
909  xcb_icccm_set_wm_client_machine(xcb->connection, CacheState.main_window,
910  XCB_ATOM_STRING, 8, strlen(ahost), ahost);
911  g_free(ahost);
912  }
913 }
914 
921  if (CacheState.fullscreen) {
922  state->width = CacheState.mon.w;
923  return;
924  }
925  // Calculate as float to stop silly, big rounding down errors.
926  state->width = (CacheState.mon.w / 100.0f) * DEFAULT_MENU_WIDTH;
927  // Use theme configured width, if set.
929  "width", state->width);
931 }
932 
943  if (state->filtered_lines == 1) {
944  state->retv = MENU_OK;
945  (state->selected_line) =
946  state->line_map[listview_get_selected(state->list_view)];
947  state->quit = 1;
948  return;
949  }
950 
951  // Double tab!
952  if (state->filtered_lines == 0 && ROW_TAB == state->prev_action) {
953  state->retv = MENU_NEXT;
954  (state->selected_line) = 0;
955  state->quit = TRUE;
956  } else {
958  }
959  state->prev_action = ROW_TAB;
960 }
966 inline static void rofi_view_nav_row_select(RofiViewState *state) {
967  if (state->list_view == NULL) {
968  return;
969  }
970  unsigned int selected = listview_get_selected(state->list_view);
971  // If a valid item is selected, return that..
972  if (selected < state->filtered_lines) {
973  char *str = mode_get_completion(state->sw, state->line_map[selected]);
974  textbox_text(state->text, str);
975  g_free(str);
977  state->refilter = TRUE;
978  }
979 }
980 
986 inline static void rofi_view_nav_first(RofiViewState *state) {
987  // state->selected = 0;
988  listview_set_selected(state->list_view, 0);
989 }
990 
996 inline static void rofi_view_nav_last(RofiViewState *state) {
997  // If no lines, do nothing.
998  if (state->filtered_lines == 0) {
999  return;
1000  }
1001  // state->selected = state->filtered_lines - 1;
1002  listview_set_selected(state->list_view, -1);
1003 }
1004 
1005 static void update_callback(textbox *t, icon *ico, unsigned int index,
1006  void *udata, TextBoxFontType *type, gboolean full) {
1007  RofiViewState *state = (RofiViewState *)udata;
1008  if (full) {
1009  GList *add_list = NULL;
1010  int fstate = 0;
1011  char *text = mode_get_display_value(state->sw, state->line_map[index],
1012  &fstate, &add_list, TRUE);
1013  (*type) |= fstate;
1014  // TODO needed for markup.
1015  textbox_font(t, *type);
1016  // Move into list view.
1017  textbox_text(t, text);
1018  PangoAttrList *list = textbox_get_pango_attributes(t);
1019  if (list != NULL) {
1020  pango_attr_list_ref(list);
1021  } else {
1022  list = pango_attr_list_new();
1023  }
1024  if (ico) {
1025  int icon_height = widget_get_desired_height(WIDGET(ico));
1026  cairo_surface_t *icon =
1027  mode_get_icon(state->sw, state->line_map[index], icon_height);
1028  icon_set_surface(ico, icon);
1029  }
1030 
1031  if (state->tokens) {
1033  {0.0, 0.0, 0.0, 0.0}};
1034  th = rofi_theme_get_highlight(WIDGET(t), "highlight", th);
1036  textbox_get_visible_text(t), list);
1037  }
1038  for (GList *iter = g_list_first(add_list); iter != NULL;
1039  iter = g_list_next(iter)) {
1040  pango_attr_list_insert(list, (PangoAttribute *)(iter->data));
1041  }
1043  pango_attr_list_unref(list);
1044  g_list_free(add_list);
1045  g_free(text);
1046  } else {
1047  int fstate = 0;
1048  mode_get_display_value(state->sw, state->line_map[index], &fstate, NULL,
1049  FALSE);
1050  (*type) |= fstate;
1051  // TODO needed for markup.
1052  textbox_font(t, *type);
1053  }
1054 }
1055 
1056 void rofi_view_update(RofiViewState *state, gboolean qr) {
1057  if (!widget_need_redraw(WIDGET(state->main_window))) {
1058  return;
1059  }
1060  g_debug("Redraw view");
1061  TICK();
1062  cairo_t *d = CacheState.edit_draw;
1063  cairo_set_operator(d, CAIRO_OPERATOR_SOURCE);
1064  if (CacheState.fake_bg != NULL) {
1065  if (CacheState.fake_bgrel) {
1066  cairo_set_source_surface(d, CacheState.fake_bg, 0.0, 0.0);
1067  } else {
1068  cairo_set_source_surface(d, CacheState.fake_bg,
1069  -(double)(state->x - CacheState.mon.x),
1070  -(double)(state->y - CacheState.mon.y));
1071  }
1072  cairo_paint(d);
1073  cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1074  } else {
1075  // Paint the background transparent.
1076  cairo_set_source_rgba(d, 0, 0, 0, 0.0);
1077  cairo_paint(d);
1078  }
1079  TICK_N("Background");
1080 
1081  // Always paint as overlay over the background.
1082  cairo_set_operator(d, CAIRO_OPERATOR_OVER);
1083  widget_draw(WIDGET(state->main_window), d);
1084 
1085  TICK_N("widgets");
1086  cairo_surface_flush(CacheState.edit_surf);
1087  if (qr) {
1089  }
1090 }
1091 
1093  g_free(state->line_map);
1094  g_free(state->distance);
1095  state->num_lines = mode_get_num_entries(state->sw);
1096  state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
1097  state->distance = g_malloc0_n(state->num_lines, sizeof(int));
1098  listview_set_max_lines(state->list_view, state->num_lines);
1100 }
1101 
1102 static void rofi_view_refilter(RofiViewState *state) {
1103  if (state->sw == NULL) {
1104  return;
1105  }
1106  TICK_N("Filter start");
1107  if (state->reload) {
1108  _rofi_view_reload_row(state);
1109  state->reload = FALSE;
1110  }
1111  TICK_N("Filter reload rows");
1112  if (state->tokens) {
1113  helper_tokenize_free(state->tokens);
1114  state->tokens = NULL;
1115  }
1116  TICK_N("Filter tokenize");
1117  if (state->text && strlen(state->text->text) > 0) {
1118  unsigned int j = 0;
1119  gchar *pattern = mode_preprocess_input(state->sw, state->text->text);
1120  glong plen = pattern ? g_utf8_strlen(pattern, -1) : 0;
1121  state->tokens = helper_tokenize(pattern, config.case_sensitive);
1129  unsigned int nt = MAX(1, state->num_lines / 500);
1130  thread_state_view states[nt];
1131  GCond cond;
1132  GMutex mutex;
1133  g_mutex_init(&mutex);
1134  g_cond_init(&cond);
1135  unsigned int count = nt;
1136  unsigned int steps = (state->num_lines + nt) / nt;
1137  for (unsigned int i = 0; i < nt; i++) {
1138  states[i].state = state;
1139  states[i].start = i * steps;
1140  states[i].stop = MIN(state->num_lines, (i + 1) * steps);
1141  states[i].count = 0;
1142  states[i].cond = &cond;
1143  states[i].mutex = &mutex;
1144  states[i].acount = &count;
1145  states[i].plen = plen;
1146  states[i].pattern = pattern;
1147  states[i].st.callback = filter_elements;
1148  if (i > 0) {
1149  g_thread_pool_push(tpool, &states[i], NULL);
1150  }
1151  }
1152  // Run one in this thread.
1153  rofi_view_call_thread(&states[0], NULL);
1154  // No need to do this with only one thread.
1155  if (nt > 1) {
1156  g_mutex_lock(&mutex);
1157  while (count > 0) {
1158  g_cond_wait(&cond, &mutex);
1159  }
1160  g_mutex_unlock(&mutex);
1161  }
1162  g_cond_clear(&cond);
1163  g_mutex_clear(&mutex);
1164  for (unsigned int i = 0; i < nt; i++) {
1165  if (j != states[i].start) {
1166  memmove(&(state->line_map[j]), &(state->line_map[states[i].start]),
1167  sizeof(unsigned int) * (states[i].count));
1168  }
1169  j += states[i].count;
1170  }
1171  if (config.sort) {
1172  g_qsort_with_data(state->line_map, j, sizeof(int), lev_sort,
1173  state->distance);
1174  }
1175 
1176  // Cleanup + bookkeeping.
1177  state->filtered_lines = j;
1178  g_free(pattern);
1179  } else {
1180  for (unsigned int i = 0; i < state->num_lines; i++) {
1181  state->line_map[i] = i;
1182  }
1183  state->filtered_lines = state->num_lines;
1184  }
1185  TICK_N("Filter matching done");
1187 
1188  if (state->tb_filtered_rows) {
1189  char *r = g_strdup_printf("%u", state->filtered_lines);
1190  textbox_text(state->tb_filtered_rows, r);
1191  g_free(r);
1192  }
1193  if (state->tb_total_rows) {
1194  char *r = g_strdup_printf("%u", state->num_lines);
1195  textbox_text(state->tb_total_rows, r);
1196  g_free(r);
1197  }
1198  TICK_N("Update filter lines");
1199 
1200  if (config.auto_select == TRUE && state->filtered_lines == 1 &&
1201  state->num_lines > 1) {
1202  (state->selected_line) =
1203  state->line_map[listview_get_selected(state->list_view)];
1204  state->retv = MENU_OK;
1205  state->quit = TRUE;
1206  }
1207 
1208  // Size the window.
1209  int height = rofi_view_calculate_height(state);
1210  if (height != state->height) {
1211  state->height = height;
1214  g_debug("Resize based on re-filter");
1215  }
1216  TICK_N("Filter resize window based on window ");
1217  state->refilter = FALSE;
1218  TICK_N("Filter done");
1219 }
1225 void process_result(RofiViewState *state);
1227  if (state && state->finalize != NULL) {
1228  state->finalize(state);
1229  }
1230 }
1231 
1234  switch (action) {
1235  // Handling of paste
1236  case PASTE_PRIMARY:
1237  xcb_convert_selection(xcb->connection, CacheState.main_window,
1238  XCB_ATOM_PRIMARY, xcb->ewmh.UTF8_STRING,
1239  xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1240  xcb_flush(xcb->connection);
1241  break;
1242  case PASTE_SECONDARY:
1243  xcb_convert_selection(xcb->connection, CacheState.main_window,
1244  netatoms[CLIPBOARD], xcb->ewmh.UTF8_STRING,
1245  xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME);
1246  xcb_flush(xcb->connection);
1247  break;
1248  case SCREENSHOT:
1250  break;
1251  case CHANGE_ELLIPSIZE:
1252  if (state->list_view) {
1254  }
1255  break;
1256  case TOGGLE_SORT:
1257  if (state->case_indicator != NULL) {
1258  config.sort = !config.sort;
1259  state->refilter = TRUE;
1261  }
1262  break;
1263  case MODE_PREVIOUS:
1264  state->retv = MENU_PREVIOUS;
1265  (state->selected_line) = 0;
1266  state->quit = TRUE;
1267  break;
1268  // Menu navigation.
1269  case MODE_NEXT:
1270  state->retv = MENU_NEXT;
1271  (state->selected_line) = 0;
1272  state->quit = TRUE;
1273  break;
1274  case MODE_COMPLETE: {
1275  unsigned int selected = listview_get_selected(state->list_view);
1276  state->selected_line = UINT32_MAX;
1277  if (selected < state->filtered_lines) {
1278  state->selected_line = state->line_map[selected];
1279  }
1280  state->retv = MENU_COMPLETE;
1281  state->quit = TRUE;
1282  break;
1283  }
1284  // Toggle case sensitivity.
1286  if (state->case_indicator != NULL) {
1288  (state->selected_line) = 0;
1289  state->refilter = TRUE;
1291  }
1292  break;
1293  // Special delete entry command.
1294  case DELETE_ENTRY: {
1295  unsigned int selected = listview_get_selected(state->list_view);
1296  if (selected < state->filtered_lines) {
1297  (state->selected_line) = state->line_map[selected];
1298  state->retv = MENU_ENTRY_DELETE;
1299  state->quit = TRUE;
1300  }
1301  break;
1302  }
1303  case SELECT_ELEMENT_1:
1304  case SELECT_ELEMENT_2:
1305  case SELECT_ELEMENT_3:
1306  case SELECT_ELEMENT_4:
1307  case SELECT_ELEMENT_5:
1308  case SELECT_ELEMENT_6:
1309  case SELECT_ELEMENT_7:
1310  case SELECT_ELEMENT_8:
1311  case SELECT_ELEMENT_9:
1312  case SELECT_ELEMENT_10: {
1313  unsigned int index = action - SELECT_ELEMENT_1;
1314  if (index < state->filtered_lines) {
1315  state->selected_line = state->line_map[index];
1316  state->retv = MENU_OK;
1317  state->quit = TRUE;
1318  }
1319  break;
1320  }
1321  case CUSTOM_1:
1322  case CUSTOM_2:
1323  case CUSTOM_3:
1324  case CUSTOM_4:
1325  case CUSTOM_5:
1326  case CUSTOM_6:
1327  case CUSTOM_7:
1328  case CUSTOM_8:
1329  case CUSTOM_9:
1330  case CUSTOM_10:
1331  case CUSTOM_11:
1332  case CUSTOM_12:
1333  case CUSTOM_13:
1334  case CUSTOM_14:
1335  case CUSTOM_15:
1336  case CUSTOM_16:
1337  case CUSTOM_17:
1338  case CUSTOM_18:
1339  case CUSTOM_19: {
1340  state->selected_line = UINT32_MAX;
1341  unsigned int selected = listview_get_selected(state->list_view);
1342  if (selected < state->filtered_lines) {
1343  (state->selected_line) = state->line_map[selected];
1344  }
1345  state->retv = MENU_CUSTOM_COMMAND | ((action - CUSTOM_1) & MENU_LOWER_MASK);
1346  state->quit = TRUE;
1347  break;
1348  }
1349  // If you add a binding here, make sure to add it to
1350  // rofi_view_keyboard_navigation too
1351  case CANCEL:
1352  state->retv = MENU_CANCEL;
1353  state->quit = TRUE;
1354  break;
1355  case ROW_UP:
1356  listview_nav_up(state->list_view);
1357  break;
1358  case ROW_TAB:
1359  rofi_view_nav_row_tab(state);
1360  break;
1361  case ROW_DOWN:
1362  listview_nav_down(state->list_view);
1363  break;
1364  case ROW_LEFT:
1365  listview_nav_left(state->list_view);
1366  break;
1367  case ROW_RIGHT:
1368  listview_nav_right(state->list_view);
1369  break;
1370  case PAGE_PREV:
1372  break;
1373  case PAGE_NEXT:
1375  break;
1376  case ROW_FIRST:
1377  rofi_view_nav_first(state);
1378  break;
1379  case ROW_LAST:
1380  rofi_view_nav_last(state);
1381  break;
1382  case ROW_SELECT:
1383  rofi_view_nav_row_select(state);
1384  break;
1385  // If you add a binding here, make sure to add it to textbox_keybinding too
1386  case MOVE_CHAR_BACK: {
1387  if (textbox_keybinding(state->text, action) == 0) {
1388  listview_nav_left(state->list_view);
1389  }
1390  break;
1391  }
1392  case MOVE_CHAR_FORWARD: {
1393  if (textbox_keybinding(state->text, action) == 0) {
1394  listview_nav_right(state->list_view);
1395  }
1396  break;
1397  }
1398  case CLEAR_LINE:
1399  case MOVE_FRONT:
1400  case MOVE_END:
1401  case REMOVE_TO_EOL:
1402  case REMOVE_TO_SOL:
1403  case REMOVE_WORD_BACK:
1404  case REMOVE_WORD_FORWARD:
1405  case REMOVE_CHAR_FORWARD:
1406  case MOVE_WORD_BACK:
1407  case MOVE_WORD_FORWARD:
1408  case REMOVE_CHAR_BACK: {
1409  int rc = textbox_keybinding(state->text, action);
1410  if (rc == 1) {
1411  // Entry changed.
1412  state->refilter = TRUE;
1413  } else if (rc == 2) {
1414  // Movement.
1415  }
1416  break;
1417  }
1418  case ACCEPT_ALT: {
1419  unsigned int selected = listview_get_selected(state->list_view);
1420  state->selected_line = UINT32_MAX;
1421  if (selected < state->filtered_lines) {
1422  (state->selected_line) = state->line_map[selected];
1423  state->retv = MENU_OK;
1424  } else {
1425  // Nothing entered and nothing selected.
1426  state->retv = MENU_CUSTOM_INPUT;
1427  }
1428  state->retv |= MENU_CUSTOM_ACTION;
1429  state->quit = TRUE;
1430  break;
1431  }
1432  case ACCEPT_CUSTOM: {
1433  state->selected_line = UINT32_MAX;
1434  state->retv = MENU_CUSTOM_INPUT;
1435  state->quit = TRUE;
1436  break;
1437  }
1438  case ACCEPT_CUSTOM_ALT: {
1439  state->selected_line = UINT32_MAX;
1441  state->quit = TRUE;
1442  break;
1443  }
1444  case ACCEPT_ENTRY: {
1445  // If a valid item is selected, return that..
1446  unsigned int selected = listview_get_selected(state->list_view);
1447  state->selected_line = UINT32_MAX;
1448  if (selected < state->filtered_lines) {
1449  (state->selected_line) = state->line_map[selected];
1450  state->retv = MENU_OK;
1451  } else {
1452  // Nothing entered and nothing selected.
1453  state->retv = MENU_CUSTOM_INPUT;
1454  }
1455 
1456  state->quit = TRUE;
1457  break;
1458  }
1459  }
1460 }
1461 
1463  guint action) {
1465  switch (scope) {
1466  case SCOPE_GLOBAL:
1468  return TRUE;
1469  case SCOPE_MOUSE_LISTVIEW:
1471  case SCOPE_MOUSE_EDITBOX:
1472  case SCOPE_MOUSE_SCROLLBAR:
1474  gint x = state->mouse.x, y = state->mouse.y;
1476  (WidgetType)scope, x, y);
1477  if (target == NULL) {
1478  return FALSE;
1479  }
1480  widget_xy_to_relative(target, &x, &y);
1481  switch (widget_trigger_action(target, action, x, y)) {
1483  return FALSE;
1485  target = NULL;
1486  /* FALLTHRU */
1488  state->mouse.motion_target = target;
1489  /* FALLTHRU */
1491  return TRUE;
1492  }
1493  break;
1494  }
1495  }
1496  return FALSE;
1497 }
1498 
1499 void rofi_view_handle_text(RofiViewState *state, char *text) {
1500  if (textbox_append_text(state->text, text, strlen(text))) {
1501  state->refilter = TRUE;
1502  }
1503 }
1504 
1506  switch (type) {
1507  case ROFI_CURSOR_DEFAULT:
1508  return CURSOR_DEFAULT;
1509 
1510  case ROFI_CURSOR_POINTER:
1511  return CURSOR_POINTER;
1512 
1513  case ROFI_CURSOR_TEXT:
1514  return CURSOR_TEXT;
1515  }
1516 
1517  return CURSOR_DEFAULT;
1518 }
1519 
1521  gint y) {
1523  WIDGET_TYPE_UNKNOWN, x, y);
1524 
1525  return target != NULL ? target->cursor_type : ROFI_CURSOR_DEFAULT;
1526 }
1527 
1530 
1531  if (x11_type == CacheState.cursor_type) {
1532  return;
1533  }
1534 
1535  CacheState.cursor_type = x11_type;
1536 
1537  x11_set_cursor(CacheState.main_window, x11_type);
1538 }
1539 
1540 void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y,
1541  gboolean find_mouse_target) {
1542  state->mouse.x = x;
1543  state->mouse.y = y;
1544 
1546 
1548 
1549  if (find_mouse_target) {
1550  widget *target = widget_find_mouse_target(
1552 
1553  if (target != NULL) {
1554  state->mouse.motion_target = target;
1555  }
1556  }
1557 
1558  if (state->mouse.motion_target != NULL) {
1559  widget_xy_to_relative(state->mouse.motion_target, &x, &y);
1561 
1562  if (find_mouse_target) {
1563  state->mouse.motion_target = NULL;
1564  }
1565  }
1566 }
1567 
1569  if (rofi_view_get_completed(state)) {
1570  // This menu is done.
1571  rofi_view_finalize(state);
1572  // If there a state. (for example error) reload it.
1573  state = rofi_view_get_active();
1574 
1575  // cleanup, if no more state to display.
1576  if (state == NULL) {
1577  // Quit main-loop.
1579  return;
1580  }
1581  }
1582 
1583  // Update if requested.
1584  if (state->refilter) {
1585  rofi_view_refilter(state);
1586  }
1587  rofi_view_update(state, TRUE);
1588 }
1589 
1595  xcb_configure_notify_event_t *xce) {
1596  if (xce->window == CacheState.main_window) {
1597  if (state->x != xce->x || state->y != xce->y) {
1598  state->x = xce->x;
1599  state->y = xce->y;
1601  }
1602  if (state->width != xce->width || state->height != xce->height) {
1603  state->width = xce->width;
1604  state->height = xce->height;
1605 
1606  cairo_destroy(CacheState.edit_draw);
1607  cairo_surface_destroy(CacheState.edit_surf);
1608 
1609  xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
1610  CacheState.edit_pixmap = xcb_generate_id(xcb->connection);
1611  xcb_create_pixmap(xcb->connection, depth->depth, CacheState.edit_pixmap,
1612  CacheState.main_window, state->width, state->height);
1613 
1614  CacheState.edit_surf =
1615  cairo_xcb_surface_create(xcb->connection, CacheState.edit_pixmap,
1616  visual, state->width, state->height);
1617  CacheState.edit_draw = cairo_create(CacheState.edit_surf);
1618  g_debug("Re-size window based external request: %d %d", state->width,
1619  state->height);
1620  widget_resize(WIDGET(state->main_window), state->width, state->height);
1621  }
1622  }
1623 }
1624 
1628 void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target) {
1629  if ((CacheState.flags & MENU_NORMAL_WINDOW) == 0) {
1630  if (target != CacheState.main_window) {
1631  state->quit = TRUE;
1632  state->retv = MENU_CANCEL;
1633  }
1634  }
1635 }
1636 
1638  if (CacheState.repaint_source == 0) {
1639  CacheState.repaint_source =
1640  g_idle_add_full(G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL);
1641  }
1642 }
1643 
1645  if (CacheState.fullscreen == TRUE) {
1646  return CacheState.mon.h;
1647  }
1648 
1649  RofiDistance h =
1650  rofi_theme_get_distance(WIDGET(state->main_window), "height", 0);
1651  unsigned int height = distance_get_pixel(h, ROFI_ORIENTATION_VERTICAL);
1652  // If height is set, return it.
1653  if (height > 0) {
1654  return height;
1655  }
1656  // Autosize based on widgets.
1657  widget *main_window = WIDGET(state->main_window);
1659 }
1660 
1662  widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1663  G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1664  RofiViewState *state = (RofiViewState *)user_data;
1665  switch (action) {
1666  case MOUSE_CLICK_DOWN: {
1667  const char *type = rofi_theme_get_string(wid, "action", NULL);
1668  if (type) {
1669  (state->selected_line) =
1670  state->line_map[listview_get_selected(state->list_view)];
1671  guint id = key_binding_get_action_from_name(type);
1672  if (id != UINT32_MAX) {
1674  }
1675  state->skip_absorb = TRUE;
1677  }
1678  }
1679  case MOUSE_CLICK_UP:
1680  case MOUSE_DCLICK_DOWN:
1681  case MOUSE_DCLICK_UP:
1682  break;
1683  }
1685 }
1687  widget *wid, MouseBindingMouseDefaultAction action, G_GNUC_UNUSED gint x,
1688  G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data) {
1689  RofiViewState *state = (RofiViewState *)user_data;
1690  unsigned int i;
1691  for (i = 0; i < state->num_modi; i++) {
1692  if (WIDGET(state->modi[i]) == wid) {
1693  break;
1694  }
1695  }
1696  if (i == state->num_modi) {
1698  }
1699 
1700  switch (action) {
1701  case MOUSE_CLICK_DOWN:
1702  state->retv = MENU_QUICK_SWITCH | (i & MENU_LOWER_MASK);
1703  state->quit = TRUE;
1704  state->skip_absorb = TRUE;
1706  case MOUSE_CLICK_UP:
1707  case MOUSE_DCLICK_DOWN:
1708  case MOUSE_DCLICK_UP:
1709  break;
1710  }
1712 }
1713 
1714 // @TODO don't like this construction.
1715 static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom,
1716  void *udata) {
1717  RofiViewState *state = (RofiViewState *)udata;
1718  state->retv = MENU_OK;
1719  if (custom) {
1720  state->retv |= MENU_CUSTOM_ACTION;
1721  }
1722  (state->selected_line) = state->line_map[listview_get_selected(lv)];
1723  // Quit
1724  state->quit = TRUE;
1725  state->skip_absorb = TRUE;
1726 }
1727 
1728 static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget,
1729  const char *name) {
1730  char *defaults = NULL;
1731  widget *wid = NULL;
1732 
1736  if (strcmp(name, "mainbox") == 0) {
1737  wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1738  box_add((box *)parent_widget, WIDGET(wid), TRUE);
1739  if (config.sidebar_mode) {
1740  defaults = "inputbar,message,listview,mode-switcher";
1741  } else {
1742  defaults = "inputbar,message,listview";
1743  }
1744  }
1748  else if (strcmp(name, "inputbar") == 0) {
1749  wid =
1750  (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1751  defaults = "prompt,entry,overlay,case-indicator";
1752  box_add((box *)parent_widget, WIDGET(wid), FALSE);
1753  }
1757  else if (strcmp(name, "prompt") == 0) {
1758  if (state->prompt != NULL) {
1759  g_error("Prompt widget can only be added once to the layout.");
1760  return;
1761  }
1762  // Prompt box.
1763  state->prompt =
1764  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1765  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1766  rofi_view_update_prompt(state);
1767  box_add((box *)parent_widget, WIDGET(state->prompt), FALSE);
1768  defaults = NULL;
1769  } else if (strcmp(name, "num-rows") == 0) {
1770  state->tb_total_rows =
1771  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1772  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1773  box_add((box *)parent_widget, WIDGET(state->tb_total_rows), FALSE);
1774  defaults = NULL;
1775  } else if (strcmp(name, "num-filtered-rows") == 0) {
1776  state->tb_filtered_rows =
1777  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1778  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0);
1779  box_add((box *)parent_widget, WIDGET(state->tb_filtered_rows), FALSE);
1780  defaults = NULL;
1781  }
1785  else if (strcmp(name, "case-indicator") == 0) {
1786  if (state->case_indicator != NULL) {
1787  g_error("Case indicator widget can only be added once to the layout.");
1788  return;
1789  }
1790  state->case_indicator =
1791  textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1792  TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*", 0, 0);
1793  // Add small separator between case indicator and text box.
1794  box_add((box *)parent_widget, WIDGET(state->case_indicator), FALSE);
1796  }
1800  else if (strcmp(name, "entry") == 0) {
1801  if (state->text != NULL) {
1802  g_error("Entry textbox widget can only be added once to the layout.");
1803  return;
1804  }
1805  // Entry box
1806  TextboxFlags tfl = TB_EDITABLE;
1807  tfl |= ((state->menu_flags & MENU_PASSWORD) == MENU_PASSWORD) ? TB_PASSWORD
1808  : 0;
1809  state->text = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1810  tfl | TB_AUTOHEIGHT, NORMAL, NULL, 0, 0);
1811  box_add((box *)parent_widget, WIDGET(state->text), TRUE);
1812  }
1816  else if (strcmp(name, "message") == 0) {
1817  if (state->mesg_box != NULL) {
1818  g_error("Message widget can only be added once to the layout.");
1819  return;
1820  }
1821  state->mesg_box = container_create(parent_widget, name);
1822  state->mesg_tb = textbox_create(
1823  WIDGET(state->mesg_box), WIDGET_TYPE_TEXTBOX_TEXT, "textbox",
1824  TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL, 0, 0);
1825  container_add(state->mesg_box, WIDGET(state->mesg_tb));
1827  box_add((box *)parent_widget, WIDGET(state->mesg_box), FALSE);
1828  }
1832  else if (strcmp(name, "listview") == 0) {
1833  if (state->list_view != NULL) {
1834  g_error("Listview widget can only be added once to the layout.");
1835  return;
1836  }
1837  state->list_view = listview_create(parent_widget, name, update_callback,
1838  state, config.element_height, 0);
1839  box_add((box *)parent_widget, WIDGET(state->list_view), TRUE);
1840  // Set configuration
1842  (state->menu_flags & MENU_INDICATOR) ==
1843  MENU_INDICATOR);
1847 
1848  int lines = rofi_theme_get_integer(WIDGET(state->list_view), "lines",
1850  listview_set_num_lines(state->list_view, lines);
1851  listview_set_max_lines(state->list_view, state->num_lines);
1852  }
1856  else if (strcmp(name, "mode-switcher") == 0 || strcmp(name, "sidebar") == 0) {
1857  if (state->sidebar_bar != NULL) {
1858  g_error("Mode-switcher can only be added once to the layout.");
1859  return;
1860  }
1861  state->sidebar_bar =
1862  box_create(parent_widget, name, ROFI_ORIENTATION_HORIZONTAL);
1863  box_add((box *)parent_widget, WIDGET(state->sidebar_bar), FALSE);
1865  state->modi = g_malloc0(state->num_modi * sizeof(textbox *));
1866  for (unsigned int j = 0; j < state->num_modi; j++) {
1867  const Mode *mode = rofi_get_mode(j);
1868  state->modi[j] = textbox_create(
1869  WIDGET(state->sidebar_bar), WIDGET_TYPE_MODE_SWITCHER, "button",
1870  TB_AUTOHEIGHT, (mode == state->sw) ? HIGHLIGHT : NORMAL,
1871  mode_get_display_name(mode), 0.5, 0.5);
1872  box_add(state->sidebar_bar, WIDGET(state->modi[j]), TRUE);
1874  WIDGET(state->modi[j]), textbox_sidebar_modi_trigger_action, state);
1875  }
1876  } else if (g_ascii_strcasecmp(name, "overlay") == 0) {
1877  state->overlay = textbox_create(
1878  WIDGET(parent_widget), WIDGET_TYPE_TEXTBOX_TEXT, "overlay",
1879  TB_AUTOWIDTH | TB_AUTOHEIGHT, URGENT, "blaat", 0.5, 0);
1880  box_add((box *)parent_widget, WIDGET(state->overlay), FALSE);
1881  widget_disable(WIDGET(state->overlay));
1882  } else if (g_ascii_strncasecmp(name, "textbox", 7) == 0) {
1883  textbox *t = textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name,
1884  TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
1885  box_add((box *)parent_widget, WIDGET(t), TRUE);
1886  } else if (g_ascii_strncasecmp(name, "button", 6) == 0) {
1887  textbox *t = textbox_create(parent_widget, WIDGET_TYPE_EDITBOX, name,
1888  TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0);
1889  box_add((box *)parent_widget, WIDGET(t), TRUE);
1891  state);
1892  } else if (g_ascii_strncasecmp(name, "icon", 4) == 0) {
1893  icon *t = icon_create(parent_widget, name);
1894  /* small hack to make it clickable */
1895  const char *type = rofi_theme_get_string(WIDGET(t), "action", NULL);
1896  if (type) {
1897  WIDGET(t)->type = WIDGET_TYPE_EDITBOX;
1898  }
1899  box_add((box *)parent_widget, WIDGET(t), TRUE);
1901  state);
1902  } else {
1903  wid = (widget *)box_create(parent_widget, name, ROFI_ORIENTATION_VERTICAL);
1904  box_add((box *)parent_widget, WIDGET(wid), TRUE);
1905  // g_error("The widget %s does not exists. Invalid layout.", name);
1906  }
1907  if (wid) {
1908  GList *list = rofi_theme_get_list(wid, "children", defaults);
1909  for (const GList *iter = list; iter != NULL; iter = g_list_next(iter)) {
1910  rofi_view_add_widget(state, wid, (const char *)iter->data);
1911  }
1912  g_list_free_full(list, g_free);
1913  }
1914 }
1915 
1917  xcb_query_pointer_cookie_t pointer_cookie =
1918  xcb_query_pointer(xcb->connection, CacheState.main_window);
1919  xcb_query_pointer_reply_t *pointer_reply =
1920  xcb_query_pointer_reply(xcb->connection, pointer_cookie, NULL);
1921 
1922  if (pointer_reply == NULL) {
1923  return;
1924  }
1925 
1926  rofi_view_handle_mouse_motion(state, pointer_reply->win_x,
1927  pointer_reply->win_y, config.hover_select);
1928 
1929  free(pointer_reply);
1930 }
1931 
1932 RofiViewState *rofi_view_create(Mode *sw, const char *input,
1933  MenuFlags menu_flags,
1934  void (*finalize)(RofiViewState *)) {
1935  TICK();
1937  state->menu_flags = menu_flags;
1938  state->sw = sw;
1939  state->selected_line = UINT32_MAX;
1940  state->retv = MENU_CANCEL;
1941  state->distance = NULL;
1942  state->quit = FALSE;
1943  state->skip_absorb = FALSE;
1944  // We want to filter on the first run.
1945  state->refilter = TRUE;
1946  state->finalize = finalize;
1947  state->mouse_seen = FALSE;
1948 
1949  // Request the lines to show.
1950  state->num_lines = mode_get_num_entries(sw);
1951 
1952  if (state->sw) {
1953  char *title =
1954  g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
1956  g_free(title);
1957  } else {
1959  }
1960  TICK_N("Startup notification");
1961 
1962  // Get active monitor size.
1963  TICK_N("Get active monitor");
1964 
1965  state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
1966  // Get children.
1967  GList *list =
1968  rofi_theme_get_list(WIDGET(state->main_window), "children", "mainbox");
1969  for (const GList *iter = list; iter != NULL; iter = g_list_next(iter)) {
1970  rofi_view_add_widget(state, WIDGET(state->main_window),
1971  (const char *)iter->data);
1972  }
1973  g_list_free_full(list, g_free);
1974 
1975  if (state->text && input) {
1976  textbox_text(state->text, input);
1977  textbox_cursor_end(state->text);
1978  }
1979 
1980  // filtered list
1981  state->line_map = g_malloc0_n(state->num_lines, sizeof(unsigned int));
1982  state->distance = (int *)g_malloc0_n(state->num_lines, sizeof(int));
1983 
1985  // Need to resize otherwise calculated desired height is wrong.
1986  widget_resize(WIDGET(state->main_window), state->width, 100);
1987  // Only needed when window is fixed size.
1990  }
1991 
1992  state->height = rofi_view_calculate_height(state);
1993  // Move the window to the correct x,y position.
1996 
1997  state->quit = FALSE;
1998  rofi_view_refilter(state);
1999  rofi_view_update(state, TRUE);
2000  xcb_map_window(xcb->connection, CacheState.main_window);
2002  rofi_view_ping_mouse(state);
2003  xcb_flush(xcb->connection);
2004 
2006  /* When Override Redirect, the WM will not let us know we can take focus, so
2007  * just steal it */
2008  if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) {
2009  rofi_xcb_set_input_focus(CacheState.main_window);
2010  }
2011 
2012  if (xcb->sncontext != NULL) {
2013  sn_launchee_context_complete(xcb->sncontext);
2014  }
2015  return state;
2016 }
2017 
2018 int rofi_view_error_dialog(const char *msg, int markup) {
2020  state->retv = MENU_CANCEL;
2021  state->menu_flags = MENU_ERROR_DIALOG;
2022  state->finalize = process_result;
2023 
2024  state->main_window = box_create(NULL, "window", ROFI_ORIENTATION_VERTICAL);
2025  box *box = box_create(WIDGET(state->main_window), "error-message",
2027  box_add(state->main_window, WIDGET(box), TRUE);
2028  state->text =
2030  (TB_AUTOHEIGHT | TB_WRAP) + ((markup) ? TB_MARKUP : 0),
2031  NORMAL, (msg != NULL) ? msg : "", 0, 0);
2032  box_add(box, WIDGET(state->text), TRUE);
2033 
2034  // Make sure we enable fixed num lines when in normal window mode.
2037  }
2039  // Need to resize otherwise calculated desired height is wrong.
2040  widget_resize(WIDGET(state->main_window), state->width, 100);
2041  // resize window vertically to suit
2043 
2044  // Calculate window position.
2046 
2047  // Move the window to the correct x,y position.
2049 
2050  // Display it.
2051  xcb_map_window(xcb->connection, CacheState.main_window);
2053 
2054  if (xcb->sncontext != NULL) {
2055  sn_launchee_context_complete(xcb->sncontext);
2056  }
2057 
2058  // Set it as current window.
2059  rofi_view_set_active(state);
2060  return TRUE;
2061 }
2062 
2063 void rofi_view_hide(void) {
2064  if (CacheState.main_window != XCB_WINDOW_NONE) {
2066  xcb_unmap_window(xcb->connection, CacheState.main_window);
2068  }
2069 }
2070 
2072  g_debug("Cleanup.");
2073  if (CacheState.idle_timeout > 0) {
2074  g_source_remove(CacheState.idle_timeout);
2075  CacheState.idle_timeout = 0;
2076  }
2077  if (CacheState.user_timeout > 0) {
2078  g_source_remove(CacheState.user_timeout);
2079  CacheState.user_timeout = 0;
2080  }
2081  if (CacheState.repaint_source > 0) {
2082  g_source_remove(CacheState.repaint_source);
2083  CacheState.repaint_source = 0;
2084  }
2085  if (CacheState.fake_bg) {
2086  cairo_surface_destroy(CacheState.fake_bg);
2087  CacheState.fake_bg = NULL;
2088  }
2089  if (CacheState.edit_draw) {
2090  cairo_destroy(CacheState.edit_draw);
2091  CacheState.edit_draw = NULL;
2092  }
2093  if (CacheState.edit_surf) {
2094  cairo_surface_destroy(CacheState.edit_surf);
2095  CacheState.edit_surf = NULL;
2096  }
2097  if (CacheState.main_window != XCB_WINDOW_NONE) {
2098  g_debug("Unmapping and free'ing window");
2099  xcb_unmap_window(xcb->connection, CacheState.main_window);
2101  xcb_free_gc(xcb->connection, CacheState.gc);
2102  xcb_free_pixmap(xcb->connection, CacheState.edit_pixmap);
2103  xcb_destroy_window(xcb->connection, CacheState.main_window);
2104  CacheState.main_window = XCB_WINDOW_NONE;
2105  }
2106  if (map != XCB_COLORMAP_NONE) {
2107  xcb_free_colormap(xcb->connection, map);
2108  map = XCB_COLORMAP_NONE;
2109  }
2110  xcb_flush(xcb->connection);
2111  g_assert(g_queue_is_empty(&(CacheState.views)));
2112 }
2114  TICK_N("Setup Threadpool, start");
2115  if (config.threads == 0) {
2116  config.threads = 1;
2117  long procs = sysconf(_SC_NPROCESSORS_CONF);
2118  if (procs > 0) {
2119  config.threads = MIN(procs, 128l);
2120  }
2121  }
2122  // Create thread pool
2123  GError *error = NULL;
2124  tpool = g_thread_pool_new(rofi_view_call_thread, NULL, config.threads, FALSE,
2125  &error);
2126  if (error == NULL) {
2127  // Idle threads should stick around for a max of 60 seconds.
2128  g_thread_pool_set_max_idle_time(60000);
2129  // We are allowed to have
2130  g_thread_pool_set_max_threads(tpool, config.threads, &error);
2131  }
2132  // If error occurred during setup of pool, tell user and exit.
2133  if (error != NULL) {
2134  g_warning("Failed to setup thread pool: '%s'", error->message);
2135  g_error_free(error);
2136  exit(EXIT_FAILURE);
2137  }
2138  TICK_N("Setup Threadpool, done");
2139 }
2141  if (tpool) {
2142  g_thread_pool_free(tpool, TRUE, TRUE);
2143  tpool = NULL;
2144  }
2145 }
2146 Mode *rofi_view_get_mode(RofiViewState *state) { return state->sw; }
2147 
2148 void rofi_view_set_overlay(RofiViewState *state, const char *text) {
2149  if (state->overlay == NULL || state->list_view == NULL) {
2150  return;
2151  }
2152  if (text == NULL) {
2153  widget_disable(WIDGET(state->overlay));
2154  return;
2155  }
2156  widget_enable(WIDGET(state->overlay));
2157  textbox_text(state->overlay, text);
2158  // We want to queue a repaint.
2160 }
2161 
2163  if (state->text) {
2164  textbox_text(state->text, "");
2165  rofi_view_set_selected_line(state, 0);
2166  }
2167 }
2168 
2171 }
2172 
2174  state->sw = mode;
2175  // Update prompt;
2176  if (state->prompt) {
2177  rofi_view_update_prompt(state);
2178  }
2179  if (state->sw) {
2180  char *title =
2181  g_strdup_printf("rofi - %s", mode_get_display_name(state->sw));
2183  g_free(title);
2184  } else {
2186  }
2187  if (state->sidebar_bar) {
2188  for (unsigned int j = 0; j < state->num_modi; j++) {
2189  const Mode *tb_mode = rofi_get_mode(j);
2190  textbox_font(state->modi[j], (tb_mode == state->sw) ? HIGHLIGHT : NORMAL);
2191  }
2192  }
2193  rofi_view_restart(state);
2194  state->reload = TRUE;
2195  state->refilter = TRUE;
2196  rofi_view_refilter(state);
2197  rofi_view_update(state, TRUE);
2198 }
2199 
2200 xcb_window_t rofi_view_get_window(void) { return CacheState.main_window; }
2201 
2202 void rofi_view_set_window_title(const char *title) {
2203  ssize_t len = strlen(title);
2204  xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
2205  CacheState.main_window, xcb->ewmh._NET_WM_NAME,
2206  xcb->ewmh.UTF8_STRING, 8, len, title);
2207  xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
2208  CacheState.main_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
2209  8, len, title);
2210 }
@ WL_SOUTH_EAST
Definition: rofi-types.h:244
@ WL_CENTER
Definition: rofi-types.h:230
@ WL_NORTH_WEST
Definition: rofi-types.h:240
@ WL_SOUTH
Definition: rofi-types.h:236
@ WL_NORTH_EAST
Definition: rofi-types.h:242
@ WL_WEST
Definition: rofi-types.h:238
@ WL_NORTH
Definition: rofi-types.h:232
@ WL_EAST
Definition: rofi-types.h:234
@ WL_SOUTH_WEST
Definition: rofi-types.h:246
PangoAttrList * helper_token_match_get_pango_attr(RofiHighlightColorStyle th, rofi_int_matcher **tokens, const char *input, PangoAttrList *retv)
Definition: helper.c:417
gboolean helper_validate_font(PangoFontDescription *pfd, const char *font)
Definition: helper.c:584
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:745
int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, glong slen)
Definition: helper.c:902
char * rofi_expand_path(const char *input)
Definition: helper.c:713
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition: helper.c:262
guint key_binding_get_action_from_name(const char *name)
Definition: keyb.c:150
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:665
#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:239
TextboxFlags
Definition: textbox.h:89
int textbox_keybinding(textbox *tb, KeyBindingAction action)
Definition: textbox.c:713
TextBoxFontType
Definition: textbox.h:101
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
Definition: textbox.c:303
const char * textbox_get_visible_text(const textbox *tb)
Definition: textbox.c:291
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
Definition: textbox.c:297
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
Definition: textbox.c:158
void textbox_set_pango_context(const char *font, PangoContext *p)
Definition: textbox.c:813
void textbox_cursor_end(textbox *tb)
Definition: textbox.c:585
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
Definition: textbox.c:775
void textbox_text(textbox *tb, const char *text)
Definition: textbox.c:311
@ 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:2071
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition: view.c:2148
void __create_window(MenuFlags menu_flags)
Definition: view.c:751
void rofi_view_clear_input(RofiViewState *state)
Definition: view.c:2162
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition: view.c:2173
void rofi_view_hide(void)
Definition: view.c:2063
void rofi_view_reload(void)
Definition: view.c:497
Mode * rofi_view_get_mode(RofiViewState *state)
Definition: view.c:2146
xcb_window_t rofi_view_get_window(void)
Definition: view.c:2200
void rofi_view_remove_active(RofiViewState *state)
Definition: view.c:520
RofiViewState * rofi_view_get_active(void)
Definition: view.c:518
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:2018
void rofi_view_set_active(RofiViewState *state)
Definition: view.c:527
void rofi_view_queue_redraw(void)
Definition: view.c:504
void rofi_view_restart(RofiViewState *state)
Definition: view.c:513
MenuFlags
Definition: view.h:48
void rofi_view_handle_text(RofiViewState *state, char *text)
Definition: view.c:1499
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition: view.c:586
unsigned int rofi_view_get_completed(const RofiViewState *state)
Definition: view.c:603
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
Definition: view.c:1540
gboolean rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1462
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
Definition: view.c:1628
void rofi_view_finalize(RofiViewState *state)
Definition: view.c:1226
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition: view.c:550
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
Definition: view.c:1594
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition: view.c:1932
void rofi_view_frame_callback(void)
Definition: view.c:1637
void rofi_view_free(RofiViewState *state)
Definition: view.c:568
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition: view.c:607
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition: view.c:590
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition: view.c:594
void rofi_view_maybe_update(RofiViewState *state)
Definition: view.c:1568
@ 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:2169
void rofi_capture_screenshot(void)
Definition: view.c:174
void rofi_view_workers_initialize(void)
Definition: view.c:2113
void rofi_view_set_window_title(const char *title)
Definition: view.c:2202
void rofi_view_get_current_monitor(int *width, int *height)
Definition: view.c:139
void rofi_view_workers_finalize(void)
Definition: view.c:2140
void box_add(box *box, widget *child, gboolean expand)
Definition: box.c:285
box * box_create(widget *parent, const char *name, RofiOrientation type)
Definition: box.c:345
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:138
icon * icon_create(widget *parent, const char *name)
Definition: icon.c:151
void listview_nav_page_next(listview *lv)
Definition: listview.c:869
void listview_set_fixed_num_lines(listview *lv)
Definition: listview.c:963
void listview_set_num_lines(listview *lv, unsigned int num_lines)
Definition: listview.c:939
void listview_set_num_elements(listview *lv, unsigned int rows)
Definition: listview.c:516
listview * listview_create(widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse)
Definition: listview.c:660
void listview_nav_right(listview *lv)
Definition: listview.c:786
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
Definition: listview.c:926
void listview_toggle_ellipsizing(listview *lv)
Definition: listview.c:978
void listview_set_selected(listview *lv, unsigned int selected)
Definition: listview.c:537
void listview_set_max_lines(listview *lv, unsigned int max_lines)
Definition: listview.c:951
void listview_nav_left(listview *lv)
Definition: listview.c:773
void listview_set_scroll_type(listview *lv, ScrollType type)
Definition: listview.c:920
gboolean listview_get_fixed_num_lines(listview *lv)
Definition: listview.c:957
void listview_set_ellipsize_start(listview *lv)
Definition: listview.c:969
unsigned int listview_get_selected(listview *lv)
Definition: listview.c:530
void listview_set_multi_select(listview *lv, gboolean enable)
Definition: listview.c:934
void listview_nav_up(listview *lv)
Definition: listview.c:752
void listview_nav_page_prev(listview *lv)
Definition: listview.c:859
void listview_nav_down(listview *lv)
Definition: listview.c:762
WidgetTriggerActionResult widget_trigger_action(widget *wid, guint action, gint x, gint y)
Definition: widget.c:551
void widget_queue_redraw(widget *wid)
Definition: widget.c:509
int widget_get_desired_height(widget *wid)
Definition: widget.c:649
void widget_free(widget *wid)
Definition: widget.c:447
static void widget_disable(widget *widget)
Definition: widget.h:178
void widget_resize(widget *widget, short w, short h)
Definition: widget.c:102
WidgetType
Definition: widget.h:56
static void widget_enable(widget *widget)
Definition: widget.h:186
void widget_draw(widget *widget, cairo_t *d)
Definition: widget.c:157
void widget_xy_to_relative(widget *widget, gint *x, gint *y)
Definition: widget.c:490
#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:532
void widget_set_trigger_action_handler(widget *wid, widget_trigger_action_cb cb, void *cb_data)
Definition: widget.c:562
gboolean widget_motion_notify(widget *wid, gint x, gint y)
Definition: widget.c:571
gboolean widget_need_redraw(widget *wid)
Definition: widget.c:522
@ 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:136
@ ROFI_ORIENTATION_VERTICAL
Definition: rofi-types.h:135
RofiCursorType
Definition: rofi-types.h:142
@ ROFI_CURSOR_POINTER
Definition: rofi-types.h:144
@ ROFI_CURSOR_TEXT
Definition: rofi-types.h:145
@ ROFI_CURSOR_DEFAULT
Definition: rofi-types.h:143
@ 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:181
#define DEFAULT_MENU_WIDTH
Definition: settings.h:185
@ SORT_FZF
Definition: settings.h:49
@ SORT_NORMAL
Definition: settings.h:49
PropertyValue value
Definition: rofi-types.h:290
PropertyType type
Definition: rofi-types.h:288
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:171
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:647
unsigned int count
Definition: view.c:644
GMutex * mutex
Definition: view.c:633
unsigned int stop
Definition: view.c:642
thread_state st
Definition: view.c:628
RofiViewState * state
Definition: view.c:638
unsigned int * acount
Definition: view.c:635
unsigned int start
Definition: view.c:640
GCond * cond
Definition: view.c:631
void(* callback)(struct _thread_state *t, gpointer data)
Definition: rofi-types.h:314
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
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:830
ThemeWidget * rofi_config_find_widget(const char *name, const char *state, gboolean exact)
Definition: theme.c:732
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition: theme.c:856
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:1282
Property * rofi_theme_find_property(ThemeWidget *widget, PropertyType type, const char *property, gboolean exact)
Definition: theme.c:694
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition: theme.c:1205
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition: theme.c:793
GList * rofi_theme_get_list(const widget *widget, const char *property, const char *defaults)
Definition: theme.c:1176
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition: theme.c:768
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition: theme.c:941
static void rofi_view_call_thread(gpointer data, gpointer user_data)
Definition: view.c:657
cairo_surface_t * fake_bg
Definition: view.c:95
static void rofi_view_nav_last(RofiViewState *state)
Definition: view.c:996
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:1661
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:477
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:619
guint idle_timeout
Definition: view.c:113
static void rofi_view_nav_row_select(RofiViewState *state)
Definition: view.c:966
GQueue views
Definition: view.c:109
static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom, void *udata)
Definition: view.c:1715
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:1728
static void update_callback(textbox *t, icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full)
Definition: view.c:1005
static void rofi_view_nav_row_tab(RofiViewState *state)
Definition: view.c:942
static void rofi_view_setup_fake_transparency(widget *win, const char *const fake_background)
Definition: view.c:698
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:986
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:1056
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:1232
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:662
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:458
static void rofi_view_refilter(RofiViewState *state)
Definition: view.c:1102
X11CursorType cursor_type
Definition: view.c:123
static int rofi_view_calculate_height(RofiViewState *state)
Definition: view.c:1644
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:1686
double last_ts
Definition: view.c:238
static void rofi_view_set_cursor(RofiCursorType type)
Definition: view.c:1528
static void rofi_view_ping_mouse(RofiViewState *state)
Definition: view.c:1916
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:920
static X11CursorType rofi_cursor_type_to_x11_cursor_type(RofiCursorType type)
Definition: view.c:1505
static RofiCursorType rofi_view_resolve_cursor(RofiViewState *state, gint x, gint y)
Definition: view.c:1520
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:1092
guint repaint_source
Definition: view.c:119
xcb_colormap_t map
Definition: xcb.c:95
int monitor_active(workarea *mon)
Definition: xcb.c:937
void display_early_cleanup(void)
Definition: xcb.c:1636
cairo_surface_t * x11_helper_get_screenshot_surface(void)
Definition: xcb.c:334
xcb_stuff * xcb
Definition: xcb.c:88
xcb_depth_t * depth
Definition: xcb.c:93
void rofi_xcb_revert_input_focus(void)
Definition: xcb.c:1250
void rofi_xcb_set_input_focus(xcb_window_t w)
Definition: xcb.c:1227
void x11_set_cursor(xcb_window_t window, X11CursorType type)
Definition: xcb.c:1693
cairo_surface_t * x11_helper_get_bg_surface(void)
Definition: xcb.c:360
xcb_window_t xcb_stuff_get_root_window(void)
Definition: xcb.c:1634
void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count)
Definition: xcb.c:400
void cairo_image_surface_blur(cairo_surface_t *surface, double radius, double deviation)
Definition: xcb.c:164
void x11_disable_decoration(xcb_window_t window)
Definition: xcb.c:1669
xcb_atom_t netatoms[NUM_NETATOMS]
Definition: xcb.c:100
xcb_visualtype_t * visual
Definition: xcb.c:94
X11CursorType
Definition: xcb.h:174
@ CURSOR_POINTER
Definition: xcb.h:178
@ CURSOR_DEFAULT
Definition: xcb.h:176
@ CURSOR_TEXT
Definition: xcb.h:180