rofi  1.5.1
view.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2017 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 <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <stdint.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <time.h>
40 #include <locale.h>
41 #include <xkbcommon/xkbcommon-x11.h>
42 #include <xcb/xkb.h>
43 #include <xcb/xcb_ewmh.h>
44 #include <xcb/xcb_icccm.h>
45 
46 #include <cairo.h>
47 #include <cairo-xcb.h>
48 
49 #define SN_API_NOT_YET_FROZEN
50 #include <libsn/sn.h>
51 #include "rofi.h"
52 
53 #include "timings.h"
54 #include "settings.h"
55 
56 #include "mode.h"
57 #include "display.h"
58 #include "xcb-internal.h"
59 #include "helper.h"
60 #include "helper-theme.h"
61 #include "xrmoptions.h"
62 #include "dialogs/dialogs.h"
63 
64 #include "view.h"
65 #include "view-internal.h"
66 
67 #include "theme.h"
68 
69 #include "xcb.h"
70 
77 void rofi_view_update ( RofiViewState *state, gboolean qr );
78 
79 static int rofi_view_calculate_height ( RofiViewState *state );
80 
82 GThreadPool *tpool = NULL;
83 
86 
90 struct
91 {
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;
115  unsigned long long count;
119  gboolean fullscreen;
120 } CacheState = {
121  .main_window = XCB_WINDOW_NONE,
122  .fake_bg = NULL,
123  .edit_surf = NULL,
124  .edit_draw = NULL,
125  .fake_bgrel = FALSE,
126  .flags = MENU_NORMAL,
127  .views = G_QUEUE_INIT,
128  .idle_timeout = 0,
129  .count = 0L,
130  .repaint_source = 0,
131  .fullscreen = FALSE,
132 };
133 
134 void rofi_view_get_current_monitor ( int *width, int *height )
135 {
136  if ( width ) {
137  *width = CacheState.mon.w;
138  }
139  if ( height ) {
140  *height = CacheState.mon.h;
141  }
142 }
143 static char * get_matching_state ( void )
144 {
145  if ( config.case_sensitive ) {
146  if ( config.sort ) {
147  return "±";
148  }
149  else {
150  return "-";
151  }
152  }
153  else{
154  if ( config.sort ) {
155  return "+";
156  }
157  }
158  return " ";
159 }
160 
164 static int lev_sort ( const void *p1, const void *p2, void *arg )
165 {
166  const int *a = p1;
167  const int *b = p2;
168  int *distances = arg;
169 
170  return distances[*a] - distances[*b];
171 }
172 
177 {
178  const char *outp = g_getenv ( "ROFI_PNG_OUTPUT" );
179  if ( CacheState.edit_surf == NULL ) {
180  // Nothing to store.
181  g_warning ( "There is no rofi surface to store" );
182  return;
183  }
184  const char *xdg_pict_dir = g_get_user_special_dir ( G_USER_DIRECTORY_PICTURES );
185  if ( outp == NULL && xdg_pict_dir == NULL ) {
186  g_warning ( "XDG user picture directory or ROFI_PNG_OUTPUT is not set. Cannot store screenshot." );
187  return;
188  }
189  // Get current time.
190  GDateTime *now = g_date_time_new_now_local ();
191  // Format filename.
192  char *timestmp = g_date_time_format ( now, "rofi-%Y-%m-%d-%H%M" );
193  char *filename = g_strdup_printf ( "%s-%05d.png", timestmp, 0 );
194  // Build full path
195  char *fpath = NULL;
196  if ( outp == NULL ) {
197  int index = 0;
198  fpath = g_build_filename ( xdg_pict_dir, filename, NULL );
199  while ( g_file_test ( fpath, G_FILE_TEST_EXISTS ) && index < 99 ) {
200  g_free ( fpath );
201  g_free ( filename );
202  // Try the next index.
203  index++;
204  // Format filename.
205  filename = g_strdup_printf ( "%s-%05d.png", timestmp, index );
206  // Build full path
207  fpath = g_build_filename ( xdg_pict_dir, filename, NULL );
208  }
209  }
210  else {
211  fpath = g_strdup ( outp );
212  }
213  fprintf ( stderr, color_green "Storing screenshot %s\n"color_reset, fpath );
214  cairo_status_t status = cairo_surface_write_to_png ( CacheState.edit_surf, fpath );
215  if ( status != CAIRO_STATUS_SUCCESS ) {
216  g_warning ( "Failed to produce screenshot '%s', got error: '%s'", fpath,
217  cairo_status_to_string ( status ) );
218  }
219  g_free ( fpath );
220  g_free ( filename );
221  g_free ( timestmp );
222  g_date_time_unref ( now );
223 }
224 
225 static gboolean rofi_view_repaint ( G_GNUC_UNUSED void * data )
226 {
227  if ( current_active_menu ) {
228  // Repaint the view (if needed).
229  // After a resize the edit_pixmap surface might not contain anything anymore.
230  // If we already re-painted, this does nothing.
232  g_debug ( "expose event" );
233  TICK_N ( "Expose" );
234  xcb_copy_area ( xcb->connection, CacheState.edit_pixmap, CacheState.main_window, CacheState.gc,
236  xcb_flush ( xcb->connection );
237  TICK_N ( "flush" );
238  CacheState.repaint_source = 0;
239  }
240  return G_SOURCE_REMOVE;
241 }
242 
244 {
245  if ( state->prompt ) {
246  const char *str = mode_get_display_name ( state->sw );
247  textbox_text ( state->prompt, str );
248  }
249 }
250 
263 static const int loc_transtable[9] = {
264  WL_CENTER,
265  WL_NORTH | WL_WEST,
266  WL_NORTH,
267  WL_NORTH | WL_EAST,
268  WL_EAST,
269  WL_SOUTH | WL_EAST,
270  WL_SOUTH,
271  WL_SOUTH | WL_WEST,
272  WL_WEST
273 };
275 {
276  int location = rofi_theme_get_position ( WIDGET ( state->main_window ), "location", loc_transtable[config.location] );
277  int anchor = location;
278  if ( !listview_get_fixed_num_lines ( state->list_view ) ) {
279  anchor = location;
280  if ( location == WL_CENTER ) {
281  anchor = WL_NORTH;
282  }
283  else if ( location == WL_EAST ) {
284  anchor = WL_NORTH_EAST;
285  }
286  else if ( location == WL_WEST ) {
287  anchor = WL_NORTH_WEST;
288  }
289  }
290  anchor = rofi_theme_get_position ( WIDGET ( state->main_window ), "anchor", anchor );
291 
292  if ( CacheState.fullscreen ) {
293  state->x = CacheState.mon.x;
294  state->y = CacheState.mon.y;
295  return;
296  }
297  state->y = CacheState.mon.y + ( CacheState.mon.h ) / 2;
298  state->x = CacheState.mon.x + ( CacheState.mon.w ) / 2;
299  // Determine window location
300  switch ( location )
301  {
302  case WL_NORTH_WEST:
303  state->x = CacheState.mon.x;
304  /* FALLTHRU */
305  case WL_NORTH:
306  state->y = CacheState.mon.y;
307  break;
308  case WL_NORTH_EAST:
309  state->y = CacheState.mon.y;
310  /* FALLTHRU */
311  case WL_EAST:
312  state->x = CacheState.mon.x + CacheState.mon.w;
313  break;
314  case WL_SOUTH_EAST:
315  state->x = CacheState.mon.x + CacheState.mon.w;
316  /* FALLTHRU */
317  case WL_SOUTH:
318  state->y = CacheState.mon.y + CacheState.mon.h;
319  break;
320  case WL_SOUTH_WEST:
321  state->y = CacheState.mon.y + CacheState.mon.h;
322  /* FALLTHRU */
323  case WL_WEST:
324  state->x = CacheState.mon.x;
325  break;
326  case WL_CENTER:
327  ;
328  /* FALLTHRU */
329  default:
330  break;
331  }
332  switch ( anchor )
333  {
334  case WL_SOUTH_WEST:
335  state->y -= state->height;
336  break;
337  case WL_SOUTH:
338  state->x -= state->width / 2;
339  state->y -= state->height;
340  break;
341  case WL_SOUTH_EAST:
342  state->x -= state->width;
343  state->y -= state->height;
344  break;
345  case WL_NORTH_EAST:
346  state->x -= state->width;
347  break;
348  case WL_NORTH_WEST:
349  break;
350  case WL_NORTH:
351  state->x -= state->width / 2;
352  break;
353  case WL_EAST:
354  state->x -= state->width;
355  state->y -= state->height / 2;
356  break;
357  case WL_WEST:
358  state->y -= state->height / 2;
359  break;
360  case WL_CENTER:
361  state->y -= state->height / 2;
362  state->x -= state->width / 2;
363  break;
364  default:
365  break;
366  }
367  // Apply offset.
368  RofiDistance x = rofi_theme_get_distance ( WIDGET ( state->main_window ), "x-offset", config.x_offset );
369  RofiDistance y = rofi_theme_get_distance ( WIDGET ( state->main_window ), "y-offset", config.y_offset );
372 }
373 
375 {
376  uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
377  uint32_t vals[] = { state->x, state->y, state->width, state->height };
378 
379  // Display it.
380  xcb_configure_window ( xcb->connection, CacheState.main_window, mask, vals );
381  cairo_destroy ( CacheState.edit_draw );
382  cairo_surface_destroy ( CacheState.edit_surf );
383 
384  xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
385  CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
386  xcb_create_pixmap ( xcb->connection, depth->depth,
387  CacheState.edit_pixmap, CacheState.main_window, state->width, state->height );
388 
389  CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
390  CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
391 
392  g_debug ( "Re-size window based internal request: %dx%d.", state->width, state->height );
393  // Should wrap main window in a widget.
394  widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
395 }
396 
398 {
399  if ( state->mesg_box == NULL ) {
400  return;
401  }
402  char *msg = mode_get_message ( state->sw );
403  if ( msg ) {
404  textbox_text ( state->mesg_tb, msg );
405  widget_enable ( WIDGET ( state->mesg_box ) );
406  g_free ( msg );
407  }
408  else {
409  widget_disable ( WIDGET ( state->mesg_box ) );
410  }
411 }
412 
413 static gboolean rofi_view_reload_idle ( G_GNUC_UNUSED gpointer data )
414 {
415  if ( current_active_menu ) {
416  current_active_menu->reload = TRUE;
419  }
420  CacheState.idle_timeout = 0;
421  return G_SOURCE_REMOVE;
422 }
423 
424 void rofi_view_reload ( void )
425 {
426  // @TODO add check if current view is equal to the callee
427  if ( CacheState.idle_timeout == 0 ) {
428  CacheState.idle_timeout = g_timeout_add ( 1000 / 10, rofi_view_reload_idle, NULL );
429  }
430 }
432 {
433  if ( current_active_menu && CacheState.repaint_source == 0 ) {
434  CacheState.count++;
435  g_debug ( "redraw %llu", CacheState.count );
436  CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
437  }
438 }
439 
441 {
442  state->quit = FALSE;
443  state->retv = MENU_CANCEL;
444 }
445 
447 {
448  return current_active_menu;
449 }
450 
452 {
453  if ( current_active_menu != NULL && state != NULL ) {
454  g_queue_push_head ( &( CacheState.views ), current_active_menu );
455  // TODO check.
456  current_active_menu = state;
457  g_debug ( "stack view." );
460  return;
461  }
462  else if ( state == NULL && !g_queue_is_empty ( &( CacheState.views ) ) ) {
463  g_debug ( "pop view." );
464  current_active_menu = g_queue_pop_head ( &( CacheState.views ) );
467  return;
468  }
469  g_assert ( ( current_active_menu == NULL && state != NULL ) || ( current_active_menu != NULL && state == NULL ) );
470  current_active_menu = state;
472 }
473 
474 void rofi_view_set_selected_line ( RofiViewState *state, unsigned int selected_line )
475 {
476  state->selected_line = selected_line;
477  // Find the line.
478  unsigned int selected = 0;
479  for ( unsigned int i = 0; ( ( state->selected_line ) ) < UINT32_MAX && !selected && i < state->filtered_lines; i++ ) {
480  if ( state->line_map[i] == ( state->selected_line ) ) {
481  selected = i;
482  break;
483  }
484  }
485  listview_set_selected ( state->list_view, selected );
486  xcb_clear_area ( xcb->connection, CacheState.main_window, 1, 0, 0, 1, 1 );
487  xcb_flush ( xcb->connection );
488 }
489 
491 {
492  if ( state->tokens ) {
493  helper_tokenize_free ( state->tokens );
494  state->tokens = NULL;
495  }
496  // Do this here?
497  // Wait for final release?
498  widget_free ( WIDGET ( state->main_window ) );
499  widget_free ( WIDGET ( state->overlay ) );
500 
501  g_free ( state->line_map );
502  g_free ( state->distance );
503  // Free the switcher boxes.
504  // When state is free'ed we should no longer need these.
505  if ( config.sidebar_mode == TRUE ) {
506  g_free ( state->modi );
507  state->num_modi = 0;
508  }
509  g_free ( state );
510 }
511 
513 {
514  return state->retv;
515 }
516 
517 unsigned int rofi_view_get_selected_line ( const RofiViewState *state )
518 {
519  return state->selected_line;
520 }
521 
522 unsigned int rofi_view_get_next_position ( const RofiViewState *state )
523 {
524  unsigned int next_pos = state->selected_line;
525  unsigned int selected = listview_get_selected ( state->list_view );
526  if ( ( selected + 1 ) < state->num_lines ) {
527  ( next_pos ) = state->line_map[selected + 1];
528  }
529  return next_pos;
530 }
531 
532 unsigned int rofi_view_get_completed ( const RofiViewState *state )
533 {
534  return state->quit;
535 }
536 
537 const char * rofi_view_get_user_input ( const RofiViewState *state )
538 {
539  if ( state->text ) {
540  return state->text->text;
541  }
542  return NULL;
543 }
544 
551 {
552  return g_malloc0 ( sizeof ( RofiViewState ) );
553 }
557 typedef struct _thread_state
558 {
560  unsigned int start;
561  unsigned int stop;
562  unsigned int count;
563  GCond *cond;
564  GMutex *mutex;
565  unsigned int *acount;
566 
567  const char *pattern;
568  glong plen;
569  void ( *callback )( struct _thread_state *t, gpointer data );
570 }thread_state;
577 static void rofi_view_call_thread ( gpointer data, gpointer user_data )
578 {
579  thread_state *t = (thread_state *) data;
580  t->callback ( t, user_data );
581  g_mutex_lock ( t->mutex );
582  ( *( t->acount ) )--;
583  g_cond_signal ( t->cond );
584  g_mutex_unlock ( t->mutex );
585 }
586 
587 static void filter_elements ( thread_state *t, G_GNUC_UNUSED gpointer user_data )
588 {
589  for ( unsigned int i = t->start; i < t->stop; i++ ) {
590  int match = mode_token_match ( t->state->sw, t->state->tokens, i );
591  // If each token was matched, add it to list.
592  if ( match ) {
593  t->state->line_map[t->start + t->count] = i;
594  if ( config.sort ) {
595  // This is inefficient, need to fix it.
596  char * str = mode_get_completion ( t->state->sw, i );
597  glong slen = g_utf8_strlen ( str, -1 );
599  t->state->distance[i] = levenshtein ( t->pattern, t->plen, str, slen );
600  }
601  else {
602  t->state->distance[i] = rofi_scorer_fuzzy_evaluate ( t->pattern, t->plen, str, slen );
603  }
604  g_free ( str );
605  }
606  t->count++;
607  }
608  }
609 }
610 static void rofi_view_setup_fake_transparency ( const char* const fake_background )
611 {
612  if ( CacheState.fake_bg == NULL ) {
613  cairo_surface_t *s = NULL;
618  TICK_N ( "Fake start" );
619  if ( g_strcmp0 ( fake_background, "real" ) == 0 ) {
620  return;
621  }
622  else if ( g_strcmp0 ( fake_background, "screenshot" ) == 0 ) {
624  }
625  else if ( g_strcmp0 ( fake_background, "background" ) == 0 ) {
627  }
628  else {
629  char *fpath = rofi_expand_path ( fake_background );
630  g_debug ( "Opening %s to use as background.", fpath );
631  s = cairo_image_surface_create_from_png ( fpath );
632  CacheState.fake_bgrel = TRUE;
633  g_free ( fpath );
634  }
635  TICK_N ( "Get surface." );
636  if ( s != NULL ) {
637  if ( cairo_surface_status ( s ) != CAIRO_STATUS_SUCCESS ) {
638  g_debug ( "Failed to open surface fake background: %s",
639  cairo_status_to_string ( cairo_surface_status ( s ) ) );
640  cairo_surface_destroy ( s );
641  s = NULL;
642  }
643  else {
644  CacheState.fake_bg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h );
645  cairo_t *dr = cairo_create ( CacheState.fake_bg );
646  if ( CacheState.fake_bgrel ) {
647  cairo_set_source_surface ( dr, s, 0, 0 );
648  }
649  else {
650  cairo_set_source_surface ( dr, s, -CacheState.mon.x, -CacheState.mon.y );
651  }
652  cairo_paint ( dr );
653  cairo_destroy ( dr );
654  cairo_surface_destroy ( s );
655  }
656  }
657  TICK_N ( "Fake transparency" );
658  }
659 }
660 void __create_window ( MenuFlags menu_flags )
661 {
662  uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
663  uint32_t selval[] = {
664  XCB_BACK_PIXMAP_NONE, 0,
665  XCB_GRAVITY_STATIC,
666  XCB_BACKING_STORE_NOT_USEFUL,
667  XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
668  XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
669  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_1_MOTION,
670  map
671  };
672 
673  xcb_window_t box_window = xcb_generate_id ( xcb->connection );
674  xcb_void_cookie_t cc = xcb_create_window_checked ( xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window ( ),
675  0, 0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
676  visual->visual_id, selmask, selval );
677  xcb_generic_error_t *error;
678  error = xcb_request_check ( xcb->connection, cc );
679  if ( error ) {
680  g_error ( "xcb_create_window() failed error=0x%x\n", error->error_code );
681  exit ( EXIT_FAILURE );
682  }
683  TICK_N ( "xcb create window" );
684  CacheState.gc = xcb_generate_id ( xcb->connection );
685  xcb_create_gc ( xcb->connection, CacheState.gc, box_window, 0, 0 );
686 
687  TICK_N ( "xcb create gc" );
688  // Create a drawable.
689  CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
690  xcb_create_pixmap ( xcb->connection, depth->depth,
691  CacheState.edit_pixmap, CacheState.main_window, 200, 100 );
692 
693  CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, 200, 100 );
694  CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
695 
696  TICK_N ( "create cairo surface" );
697  // Set up pango context.
698  cairo_font_options_t *fo = cairo_font_options_create ();
699  // Take font description from xlib surface
700  cairo_surface_get_font_options ( CacheState.edit_surf, fo );
701  // TODO should we update the drawable each time?
702  PangoContext *p = pango_cairo_create_context ( CacheState.edit_draw );
703  // Set the font options from the xlib surface
704  pango_cairo_context_set_font_options ( p, fo );
705  TICK_N ( "pango cairo font setup" );
706 
707  CacheState.main_window = box_window;
708  CacheState.flags = menu_flags;
709  monitor_active ( &( CacheState.mon ) );
710  // Setup dpi
711  if ( config.dpi > 1 ) {
712  PangoFontMap *font_map = pango_cairo_font_map_get_default ();
713  pango_cairo_font_map_set_resolution ( (PangoCairoFontMap *) font_map, (double) config.dpi );
714  }
715  else if ( config.dpi == 0 || config.dpi == 1 ) {
716  // Auto-detect mode.
717  double dpi = 96;
718  if ( CacheState.mon.mh > 0 && config.dpi == 1 ) {
719  dpi = ( CacheState.mon.h * 25.4 ) / (double) ( CacheState.mon.mh );
720  }
721  else {
722  dpi = ( xcb->screen->height_in_pixels * 25.4 ) / (double) ( xcb->screen->height_in_millimeters );
723  }
724 
725  g_debug ( "Auto-detected DPI: %.2lf", dpi );
726  PangoFontMap *font_map = pango_cairo_font_map_get_default ();
727  pango_cairo_font_map_set_resolution ( (PangoCairoFontMap *) font_map, dpi );
728  config.dpi = dpi;
729  }
730  // Setup font.
731  // Dummy widget.
732  box *win = box_create ( NULL, "window", ROFI_ORIENTATION_HORIZONTAL );
733  const char *font = rofi_theme_get_string ( WIDGET ( win ), "font", config.menu_font );
734  if ( font ) {
735  PangoFontDescription *pfd = pango_font_description_from_string ( font );
736  if ( helper_validate_font ( pfd, font ) ) {
737  pango_context_set_font_description ( p, pfd );
738  }
739  pango_font_description_free ( pfd );
740  }
741  PangoLanguage *l = pango_language_get_default ();
742  pango_context_set_language ( p, l );
743  TICK_N ( "configure font" );
744 
745  // Tell textbox to use this context.
746  textbox_set_pango_context ( font, p );
747  // cleanup
748  g_object_unref ( p );
749  cairo_font_options_destroy ( fo );
750 
751  TICK_N ( "textbox setup" );
752  // // make it an unmanaged window
753  if ( ( ( menu_flags & MENU_NORMAL_WINDOW ) == 0 ) ) {
754  window_set_atom_prop ( box_window, xcb->ewmh._NET_WM_STATE, &( xcb->ewmh._NET_WM_STATE_ABOVE ), 1 );
755  uint32_t values[] = { 1 };
756  xcb_change_window_attributes ( xcb->connection, box_window, XCB_CW_OVERRIDE_REDIRECT, values );
757  }
758  else{
759  window_set_atom_prop ( box_window, xcb->ewmh._NET_WM_WINDOW_TYPE, &( xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL ), 1 );
760  x11_disable_decoration ( box_window );
761  }
762 
763  TICK_N ( "setup window attributes" );
764  CacheState.fullscreen = rofi_theme_get_boolean ( WIDGET ( win ), "fullscreen", config.fullscreen );
765  if ( CacheState.fullscreen ) {
766  xcb_atom_t atoms[] = {
767  xcb->ewmh._NET_WM_STATE_FULLSCREEN,
768  xcb->ewmh._NET_WM_STATE_ABOVE
769  };
770  window_set_atom_prop ( box_window, xcb->ewmh._NET_WM_STATE, atoms, sizeof ( atoms ) / sizeof ( xcb_atom_t ) );
771  }
772 
773  TICK_N ( "setup window fullscreen" );
774  // Set the WM_NAME
775  xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box_window, xcb->ewmh._NET_WM_NAME, xcb->ewmh.UTF8_STRING, 8, 4, "rofi" );
776  xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 4, "rofi" );
777 
778  const char wm_class_name[] = "rofi\0Rofi";
779  xcb_icccm_set_wm_class ( xcb->connection, box_window, sizeof ( wm_class_name ), wm_class_name );
780 
781  TICK_N ( "setup window name and class" );
782  const char *transparency = rofi_theme_get_string ( WIDGET ( win ), "transparency", NULL );
783  if ( transparency ) {
784  rofi_view_setup_fake_transparency ( transparency );
787  }
788  if ( xcb->sncontext != NULL ) {
789  sn_launchee_context_setup_window ( xcb->sncontext, CacheState.main_window );
790  }
791  TICK_N ( "setup startup notification" );
792  widget_free ( WIDGET ( win ) );
793  TICK_N ( "done" );
794 
795  // Set the PID.
796  pid_t pid = getpid ();
797  xcb_ewmh_set_wm_pid ( &( xcb->ewmh ), CacheState.main_window, pid );
798 
799  // Get hostname
800  const char *hostname = g_get_host_name ();
801  char *ahost = g_hostname_to_ascii ( hostname );
802  if ( ahost != NULL ) {
803  xcb_icccm_set_wm_client_machine ( xcb->connection,
804  CacheState.main_window,
805  XCB_ATOM_STRING, 8,
806  strlen ( ahost ), ahost );
807  g_free ( ahost );
808  }
809 }
810 
817 {
818  if ( CacheState.fullscreen ) {
819  state->width = CacheState.mon.w;
820  return;
821  }
822  if ( config.menu_width < 0 ) {
823  double fw = textbox_get_estimated_char_width ( );
824  state->width = -( fw * config.menu_width );
826  }
827  else{
828  // Calculate as float to stop silly, big rounding down errors.
829  state->width = config.menu_width < 101 ? ( CacheState.mon.w / 100.0f ) * ( float ) config.menu_width : config.menu_width;
830  }
831  // Use theme configured width, if set.
834 }
835 
846 {
847  if ( state->filtered_lines == 1 ) {
848  state->retv = MENU_OK;
850  state->quit = 1;
851  return;
852  }
853 
854  // Double tab!
855  if ( state->filtered_lines == 0 && ROW_TAB == state->prev_action ) {
856  state->retv = MENU_NEXT;
857  ( state->selected_line ) = 0;
858  state->quit = TRUE;
859  }
860  else {
862  }
864 }
871 {
872  if ( state->list_view == NULL ) {
873  return;
874  }
875  unsigned int selected = listview_get_selected ( state->list_view );
876  // If a valid item is selected, return that..
877  if ( selected < state->filtered_lines ) {
878  char *str = mode_get_completion ( state->sw, state->line_map[selected] );
879  textbox_text ( state->text, str );
880  g_free ( str );
882  state->refilter = TRUE;
883  }
884 }
885 
891 inline static void rofi_view_nav_first ( RofiViewState * state )
892 {
893 // state->selected = 0;
895 }
896 
902 inline static void rofi_view_nav_last ( RofiViewState * state )
903 {
904  // If no lines, do nothing.
905  if ( state->filtered_lines == 0 ) {
906  return;
907  }
908  //state->selected = state->filtered_lines - 1;
910 }
911 
912 static void update_callback ( textbox *t, unsigned int index, void *udata, TextBoxFontType type, gboolean full )
913 {
914  RofiViewState *state = (RofiViewState *) udata;
915  if ( full ) {
916  GList *add_list = NULL;
917  int fstate = 0;
918  char *text = mode_get_display_value ( state->sw, state->line_map[index], &fstate, &add_list, TRUE );
919  type |= fstate;
920  textbox_font ( t, type );
921  // Move into list view.
922  textbox_text ( t, text );
923  PangoAttrList *list = textbox_get_pango_attributes ( t );
924  if ( list != NULL ) {
925  pango_attr_list_ref ( list );
926  }
927  else{
928  list = pango_attr_list_new ();
929  }
930  int icon_height = textbox_get_font_height ( t );
931 
932  cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height );
933  textbox_icon ( t, icon );
934 
935  if ( state->tokens && config.show_match ) {
936  RofiHighlightColorStyle th = { ROFI_HL_BOLD | ROFI_HL_UNDERLINE, { 0.0, 0.0, 0.0, 0.0 } };
937  th = rofi_theme_get_highlight ( WIDGET ( t ), "highlight", th );
939  }
940  for ( GList *iter = g_list_first ( add_list ); iter != NULL; iter = g_list_next ( iter ) ) {
941  pango_attr_list_insert ( list, (PangoAttribute *) ( iter->data ) );
942  }
943  textbox_set_pango_attributes ( t, list );
944  pango_attr_list_unref ( list );
945  g_list_free ( add_list );
946  g_free ( text );
947  }
948  else {
949  int fstate = 0;
950  mode_get_display_value ( state->sw, state->line_map[index], &fstate, NULL, FALSE );
951  type |= fstate;
952  textbox_font ( t, type );
953  }
954 }
955 
956 void rofi_view_update ( RofiViewState *state, gboolean qr )
957 {
958  if ( !widget_need_redraw ( WIDGET ( state->main_window ) ) ) {
959  return;
960  }
961  g_debug ( "Redraw view" );
962  TICK ();
963  cairo_t *d = CacheState.edit_draw;
964  cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE );
965  if ( CacheState.fake_bg != NULL ) {
966  if ( CacheState.fake_bgrel ) {
967  cairo_set_source_surface ( d, CacheState.fake_bg, 0.0, 0.0 );
968  }
969  else {
970  cairo_set_source_surface ( d, CacheState.fake_bg,
971  -(double) ( state->x - CacheState.mon.x ),
972  -(double) ( state->y - CacheState.mon.y ) );
973  }
974  cairo_paint ( d );
975  cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
976  }
977  else {
978  // Paint the background transparent.
979  cairo_set_source_rgba ( d, 0, 0, 0, 0.0 );
980  cairo_paint ( d );
981  }
982  TICK_N ( "Background" );
983 
984  // Always paint as overlay over the background.
985  cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
986  widget_draw ( WIDGET ( state->main_window ), d );
987 
988  if ( state->overlay ) {
989  widget_draw ( WIDGET ( state->overlay ), d );
990  }
991  TICK_N ( "widgets" );
992  cairo_surface_flush ( CacheState.edit_surf );
993  if ( qr ) {
995  }
996 }
997 
999 {
1000  g_free ( state->line_map );
1001  g_free ( state->distance );
1003  state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
1004  state->distance = g_malloc0_n ( state->num_lines, sizeof ( int ) );
1007 }
1008 
1010 {
1011  TICK_N ( "Filter start" );
1012  if ( state->reload ) {
1014  state->reload = FALSE;
1015  }
1016  if ( state->tokens ) {
1018  state->tokens = NULL;
1019  }
1020  if ( state->text && strlen ( state->text->text ) > 0 ) {
1021  unsigned int j = 0;
1022  gchar *pattern = mode_preprocess_input ( state->sw, state->text->text );
1023  glong plen = pattern ? g_utf8_strlen ( pattern, -1 ) : 0;
1031  unsigned int nt = MAX ( 1, state->num_lines / 500 );
1032  thread_state states[nt];
1033  GCond cond;
1034  GMutex mutex;
1035  g_mutex_init ( &mutex );
1036  g_cond_init ( &cond );
1037  unsigned int count = nt;
1038  unsigned int steps = ( state->num_lines + nt ) / nt;
1039  for ( unsigned int i = 0; i < nt; i++ ) {
1040  states[i].state = state;
1041  states[i].start = i * steps;
1042  states[i].stop = MIN ( state->num_lines, ( i + 1 ) * steps );
1043  states[i].count = 0;
1044  states[i].cond = &cond;
1045  states[i].mutex = &mutex;
1046  states[i].acount = &count;
1047  states[i].plen = plen;
1048  states[i].pattern = pattern;
1049  states[i].callback = filter_elements;
1050  if ( i > 0 ) {
1051  g_thread_pool_push ( tpool, &states[i], NULL );
1052  }
1053  }
1054  // Run one in this thread.
1055  rofi_view_call_thread ( &states[0], NULL );
1056  // No need to do this with only one thread.
1057  if ( nt > 1 ) {
1058  g_mutex_lock ( &mutex );
1059  while ( count > 0 ) {
1060  g_cond_wait ( &cond, &mutex );
1061  }
1062  g_mutex_unlock ( &mutex );
1063  }
1064  g_cond_clear ( &cond );
1065  g_mutex_clear ( &mutex );
1066  for ( unsigned int i = 0; i < nt; i++ ) {
1067  if ( j != states[i].start ) {
1068  memmove ( &( state->line_map[j] ), &( state->line_map[states[i].start] ), sizeof ( unsigned int ) * ( states[i].count ) );
1069  }
1070  j += states[i].count;
1071  }
1072  if ( config.sort ) {
1073  g_qsort_with_data ( state->line_map, j, sizeof ( int ), lev_sort, state->distance );
1074  }
1075 
1076  // Cleanup + bookkeeping.
1077  state->filtered_lines = j;
1078  g_free ( pattern );
1079  }
1080  else{
1081  for ( unsigned int i = 0; i < state->num_lines; i++ ) {
1082  state->line_map[i] = i;
1083  }
1085  }
1087 
1088  if ( config.auto_select == TRUE && state->filtered_lines == 1 && state->num_lines > 1 ) {
1090  state->retv = MENU_OK;
1091  state->quit = TRUE;
1092  }
1093  // Size the window.
1094  int height = rofi_view_calculate_height ( state );
1095  if ( height != state->height ) {
1096  state->height = height;
1099  g_debug ( "Resize based on re-filter" );
1100  }
1101  state->refilter = FALSE;
1102  TICK_N ( "Filter done" );
1103 }
1111 {
1112  if ( state && state->finalize != NULL ) {
1113  state->finalize ( state );
1114  }
1115 }
1116 
1118 {
1120  switch ( action )
1121  {
1122  // Handling of paste
1123  case PASTE_PRIMARY:
1124  xcb_convert_selection ( xcb->connection, CacheState.main_window, XCB_ATOM_PRIMARY,
1125  xcb->ewmh.UTF8_STRING, xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME );
1126  xcb_flush ( xcb->connection );
1127  break;
1128  case PASTE_SECONDARY:
1129  xcb_convert_selection ( xcb->connection, CacheState.main_window, netatoms[CLIPBOARD],
1130  xcb->ewmh.UTF8_STRING, xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME );
1131  xcb_flush ( xcb->connection );
1132  break;
1133  case SCREENSHOT:
1135  break;
1136  case TOGGLE_SORT:
1137  if ( state->case_indicator != NULL ) {
1138  config.sort = !config.sort;
1139  state->refilter = TRUE;
1141  }
1142  break;
1143  case MODE_PREVIOUS:
1145  ( state->selected_line ) = 0;
1146  state->quit = TRUE;
1147  break;
1148  // Menu navigation.
1149  case MODE_NEXT:
1150  state->retv = MENU_NEXT;
1151  ( state->selected_line ) = 0;
1152  state->quit = TRUE;
1153  break;
1154  // Toggle case sensitivity.
1156  if ( state->case_indicator != NULL ) {
1158  ( state->selected_line ) = 0;
1159  state->refilter = TRUE;
1161  }
1162  break;
1163  // Special delete entry command.
1164  case DELETE_ENTRY:
1165  {
1166  unsigned int selected = listview_get_selected ( state->list_view );
1167  if ( selected < state->filtered_lines ) {
1168  ( state->selected_line ) = state->line_map[selected];
1170  state->quit = TRUE;
1171  }
1172  break;
1173  }
1174  case SELECT_ELEMENT_1:
1175  case SELECT_ELEMENT_2:
1176  case SELECT_ELEMENT_3:
1177  case SELECT_ELEMENT_4:
1178  case SELECT_ELEMENT_5:
1179  case SELECT_ELEMENT_6:
1180  case SELECT_ELEMENT_7:
1181  case SELECT_ELEMENT_8:
1182  case SELECT_ELEMENT_9:
1183  case SELECT_ELEMENT_10:
1184  {
1185  unsigned int index = action - SELECT_ELEMENT_1;
1186  if ( index < state->filtered_lines ) {
1187  state->selected_line = state->line_map[index];
1188  state->retv = MENU_OK;
1189  state->quit = TRUE;
1190  }
1191  break;
1192  }
1193  case CUSTOM_1:
1194  case CUSTOM_2:
1195  case CUSTOM_3:
1196  case CUSTOM_4:
1197  case CUSTOM_5:
1198  case CUSTOM_6:
1199  case CUSTOM_7:
1200  case CUSTOM_8:
1201  case CUSTOM_9:
1202  case CUSTOM_10:
1203  case CUSTOM_11:
1204  case CUSTOM_12:
1205  case CUSTOM_13:
1206  case CUSTOM_14:
1207  case CUSTOM_15:
1208  case CUSTOM_16:
1209  case CUSTOM_17:
1210  case CUSTOM_18:
1211  case CUSTOM_19:
1212  {
1213  state->selected_line = UINT32_MAX;
1214  unsigned int selected = listview_get_selected ( state->list_view );
1215  if ( selected < state->filtered_lines ) {
1216  ( state->selected_line ) = state->line_map[selected];
1217  }
1218  state->retv = MENU_QUICK_SWITCH | ( ( action - CUSTOM_1 ) & MENU_LOWER_MASK );
1219  state->quit = TRUE;
1220  break;
1221  }
1222  // If you add a binding here, make sure to add it to rofi_view_keyboard_navigation too
1223  case CANCEL:
1224  state->retv = MENU_CANCEL;
1225  state->quit = TRUE;
1226  break;
1227  case ROW_UP:
1229  break;
1230  case ROW_TAB:
1232  break;
1233  case ROW_DOWN:
1235  break;
1236  case ROW_LEFT:
1238  break;
1239  case ROW_RIGHT:
1241  break;
1242  case PAGE_PREV:
1244  break;
1245  case PAGE_NEXT:
1247  break;
1248  case ROW_FIRST:
1250  break;
1251  case ROW_LAST:
1253  break;
1254  case ROW_SELECT:
1256  break;
1257  // If you add a binding here, make sure to add it to textbox_keybinding too
1258  case MOVE_CHAR_BACK:
1259  {
1260  if ( textbox_keybinding ( state->text, action ) == 0 ) {
1262  }
1263  break;
1264  }
1265  case MOVE_CHAR_FORWARD:
1266  {
1267  if ( textbox_keybinding ( state->text, action ) == 0 ) {
1269  }
1270  break;
1271  }
1272  case CLEAR_LINE:
1273  case MOVE_FRONT:
1274  case MOVE_END:
1275  case REMOVE_TO_EOL:
1276  case REMOVE_TO_SOL:
1277  case REMOVE_WORD_BACK:
1278  case REMOVE_WORD_FORWARD:
1279  case REMOVE_CHAR_FORWARD:
1280  case MOVE_WORD_BACK:
1281  case MOVE_WORD_FORWARD:
1282  case REMOVE_CHAR_BACK:
1283  {
1284  int rc = textbox_keybinding ( state->text, action );
1285  if ( rc == 1 ) {
1286  // Entry changed.
1287  state->refilter = TRUE;
1288  }
1289  else if ( rc == 2 ) {
1290  // Movement.
1291  }
1292  break;
1293  }
1294  case ACCEPT_ALT:
1295  {
1296  unsigned int selected = listview_get_selected ( state->list_view );
1297  state->selected_line = UINT32_MAX;
1298  if ( selected < state->filtered_lines ) {
1299  ( state->selected_line ) = state->line_map[selected];
1300  state->retv = MENU_OK;
1301  }
1302  else {
1303  // Nothing entered and nothing selected.
1305  }
1307  state->quit = TRUE;
1308  break;
1309  }
1310  case ACCEPT_CUSTOM:
1311  {
1312  state->selected_line = UINT32_MAX;
1314  state->quit = TRUE;
1315  break;
1316  }
1317  case ACCEPT_ENTRY:
1318  {
1319  // If a valid item is selected, return that..
1320  unsigned int selected = listview_get_selected ( state->list_view );
1321  state->selected_line = UINT32_MAX;
1322  if ( selected < state->filtered_lines ) {
1323  ( state->selected_line ) = state->line_map[selected];
1324  state->retv = MENU_OK;
1325  }
1326  else {
1327  // Nothing entered and nothing selected.
1329  }
1330 
1331  state->quit = TRUE;
1332  break;
1333  }
1334  }
1335 }
1336 
1337 gboolean rofi_view_trigger_action ( RofiViewState *state, BindingsScope scope, guint action )
1338 {
1339  switch ( scope )
1340  {
1341  case SCOPE_GLOBAL:
1343  return TRUE;
1344  case SCOPE_MOUSE_LISTVIEW:
1346  case SCOPE_MOUSE_EDITBOX:
1347  case SCOPE_MOUSE_SCROLLBAR:
1349  {
1350  gint x = state->mouse.x, y = state->mouse.y;
1351  widget *target = widget_find_mouse_target ( WIDGET ( state->main_window ), scope, x, y );
1352  if ( target == NULL ) {
1353  return FALSE;
1354  }
1355  widget_xy_to_relative ( target, &x, &y );
1356  switch ( widget_trigger_action ( target, action, x, y ) )
1357  {
1359  return FALSE;
1361  target = NULL;
1362  /* FALLTHRU */
1364  state->mouse.motion_target = target;
1365  /* FALLTHRU */
1367  return TRUE;
1368  }
1369  break;
1370  }
1371  }
1372  return FALSE;
1373 }
1374 
1376 {
1377  if ( textbox_append_text ( state->text, text, strlen ( text ) ) ) {
1378  state->refilter = TRUE;
1379  }
1380 }
1381 
1383 {
1384  state->mouse.x = x;
1385  state->mouse.y = y;
1386  if ( state->mouse.motion_target != NULL ) {
1389  }
1390 }
1391 
1393 {
1394  if ( rofi_view_get_completed ( state ) ) {
1395  // This menu is done.
1397  // If there a state. (for example error) reload it.
1399 
1400  // cleanup, if no more state to display.
1401  if ( state == NULL ) {
1402  // Quit main-loop.
1404  return;
1405  }
1406  }
1407 
1408  // Update if requested.
1409  if ( state->refilter ) {
1411  }
1412  rofi_view_update ( state, TRUE );
1413 }
1414 
1415 void rofi_view_temp_configure_notify ( RofiViewState *state, xcb_configure_notify_event_t *xce )
1416 {
1417  if ( xce->window == CacheState.main_window ) {
1418  if ( state->x != xce->x || state->y != xce->y ) {
1419  state->x = xce->x;
1420  state->y = xce->y;
1422  }
1423  if ( state->width != xce->width || state->height != xce->height ) {
1424  state->width = xce->width;
1425  state->height = xce->height;
1426 
1427  cairo_destroy ( CacheState.edit_draw );
1428  cairo_surface_destroy ( CacheState.edit_surf );
1429 
1430  xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
1431  CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
1432  xcb_create_pixmap ( xcb->connection, depth->depth, CacheState.edit_pixmap, CacheState.main_window,
1433  state->width, state->height );
1434 
1435  CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
1436  CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
1437  g_debug ( "Re-size window based external request: %d %d", state->width, state->height );
1439  }
1440  }
1441 }
1442 
1443 void rofi_view_temp_click_to_exit ( RofiViewState *state, xcb_window_t target )
1444 {
1445  if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
1446  if ( target != CacheState.main_window ) {
1447  state->quit = TRUE;
1448  state->retv = MENU_CANCEL;
1449  }
1450  }
1451 }
1452 
1454 {
1455  if ( CacheState.repaint_source == 0 ) {
1456  CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
1457  }
1458 }
1459 
1461 {
1462  if ( CacheState.fullscreen == TRUE ) {
1463  return CacheState.mon.h;
1464  }
1465 
1466  RofiDistance h = rofi_theme_get_distance ( WIDGET ( state->main_window ), "height", 0 );
1467  unsigned int height = distance_get_pixel ( h, ROFI_ORIENTATION_VERTICAL );
1468  // If height is set, return it.
1469  if ( height > 0 ) {
1470  return height;
1471  }
1472  // Autosize based on widgets.
1475 }
1476 
1477 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 )
1478 {
1479  RofiViewState *state = ( RofiViewState *) user_data;
1480  unsigned int i;
1481  for ( i = 0; i < state->num_modi; i++ ) {
1482  if ( WIDGET ( state->modi[i] ) == wid ) {
1483  break;
1484  }
1485  }
1486  if ( i == state->num_modi ) {
1488  }
1489 
1490  switch ( action )
1491  {
1492  case MOUSE_CLICK_DOWN:
1494  state->quit = TRUE;
1495  state->skip_absorb = TRUE;
1497  case MOUSE_CLICK_UP:
1498  case MOUSE_DCLICK_DOWN:
1499  case MOUSE_DCLICK_UP:
1500  break;
1501  }
1503 }
1504 
1505 // @TODO don't like this construction.
1506 static void rofi_view_listview_mouse_activated_cb ( listview *lv, gboolean custom, void *udata )
1507 {
1508  RofiViewState *state = (RofiViewState *) udata;
1509  state->retv = MENU_OK;
1510  if ( custom ) {
1512  }
1514  // Quit
1515  state->quit = TRUE;
1516  state->skip_absorb = TRUE;
1517 }
1518 
1519 static void rofi_view_add_widget ( RofiViewState *state, widget *parent_widget, const char *name )
1520 {
1521  char *defaults = NULL;
1522  widget *wid = NULL;
1523 
1527  if ( strcmp ( name, "mainbox" ) == 0 ) {
1528  wid = (widget *) box_create ( parent_widget, name, ROFI_ORIENTATION_VERTICAL );
1529  box_add ( (box *) parent_widget, WIDGET ( wid ), TRUE );
1530  defaults = "inputbar,message,listview,sidebar";
1531  }
1535  else if ( strcmp ( name, "inputbar" ) == 0 ) {
1536  wid = (widget *) box_create ( parent_widget, name, ROFI_ORIENTATION_HORIZONTAL );
1537  defaults = "prompt,entry,case-indicator";
1538  box_add ( (box *) parent_widget, WIDGET ( wid ), FALSE );
1539  }
1543  else if ( strcmp ( name, "prompt" ) == 0 ) {
1544  if ( state->prompt != NULL ) {
1545  g_error ( "Prompt widget can only be added once to the layout." );
1546  return;
1547  }
1548  // Prompt box.
1549  state->prompt = textbox_create ( parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name, TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0 );
1551  box_add ( (box *) parent_widget, WIDGET ( state->prompt ), FALSE );
1552  defaults = NULL;
1553  }
1557  else if ( strcmp ( name, "case-indicator" ) == 0 ) {
1558  if ( state->case_indicator != NULL ) {
1559  g_error ( "Case indicator widget can only be added once to the layout." );
1560  return;
1561  }
1563  // Add small separator between case indicator and text box.
1564  box_add ( (box *) parent_widget, WIDGET ( state->case_indicator ), FALSE );
1566  }
1570  else if ( strcmp ( name, "entry" ) == 0 ) {
1571  if ( state->text != NULL ) {
1572  g_error ( "Entry textbox widget can only be added once to the layout." );
1573  return;
1574  }
1575  // Entry box
1576  TextboxFlags tfl = TB_EDITABLE;
1577  tfl |= ( ( state->menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
1578  state->text = textbox_create ( parent_widget, WIDGET_TYPE_EDITBOX, name, tfl | TB_AUTOHEIGHT, NORMAL, NULL, 0, 0 );
1579  box_add ( (box *) parent_widget, WIDGET ( state->text ), TRUE );
1580  }
1584  else if ( strcmp ( name, "message" ) == 0 ) {
1585  if ( state->mesg_box != NULL ) {
1586  g_error ( "Message widget can only be added once to the layout." );
1587  return;
1588  }
1589  state->mesg_box = container_create ( parent_widget, name );
1593  box_add ( (box *) parent_widget, WIDGET ( state->mesg_box ), FALSE );
1594  }
1598  else if ( strcmp ( name, "listview" ) == 0 ) {
1599  if ( state->list_view != NULL ) {
1600  g_error ( "Listview widget can only be added once to the layout." );
1601  return;
1602  }
1603  state->list_view = listview_create ( parent_widget, name, update_callback, state, config.element_height, 0 );
1604  box_add ( (box *) parent_widget, WIDGET ( state->list_view ), TRUE );
1605  // Set configuration
1609 
1610  int lines = rofi_theme_get_integer ( WIDGET ( state->list_view ), "lines", config.menu_lines );
1613  }
1617  else if ( strcmp ( name, "sidebar" ) == 0 ) {
1618  if ( state->sidebar_bar != NULL ) {
1619  g_error ( "Sidebar widget can only be added once to the layout." );
1620  return;
1621  }
1622  if ( config.sidebar_mode ) {
1623  state->sidebar_bar = box_create ( parent_widget, name, ROFI_ORIENTATION_HORIZONTAL );
1624  box_add ( (box *) parent_widget, WIDGET ( state->sidebar_bar ), FALSE );
1626  state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) );
1627  for ( unsigned int j = 0; j < state->num_modi; j++ ) {
1628  const Mode * mode = rofi_get_mode ( j );
1630  mode_get_display_name ( mode ), 0.5, 0.5 );
1631  box_add ( state->sidebar_bar, WIDGET ( state->modi[j] ), TRUE );
1633  }
1634  }
1635  }
1636  else if ( g_ascii_strncasecmp ( name, "textbox", 7 ) == 0 ) {
1637  textbox *t = textbox_create ( parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name, TB_AUTOHEIGHT | TB_WRAP, NORMAL, "", 0, 0 );
1638  box_add ( (box *) parent_widget, WIDGET ( t ), TRUE );
1639  }
1640  else {
1641  wid = (widget *) box_create ( parent_widget, name, ROFI_ORIENTATION_VERTICAL );
1642  box_add ( (box *) parent_widget, WIDGET ( wid ), TRUE );
1643  //g_error("The widget %s does not exists. Invalid layout.", name);
1644  }
1645  if ( wid ) {
1646  GList *list = rofi_theme_get_list ( wid, "children", defaults );
1647  for ( const GList *iter = list; iter != NULL; iter = g_list_next ( iter ) ) {
1648  rofi_view_add_widget ( state, wid, (const char *) iter->data );
1649  }
1650  g_list_free_full ( list, g_free );
1651  }
1652 }
1653 
1655  const char *input,
1656  MenuFlags menu_flags,
1657  void ( *finalize )( RofiViewState * ) )
1658 {
1659  TICK ();
1661  state->menu_flags = menu_flags;
1662  state->sw = sw;
1663  state->selected_line = UINT32_MAX;
1664  state->retv = MENU_CANCEL;
1665  state->distance = NULL;
1666  state->quit = FALSE;
1667  state->skip_absorb = FALSE;
1668  //We want to filter on the first run.
1669  state->refilter = TRUE;
1670  state->finalize = finalize;
1671  state->mouse_seen = FALSE;
1672 
1673  // Request the lines to show.
1675 
1676  TICK_N ( "Startup notification" );
1677 
1678  // Get active monitor size.
1679  TICK_N ( "Get active monitor" );
1680 
1681  state->main_window = box_create ( NULL, "window", ROFI_ORIENTATION_VERTICAL );
1682  // Get children.
1683  GList *list = rofi_theme_get_list ( WIDGET ( state->main_window ), "children", "mainbox" );
1684  for ( const GList *iter = list; iter != NULL; iter = g_list_next ( iter ) ) {
1685  rofi_view_add_widget ( state, WIDGET ( state->main_window ), (const char *) iter->data );
1686  }
1687  g_list_free_full ( list, g_free );
1688 
1689  if ( state->text && input ) {
1690  textbox_text ( state->text, input );
1692  }
1693 
1696 
1697  // filtered list
1698  state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
1699  state->distance = (int *) g_malloc0_n ( state->num_lines, sizeof ( int ) );
1700 
1702  // Need to resize otherwise calculated desired height is wrong.
1703  widget_resize ( WIDGET ( state->main_window ), state->width, 100 );
1704  // Only needed when window is fixed size.
1705  if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == MENU_NORMAL_WINDOW ) {
1707  }
1708 
1710  // Move the window to the correct x,y position.
1713 
1714  state->quit = FALSE;
1716  rofi_view_update ( state, TRUE );
1717  xcb_map_window ( xcb->connection, CacheState.main_window );
1719  xcb_flush ( xcb->connection );
1720  if ( xcb->sncontext != NULL ) {
1721  sn_launchee_context_complete ( xcb->sncontext );
1722  }
1723  return state;
1724 }
1725 
1726 int rofi_view_error_dialog ( const char *msg, int markup )
1727 {
1729  state->retv = MENU_CANCEL;
1732 
1733  state->main_window = box_create ( NULL, "window", ROFI_ORIENTATION_VERTICAL );
1735  box_add ( state->main_window, WIDGET ( box ), TRUE );
1736  state->text = textbox_create ( WIDGET ( box ), WIDGET_TYPE_TEXTBOX_TEXT, "textbox", ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ),
1737  NORMAL, ( msg != NULL ) ? msg : "", 0, 0 );
1738  box_add ( box, WIDGET ( state->text ), TRUE );
1739 
1740  // Make sure we enable fixed num lines when in normal window mode.
1741  if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == MENU_NORMAL_WINDOW ) {
1743  }
1745  // Need to resize otherwise calculated desired height is wrong.
1746  widget_resize ( WIDGET ( state->main_window ), state->width, 100 );
1747  // resize window vertically to suit
1749 
1750  // Calculte window position.
1752 
1753  // Move the window to the correct x,y position.
1755 
1756  // Display it.
1757  xcb_map_window ( xcb->connection, CacheState.main_window );
1759 
1760  if ( xcb->sncontext != NULL ) {
1761  sn_launchee_context_complete ( xcb->sncontext );
1762  }
1763 
1764  // Set it as current window.
1766  return TRUE;
1767 }
1768 
1769 void rofi_view_hide ( void )
1770 {
1771  if ( CacheState.main_window != XCB_WINDOW_NONE ) {
1772  xcb_unmap_window ( xcb->connection, CacheState.main_window );
1774  }
1775 }
1776 
1778 {
1779  g_debug ( "Cleanup." );
1780  if ( CacheState.idle_timeout > 0 ) {
1781  g_source_remove ( CacheState.idle_timeout );
1782  CacheState.idle_timeout = 0;
1783  }
1784  if ( CacheState.repaint_source > 0 ) {
1785  g_source_remove ( CacheState.repaint_source );
1786  CacheState.repaint_source = 0;
1787  }
1788  if ( CacheState.fake_bg ) {
1789  cairo_surface_destroy ( CacheState.fake_bg );
1790  CacheState.fake_bg = NULL;
1791  }
1792  if ( CacheState.edit_draw ) {
1793  cairo_destroy ( CacheState.edit_draw );
1794  CacheState.edit_draw = NULL;
1795  }
1796  if ( CacheState.edit_surf ) {
1797  cairo_surface_destroy ( CacheState.edit_surf );
1798  CacheState.edit_surf = NULL;
1799  }
1800  if ( CacheState.main_window != XCB_WINDOW_NONE ) {
1801  g_debug ( "Unmapping and free'ing window" );
1802  xcb_unmap_window ( xcb->connection, CacheState.main_window );
1803  xcb_free_gc ( xcb->connection, CacheState.gc );
1804  xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
1805  xcb_destroy_window ( xcb->connection, CacheState.main_window );
1806  CacheState.main_window = XCB_WINDOW_NONE;
1807  }
1808  if ( map != XCB_COLORMAP_NONE ) {
1809  xcb_free_colormap ( xcb->connection, map );
1810  map = XCB_COLORMAP_NONE;
1811  }
1812  xcb_flush ( xcb->connection );
1813  g_assert ( g_queue_is_empty ( &( CacheState.views ) ) );
1814 }
1816 {
1817  TICK_N ( "Setup Threadpool, start" );
1818  if ( config.threads == 0 ) {
1819  config.threads = 1;
1820  long procs = sysconf ( _SC_NPROCESSORS_CONF );
1821  if ( procs > 0 ) {
1822  config.threads = MIN ( procs, 128l );
1823  }
1824  }
1825  // Create thread pool
1826  GError *error = NULL;
1827  tpool = g_thread_pool_new ( rofi_view_call_thread, NULL, config.threads, FALSE, &error );
1828  if ( error == NULL ) {
1829  // Idle threads should stick around for a max of 60 seconds.
1830  g_thread_pool_set_max_idle_time ( 60000 );
1831  // We are allowed to have
1832  g_thread_pool_set_max_threads ( tpool, config.threads, &error );
1833  }
1834  // If error occurred during setup of pool, tell user and exit.
1835  if ( error != NULL ) {
1836  g_warning ( "Failed to setup thread pool: '%s'", error->message );
1837  g_error_free ( error );
1838  exit ( EXIT_FAILURE );
1839  }
1840  TICK_N ( "Setup Threadpool, done" );
1841 }
1843 {
1844  if ( tpool ) {
1845  g_thread_pool_free ( tpool, TRUE, TRUE );
1846  tpool = NULL;
1847  }
1848 }
1850 {
1851  return state->sw;
1852 }
1853 
1854 void rofi_view_set_overlay ( RofiViewState *state, const char *text )
1855 {
1856  if ( state->overlay == NULL || state->list_view == NULL ) {
1857  return;
1858  }
1859  if ( text == NULL ) {
1861  return;
1862  }
1863  widget_enable ( WIDGET ( state->overlay ) );
1864  textbox_text ( state->overlay, text );
1865  int x_offset = widget_get_width ( WIDGET ( state->list_view ) );
1866  // Within padding of window.
1867  x_offset += widget_get_absolute_xpos ( WIDGET ( state->list_view ) );
1868  x_offset -= widget_get_width ( WIDGET ( state->overlay ) );
1869  // Within the border of widget.
1870  int top_offset = widget_get_absolute_ypos ( WIDGET ( state->list_view ) );
1871  widget_move ( WIDGET ( state->overlay ), x_offset, top_offset );
1872  // We want to queue a repaint.
1874 }
1875 
1877 {
1878  if ( state->text ) {
1879  textbox_text ( state->text, "" );
1881  }
1882 }
1883 
1885 {
1886  state->sw = mode;
1887  // Update prompt;
1888  if ( state->prompt ) {
1890  }
1891  if ( config.sidebar_mode && state->sidebar_bar ) {
1892  for ( unsigned int j = 0; j < state->num_modi; j++ ) {
1893  const Mode * mode = rofi_get_mode ( j );
1894  textbox_font ( state->modi[j], ( mode == state->sw ) ? HIGHLIGHT : NORMAL );
1895  }
1896  }
1898  state->reload = TRUE;
1899  state->refilter = TRUE;
1901  rofi_view_update ( state, TRUE );
1902 }
1903 
1904 xcb_window_t rofi_view_get_window ( void )
1905 {
1906  return CacheState.main_window;
1907 }
void rofi_view_cleanup()
Definition: view.c:1777
xcb_depth_t * depth
Definition: xcb.c:90
unsigned int * line_map
Definition: view-internal.h:74
void listview_set_selected(listview *lv, unsigned int selected)
Definition: listview.c:401
unsigned int levenshtein(const char *needle, const glong needlelen, const char *haystack, const glong haystacklen)
Definition: helper.c:702
static const int loc_transtable[9]
Definition: view.c:263
Definition: box.c:40
guint idle_timeout
Definition: view.c:113
MenuReturn
Definition: mode.h:66
void textbox_cursor_end(textbox *tb)
Definition: textbox.c:584
GList * rofi_theme_get_list(const widget *widget, const char *property, const char *defaults)
Definition: theme.c:692
void rofi_view_get_current_monitor(int *width, int *height)
Definition: view.c:134
textbox ** modi
cairo_surface_t * fake_bg
Definition: view.c:95
MouseBindingMouseDefaultAction
Definition: keyb.h:154
unsigned int auto_select
Definition: settings.h:122
void rofi_quit_main_loop(void)
Definition: rofi.c:621
GCond * cond
Definition: view.c:563
unsigned int fake_transparency
Definition: settings.h:146
void rofi_view_finalize(RofiViewState *state)
Definition: view.c:1110
gboolean widget_need_redraw(widget *wid)
Definition: widget.c:434
BindingsScope
Definition: keyb.h:39
listview * listview_create(widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse)
Definition: listview.c:514
void display_early_cleanup(void)
Definition: xcb.c:1315
int mode_token_match(const Mode *mode, rofi_int_matcher **tokens, unsigned int selected_line)
Definition: mode.c:105
void rofi_view_clear_input(RofiViewState *state)
Definition: view.c:1876
WindowLocation location
Definition: settings.h:94
unsigned int case_sensitive
Definition: settings.h:112
static void rofi_view_nav_last(RofiViewState *state)
Definition: view.c:902
Definition: mode.h:69
void x11_disable_decoration(xcb_window_t window)
Definition: xcb.c:1350
void textbox_text(textbox *tb, const char *text)
Definition: textbox.c:303
static void update_callback(textbox *t, unsigned int index, void *udata, TextBoxFontType type, gboolean full)
Definition: view.c:912
void rofi_view_reload(void)
Definition: view.c:424
unsigned int sidebar_mode
Definition: settings.h:118
PangoAttrList * helper_token_match_get_pango_attr(RofiHighlightColorStyle th, rofi_int_matcher **tokens, const char *input, PangoAttrList *retv)
Definition: helper.c:410
Definition: keyb.h:103
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
Definition: view.c:1415
void listview_nav_up(listview *lv)
Definition: listview.c:587
Definition: keyb.h:96
Definition: xcb.h:99
void listview_nav_page_prev(listview *lv)
Definition: listview.c:702
void rofi_view_workers_finalize(void)
Definition: view.c:1842
void textbox_icon(textbox *tb, cairo_surface_t *icon)
Definition: textbox.c:335
void rofi_view_queue_redraw(void)
Definition: view.c:431
unsigned int menu_lines
Definition: settings.h:59
xcb_window_t xcb_stuff_get_root_window(void)
Definition: xcb.c:1310
Mode * rofi_view_get_mode(RofiViewState *state)
Definition: view.c:1849
static void filter_elements(thread_state *t, G_GNUC_UNUSED gpointer user_data)
Definition: view.c:587
double textbox_get_estimated_char_width(void)
Definition: textbox.c:894
void listview_set_num_elements(listview *lv, unsigned int rows)
Definition: listview.c:382
KeyBindingAction prev_action
Definition: view-internal.h:82
int widget_padding_get_padding_width(const widget *wid)
Definition: widget.c:548
cairo_surface_t * mode_get_icon(const Mode *mode, unsigned int selected_line, int height)
Definition: mode.c:72
unsigned int * acount
Definition: view.c:565
Definition: keyb.h:105
static void rofi_view_update_prompt(RofiViewState *state)
Definition: view.c:243
xcb_stuff * xcb
Definition: xcb.c:85
char * mode_preprocess_input(Mode *mode, const char *input)
Definition: mode.c:157
const char * rofi_view_get_user_input(const RofiViewState *state)
Definition: view.c:537
void __create_window(MenuFlags menu_flags)
Definition: view.c:660
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
Definition: theme.c:604
unsigned int sort
Definition: settings.h:106
static void rofi_view_setup_fake_transparency(const char *const fake_background)
Definition: view.c:610
unsigned int scroll_method
Definition: settings.h:151
void listview_set_scroll_type(listview *lv, ScrollType type)
Definition: listview.c:771
int widget_get_width(widget *widget)
Definition: widget.c:377
void widget_free(widget *wid)
Definition: widget.c:355
Definition: keyb.h:99
const char * pattern
Definition: view.c:567
Definition: keyb.h:95
Definition: keyb.h:98
static void rofi_view_nav_first(RofiViewState *state)
Definition: view.c:891
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:1477
void rofi_view_set_selected_line(RofiViewState *state, unsigned int selected_line)
Definition: view.c:474
#define color_green
Definition: rofi.h:96
struct _thread_state thread_state
Definition: keyb.h:114
unsigned int num_lines
Definition: view-internal.h:76
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
Definition: view.c:1443
void textbox_font(textbox *tb, TextBoxFontType tbft)
Definition: textbox.c:229
textbox * prompt
Definition: view-internal.h:56
Definition: keyb.h:106
char * text
Definition: textbox.h:55
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition: theme.c:571
RofiViewState * rofi_view_get_active(void)
Definition: view.c:446
static void rofi_view_refilter(RofiViewState *state)
Definition: view.c:1009
void widget_set_trigger_action_handler(widget *wid, widget_trigger_action_cb cb, void *cb_data)
Definition: widget.c:468
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:549
void widget_draw(widget *widget, cairo_t *d)
Definition: widget.c:140
unsigned int rofi_get_num_enabled_modi(void)
Definition: rofi.c:123
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
Definition: textbox.c:165
void widget_disable(widget *widget)
Definition: widget.c:131
cairo_surface_t * x11_helper_get_bg_surface(void)
Definition: xcb.c:139
MenuReturn rofi_view_get_return_value(const RofiViewState *state)
Definition: view.c:512
int fake_bgrel
Definition: view.c:105
void listview_nav_right(listview *lv)
Definition: listview.c:626
xcb_ewmh_connection_t ewmh
Definition: xcb-internal.h:48
char * fake_background
Definition: settings.h:154
void rofi_view_workers_initialize(void)
Definition: view.c:1815
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
Definition: listview.c:778
void listview_set_num_lines(listview *lv, unsigned int num_lines)
Definition: listview.c:791
int dpi
Definition: settings.h:148
void rofi_view_frame_callback(void)
Definition: view.c:1453
rofi_int_matcher ** helper_tokenize(const char *input, int case_sensitive)
Definition: helper.c:256
xcb_pixmap_t edit_pixmap
Definition: view.c:99
void rofi_view_free(RofiViewState *state)
Definition: view.c:490
Definition: keyb.h:66
int y_offset
Definition: settings.h:98
RofiViewState * current_active_menu
Definition: view.c:85
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y)
Definition: view.c:1382
textbox * mesg_tb
Definition: view-internal.h:69
void widget_move(widget *widget, short x, short y)
Definition: widget.c:98
static void rofi_view_nav_row_select(RofiViewState *state)
Definition: view.c:870
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
Definition: theme.c:718
TextboxFlags
Definition: textbox.h:79
void widget_xy_to_relative(widget *widget, gint *x, gint *y)
Definition: widget.c:402
void rofi_view_hide(void)
Definition: view.c:1769
xcb_window_t rofi_view_get_window(void)
Definition: view.c:1904
void widget_resize(widget *widget, short w, short h)
Definition: widget.c:82
unsigned long long count
Definition: view.c:115
unsigned int start
Definition: view.c:560
xcb_window_t main_window
Definition: view.c:93
void rofi_view_update(RofiViewState *state, gboolean qr)
Definition: view.c:956
WidgetTriggerActionResult widget_trigger_action(widget *wid, guint action, gint x, gint y)
Definition: widget.c:460
struct RofiViewState::@4 mouse
unsigned int rofi_view_get_next_position(const RofiViewState *state)
Definition: view.c:522
int menu_width
Definition: settings.h:57
static void rofi_view_listview_mouse_activated_cb(listview *lv, gboolean custom, void *udata)
Definition: view.c:1506
RofiViewState * state
Definition: view.c:559
void widget_queue_redraw(widget *wid)
Definition: widget.c:421
int x_offset
Definition: settings.h:100
Definition: keyb.h:108
Definition: keyb.h:110
MenuReturn retv
Definition: view-internal.h:93
Definition: keyb.h:112
unsigned int listview_get_selected(listview *lv)
Definition: listview.c:393
int textbox_keybinding(textbox *tb, KeyBindingAction action)
Definition: textbox.c:721
void rofi_view_handle_text(RofiViewState *state, char *text)
Definition: view.c:1375
const char * textbox_get_visible_text(const textbox *tb)
Definition: textbox.c:280
unsigned int rofi_view_get_completed(const RofiViewState *state)
Definition: view.c:532
void rofi_view_set_active(RofiViewState *state)
Definition: view.c:451
guint repaint_source
Definition: view.c:117
container * mesg_box
Definition: view-internal.h:67
int rofi_view_error_dialog(const char *msg, int markup)
Definition: view.c:1726
textbox * text
Definition: view-internal.h:58
#define TICK()
Definition: timings.h:89
box * box_create(widget *parent, const char *name, RofiOrientation type)
Definition: box.c:335
gboolean rofi_view_trigger_action(RofiViewState *state, BindingsScope scope, guint action)
Definition: view.c:1337
static void rofi_view_nav_row_tab(RofiViewState *state)
Definition: view.c:845
TextBoxFontType
Definition: textbox.h:93
static char * get_matching_state(void)
Definition: view.c:143
static void rofi_view_window_update_size(RofiViewState *state)
Definition: view.c:374
char * menu_font
Definition: settings.h:63
cairo_t * edit_draw
Definition: view.c:103
Definition: textbox.h:96
GQueue views
Definition: view.c:109
void listview_set_multi_select(listview *lv, gboolean enable)
Definition: listview.c:785
GThreadPool * tpool
Definition: view.c:82
static void rofi_view_calculate_window_position(RofiViewState *state)
Definition: view.c:274
Definition: textbox.h:98
MatchingMethod matching_method
Definition: settings.h:130
char * rofi_expand_path(const char *input)
Definition: helper.c:669
GMutex * mutex
Definition: view.c:564
gboolean show_match
Definition: settings.h:159
xcb_connection_t * connection
Definition: xcb-internal.h:47
KeyBindingAction
Definition: keyb.h:55
xcb_colormap_t map
Definition: xcb.c:92
void process_result(RofiViewState *state)
Definition: rofi.c:193
void listview_set_fixed_num_lines(listview *lv)
Definition: listview.c:819
Definition: keyb.h:91
MenuFlags flags
Definition: view.c:107
void rofi_view_switch_mode(RofiViewState *state, Mode *mode)
Definition: view.c:1884
unsigned int mode_get_num_entries(const Mode *mode)
Definition: mode.c:56
void(* finalize)(struct RofiViewState *state)
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:735
static int rofi_view_calculate_height(RofiViewState *state)
Definition: view.c:1460
char * mode_get_display_value(const Mode *mode, unsigned int selected_line, int *state, GList **attribute_list, int get_entry)
Definition: mode.c:63
textbox * case_indicator
Definition: view-internal.h:60
int monitor_active(workarea *mon)
Definition: xcb.c:680
gboolean fullscreen
Definition: view.c:119
xcb_visualtype_t * visual
Definition: xcb.c:91
unsigned int stop
Definition: view.c:561
unsigned int filtered_lines
Definition: view-internal.h:79
int element_height
Definition: settings.h:116
void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count)
Definition: xcb.c:176
WidgetTriggerActionResult
Definition: widget.h:77
void listview_nav_page_next(listview *lv)
Definition: listview.c:714
void widget_enable(widget *widget)
Definition: widget.c:122
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
Definition: textbox.c:287
static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, const char *name)
Definition: view.c:1519
void rofi_view_restart(RofiViewState *state)
Definition: view.c:440
static void rofi_view_reload_message_bar(RofiViewState *state)
Definition: view.c:397
unsigned int count
Definition: view.c:562
xcb_screen_t * screen
Definition: xcb-internal.h:49
#define WIDGET(a)
Definition: widget.h:115
unsigned int levenshtein_sort
Definition: settings.h:110
void helper_tokenize_free(rofi_int_matcher **tokens)
Definition: helper.c:155
void(* callback)(struct _thread_state *t, gpointer data)
Definition: view.c:569
void rofi_view_maybe_update(RofiViewState *state)
Definition: view.c:1392
listview * list_view
Definition: view-internal.h:63
int rofi_theme_get_position(const widget *widget, const char *property, int def)
Definition: theme.c:516
textbox * overlay
Definition: view-internal.h:65
Definition: mode.h:73
static gboolean rofi_view_reload_idle(G_GNUC_UNUSED gpointer data)
Definition: view.c:413
SnLauncheeContext * sncontext
Definition: xcb-internal.h:52
const Mode * rofi_get_mode(unsigned int index)
Definition: rofi.c:128
void listview_set_max_lines(listview *lv, unsigned int max_lines)
Definition: listview.c:805
char * mode_get_message(const Mode *mode)
Definition: mode.c:164
const char * mode_get_display_name(const Mode *mode)
Definition: mode.c:143
rofi_int_matcher ** tokens
unsigned int rofi_view_get_selected_line(const RofiViewState *state)
Definition: view.c:517
Settings config
unsigned int num_modi
static void rofi_view_calculate_window_width(RofiViewState *state)
Definition: view.c:816
void rofi_view_set_overlay(RofiViewState *state, const char *text)
Definition: view.c:1854
int widget_get_absolute_xpos(widget *wid)
Definition: widget.c:577
gboolean widget_motion_notify(widget *wid, gint x, gint y)
Definition: widget.c:477
int widget_get_absolute_ypos(widget *wid)
Definition: widget.c:588
int widget_get_desired_height(widget *wid)
Definition: widget.c:556
unsigned int threads
Definition: settings.h:150
widget * widget_find_mouse_target(widget *wid, WidgetType type, gint x, gint y)
Definition: widget.c:442
int textbox_get_font_height(const textbox *tb)
Definition: textbox.c:867
gboolean listview_get_fixed_num_lines(listview *lv)
Definition: listview.c:812
void listview_nav_left(listview *lv)
Definition: listview.c:612
#define TICK_N(a)
Definition: timings.h:94
Definition: keyb.h:107
static gboolean rofi_view_repaint(G_GNUC_UNUSED void *data)
Definition: view.c:225
xcb_gcontext_t gc
Definition: view.c:97
static void rofi_view_call_thread(gpointer data, gpointer user_data)
Definition: view.c:577
void container_add(container *container, widget *child)
Definition: container.c:71
glong plen
Definition: view.c:568
unsigned int selected_line
Definition: view-internal.h:91
#define color_reset
Definition: rofi.h:90
static RofiViewState * __rofi_view_state_create(void)
Definition: view.c:550
void listview_nav_down(listview *lv)
Definition: listview.c:599
cairo_surface_t * edit_surf
Definition: view.c:101
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
Definition: textbox.c:294
Definition: keyb.h:97
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition: theme.c:533
Definition: keyb.h:111
unsigned int fullscreen
Definition: settings.h:144
void rofi_capture_screenshot(void)
Definition: view.c:176
Definition: keyb.h:109
static void rofi_view_trigger_global_action(KeyBindingAction action)
Definition: view.c:1117
Definition: keyb.h:113
void box_add(box *box, widget *child, gboolean expand)
Definition: box.c:283
MenuFlags menu_flags
RofiViewState * rofi_view_create(Mode *sw, const char *input, MenuFlags menu_flags, void(*finalize)(RofiViewState *))
Definition: view.c:1654
MenuFlags
Definition: view.h:43
char * mode_get_completion(const Mode *mode, unsigned int selected_line)
Definition: mode.c:84
workarea mon
Definition: view.c:111
xcb_atom_t netatoms[NUM_NETATOMS]
Definition: xcb.c:97
static void _rofi_view_reload_row(RofiViewState *state)
Definition: view.c:998
widget * motion_target
static int lev_sort(const void *p1, const void *p2, void *arg)
Definition: view.c:164
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
Definition: textbox.c:785
int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, glong slen)
Definition: helper.c:891
container * container_create(widget *parent, const char *name)
Definition: container.c:103
cairo_surface_t * x11_helper_get_screenshot_surface(void)
Definition: xcb.c:104
gboolean helper_validate_font(PangoFontDescription *pfd, const char *font)
Definition: helper.c:556
void textbox_set_pango_context(const char *font, PangoContext *p)
Definition: textbox.c:824
struct @0 CacheState