/* @brief Calls the associated redraw functions of both query and response text. * * @param connection A connection to the Xorg server. * @param window An xcb window created by xcb_generate_id. * @param cr A cairo context for drawing to the screen. * @param surface A cairo surface for drawing to the screen. * @param query_string The string to draw into the query field (what is being typed). * @param query_cursor_index The current index of the cursor * @return Void. */ static void redraw_all(xcb_connection_t *connection, xcb_window_t window, cairo_t *cr, cairo_surface_t *surface, char *query_string, uint32_t query_cursor_index) { draw_query_text(cr, surface, query_string, query_cursor_index); draw_response_text(connection, window, cr, surface, global.results, global.result_count); }
/* @brief Processes an entered key by: * * 1) Adding the key to the query buffer (backspace will remove a character). * 2) Drawing the updated query to the screen if necessary. * 3) Writing the updated query to the child process if necessary. * * @param query_buffer The string of the current query (what is typed). * @param query_index A reference to the current length of the query. * @param query_cursor_index A reference to the current index of the cursor in the query. * @param key The key enetered. * @param connection A connection to the Xorg server. * @param cairo_context A cairo context for drawing to the screen. * @param cairo_surface A cairo surface for drawing to the screen. * @param to_write A descriptor to write to the child process. * @return 0 on success and 1 on failure. */ static inline int32_t process_key_stroke(char *query_buffer, uint32_t *query_index, uint32_t *query_cursor_index, xcb_keysym_t key, xcb_connection_t *connection, cairo_t *cairo_context, cairo_surface_t *cairo_surface, FILE *to_write) { pthread_mutex_lock(&global.result_mutex); /* Check when we should update. */ int32_t redraw = 0; int32_t resend = 0; debug("key: %u\n", key); switch (key) { case 65293: /* Enter. */ if (global.results && global.result_highlight < global.result_count && global.result_highlight >= 0) { printf("%s", global.results[global.result_highlight].action); goto cleanup; } break; case 65361: /* Left. */ if (*query_cursor_index > 0) { (*query_cursor_index)--; redraw = 1; } break; case 65363: /* Right. */ if (*query_cursor_index < *query_index) { (*query_cursor_index)++; redraw = 1; } break; case 65362: /* Up. */ if (global.result_highlight > 0) { global.result_highlight--; draw_response_text(connection, 0, cairo_context, cairo_surface, global.results, global.result_count); } break; case 65364: /* Down. */ if (global.result_count && global.result_highlight < global.result_count - 1) { global.result_highlight++; draw_response_text(connection, 0, cairo_context, cairo_surface, global.results, global.result_count); } break; case 65289: /* Tab. */ if (global.result_count && global.result_highlight < global.result_count - 1) { global.result_highlight++; draw_response_text(connection, 0, cairo_context, cairo_surface, global.results, global.result_count); } else if(global.result_count && global.result_highlight == global.result_count - 1) { global.result_highlight = 0; draw_response_text(connection, 0, cairo_context, cairo_surface, global.results, global.result_count); } break; case 65056: /* Shift Tab */ if (global.result_count && global.result_highlight > 0) { global.result_highlight--; draw_response_text(connection, 0, cairo_context, cairo_surface, global.results, global.result_count); } else if(global.result_count && global.result_highlight == 0) { global.result_highlight = global.result_count - 1; draw_response_text(connection, 0, cairo_context, cairo_surface, global.results, global.result_count); } break; case 65307: /* Escape. */ goto cleanup; case 65288: /* Backspace. */ if (*query_index > 0 && *query_cursor_index > 0) { memmove(&query_buffer[(*query_cursor_index) - 1], &query_buffer[*query_cursor_index], *query_index - *query_cursor_index + 1); (*query_cursor_index)--; (*query_index)--; query_buffer[(*query_index)] = 0; redraw = 1; resend = 1; } else if (*query_index == 0 && settings.backspace_exit) { /* Backspace with nothing? */ goto cleanup; } break; default: if (isprint((char)key) && *query_index < MAX_QUERY) { memmove(&query_buffer[(*query_cursor_index) + 1], &query_buffer[*query_cursor_index], *query_index - *query_cursor_index + 1); query_buffer[(*query_cursor_index)++] = key; (*query_index)++; redraw = 1; resend = 1; } break; } if (redraw) { draw_query_text(cairo_context, cairo_surface, query_buffer, *query_cursor_index); xcb_flush(connection); } if (resend) { if (write_to_remote(to_write, "%s\n", query_buffer)) { fprintf(stderr, "Failed to write.\n"); } } pthread_mutex_unlock(&global.result_mutex); return 1; cleanup: pthread_mutex_unlock(&global.result_mutex); return 0; }
/* @brief Processes an entered key by: * * 1) Adding the key to the query buffer (backspace will remove a character). * 2) Drawing the updated query to the screen if necessary. * 3) Writing the updated query to the child process if necessary. * * @param query_buffer The string of the current query (what is typed). * @param query_index A reference to the current length of the query. * @param query_cursor_index A reference to the current index of the cursor in the query. * @param key The key enetered. * @param connection A connection to the Xorg server. * @param cairo_context A cairo context for drawing to the screen. * @param cairo_surface A cairo surface for drawing to the screen. * @param to_write A descriptor to write to the child process. * @return 0 on success and 1 on failure. */ static inline int32_t process_key_stroke(xcb_window_t window, char *query_buffer, uint32_t *query_index, uint32_t *query_cursor_index, xcb_keysym_t key, uint16_t modifier_mask, xcb_connection_t *connection, cairo_t *cairo_context, cairo_surface_t *cairo_surface, FILE *to_write) { pthread_mutex_lock(&global.result_mutex); /* Check when we should update. */ int32_t redraw = 0; int32_t resend = 0; uint8_t mod_key = get_modifiers(modifier_mask); debug("key: %u, modifier: %u\n", key, mod_key); uint32_t highlight = global.result_highlight; uint32_t old_pos; if (global.result_count && key == 100 && mod_key == 3) { /* CTRL-D * GO down to the next title */ next_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } else if (global.result_count && key == 117 && mod_key == 3) { /* CTRL-U * GO up to the next title */ previous_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } else { switch (key) { case 65293: /* Enter. */ if (global.results && global.result_highlight < global.result_count) { char *title = global.results[global.result_highlight].text; char *action = global.results[global.result_highlight].action; char command[255] = "echo '"; strcat(command, query_buffer); strcat(command, " {"); char titleParsed[255]; str_replace(strcpy(titleParsed, title), "'", "'\\''"); strcat(command, titleParsed); strcat(command, " | "); char actionParsed[255]; str_replace(strcpy(actionParsed, action), "'", "'\\''"); strcat(command, actionParsed); strcat(command, "}"); strcat(command, "' >> /home/olli/.local/share/lighthouse_queries && "); printf("%s", command); printf("%s", action); goto cleanup; } break; case 65471: /* F2 */ next_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65472: /* F3 */ previous_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65361: /* Left. */ if (*query_cursor_index > 0) { (*query_cursor_index)--; redraw = 1; } break; case 65363: /* Right. */ if (*query_cursor_index < *query_index) { (*query_cursor_index)++; redraw = 1; } break; case 65362: /* Up. */ if (!global.result_count) break; if (highlight) { /* Avoid segfault when highlight on the top. */ old_pos = highlight; get_previous_non_title(&highlight); if (!global.results[highlight].action) { /* If it's a title it mean the get_previous_non_title function * found nothing and hit the top. */ highlight = old_pos; /* To not let the highlight point on a title. */ if (global.result_offset) global.result_offset--; } global.result_highlight = highlight; draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } break; case 65364: /* Down. */ if (!global.result_count) break; if (highlight < global.result_count - 1) { old_pos = highlight; get_next_non_title(&highlight); if (highlight == global.result_count) { /* If no other result with an action can be found, it just inc the * the offset so it can show the hidden title and make the highlight to the * previous non_title. * NB: If the offset limit is exceed, it's handled by the draw_result_text function. */ highlight = old_pos; global.result_offset++; } global.result_highlight = highlight; draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } break; case 65289: /* Tab. */ if (!global.result_count) break; get_next_line(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65056: /* Shift Tab */ if (!global.result_count) break; get_previous_line(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65307: /* Escape. */ goto cleanup; case 65288: /* Backspace. */ if (*query_index > 0 && *query_cursor_index > 0) { memmove(&query_buffer[(*query_cursor_index) - 1], &query_buffer[*query_cursor_index], *query_index - *query_cursor_index + 1); (*query_cursor_index)--; (*query_index)--; query_buffer[(*query_index)] = 0; redraw = 1; resend = 1; } else if (*query_index == 0 && settings.backspace_exit) { /* Backspace with nothing */ goto cleanup; } break; default: if (isprint((char)key) && *query_index < MAX_QUERY) { memmove(&query_buffer[(*query_cursor_index) + 1], &query_buffer[*query_cursor_index], *query_index - *query_cursor_index + 1); query_buffer[(*query_cursor_index)++] = key; (*query_index)++; redraw = 1; resend = 1; } break; } } if (redraw) { draw_query_text(cairo_context, cairo_surface, query_buffer, *query_cursor_index); xcb_flush(connection); } if (resend) { if (write_to_remote(to_write, "%s\n", query_buffer)) { fprintf(stderr, "Failed to write.\n"); } } pthread_mutex_unlock(&global.result_mutex); return 1; cleanup: pthread_mutex_unlock(&global.result_mutex); return 0; }