diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3969feb7..3a52087e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -14,7 +14,7 @@ Before creating an issue: When reporting bugs include the following information: * Rofi version. rofi -v -* Rofi configuration. rofi -dump-xresources (preferable in a pastebin) +* Rofi configuration. rofi -dump-xresources (preferable in a [gist](https://gist.github.com/)) * Steps to reproduce. * What behaviour you see. * What behaviour you expect to see. diff --git a/Changelog b/Changelog index 6967363a..0e1077e6 100644 --- a/Changelog +++ b/Changelog @@ -1,9 +1,13 @@ unreleased New Features + - Keys mode, showing keybindings. + - Stop cycling option (#407) (Thx to Yaroslav) + - Kill window on delete entry (#316) Improvements - Allow user to use X11 background for fake transparency (#390) - Allow user to specify background image. - Improved keybinding handling, allowing on-release and modifier only (#384). + - Use display name for prompt (#409) Bug fixes - Grab mouse pointer with keyboard diff --git a/Makefile.am b/Makefile.am index 769bcc4d..f50c0240 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,6 +38,7 @@ rofi_SOURCES=\ source/dialogs/combi.c\ source/dialogs/window.c\ source/dialogs/script.c\ + source/dialogs/help-keys.c\ include/xcb.h\ include/xcb-internal.h\ include/rofi.h\ @@ -64,6 +65,7 @@ rofi_SOURCES=\ include/dialogs/script.h\ include/dialogs/window.h\ include/dialogs/dialogs.h\ + include/dialogs/help-keys.h\ include/xkb.h\ include/xkb-internal.h @@ -140,7 +142,7 @@ update-manpage: $(top_srcdir)/doc/rofi-manpage.markdown ## # Rofi test program ## -check_PROGRAMS=history_test textbox_test helper_test helper_expand helper_config_cmdline_parser +check_PROGRAMS=history_test textbox_test helper_test helper_expand helper_config_cmdline_parser widget_test history_test_CFLAGS=\ $(AM_CFLAGS)\ @@ -186,6 +188,11 @@ textbox_test_LDADD=\ $(cairo_LIBS)\ $(libsn_LIBS) +widget_test_LDADD=$(textbox_test_LDADD) +widget_test_CFLAGS=$(textbox_test_CFLAGS) +widget_test_SOURCES=\ + source/widget.c\ + test/widget-test.c textbox_test_SOURCES=\ source/widget.c\ source/textbox.c\ @@ -271,7 +278,8 @@ TESTS=\ history_test\ helper_test\ helper_expand\ - helper_config_cmdline_parser + helper_config_cmdline_parser\ + widget_test .PHONY: test-x test-x: $(bin_PROGRAMS) textbox_test diff --git a/README.md b/README.md index 3328415c..85c889dd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ [![Build Status](https://travis-ci.org/DaveDavenport/rofi.svg?branch=master)](https://travis-ci.org/DaveDavenport/rofi) [![codecov.io](https://codecov.io/github/DaveDavenport/rofi/coverage.svg?branch=master)](https://codecov.io/github/DaveDavenport/rofi?branch=master) +[![Issues](https://img.shields.io/github/issues/DaveDavenport/rofi.svg)](https://github.com/DaveDavenport/rofi/issues) +[![Forks](https://img.shields.io/github/forks/DaveDavenport/rofi.svg)](https://github.com/DaveDavenport/rofi/network) +[![Stars](https://img.shields.io/github/stars/DaveDavenport/rofi.svg)](https://github.com/DaveDavenport/rofi/stargazers) +[![Downloads](https://img.shields.io/github/downloads/DaveDavenport/rofi/total.svg)](https://github.com/DaveDavenport/rofi/releases) # A window switcher, run dialog and dmenu replacement @@ -143,10 +147,10 @@ Type `Shift-Right` to switch from Window list mode to Run mode and back. |`Ctrl-Enter` | Use entered text as command (in ssh/run modi) | |`Shift-Enter` | Launch the application in a terminal (in run mode) | |`Shift-Enter` | Return the selected entry and move to the next item while keeping Rofi open. (in dmenu) | -|`Shift-Right` | Switch to the next modi. The list can be customized with the -switchers argument. | -|`Shift-Left` | Switch to the previous modi. The list can be customized with the -switchers argument. | -|`Ctrl-Tab` | Switch to the next modi. The list can be customized with the -switchers argument. | -|`Ctrl-Shift-Tab` | Switch to the previous modi. The list can be customized with the -switchers argument. | +|`Shift-Right` | Switch to the next modi. The list can be customized with the -modi option. | +|`Shift-Left` | Switch to the previous modi. The list can be customized with the -modi option. | +|`Ctrl-Tab` | Switch to the next modi. The list can be customized with the -modi option. | +|`Ctrl-Shift-Tab` | Switch to the previous modi. The list can be customized with the -modi option. | |`Ctrl-space` | Set selected item as input text. | |`Shift-Del` | Delete entry from history. | |`grave` | Toggle case sensitivity. | diff --git a/config/config.c b/config/config.c index 346e47d0..d20a2cb4 100644 --- a/config/config.c +++ b/config/config.c @@ -94,6 +94,8 @@ Settings config = { .levenshtein_sort = FALSE, /** Case sensitivity of the search */ .case_sensitive = FALSE, + /** Cycle through in the element list */ + .cycle = TRUE, /** Height of an element in #chars */ .element_height = 1, /** Sidebar mode, show the modi */ diff --git a/data/uncrustify.cfg b/data/uncrustify.cfg index 8fc2b96e..3e11e22f 100644 --- a/data/uncrustify.cfg +++ b/data/uncrustify.cfg @@ -1,7 +1,7 @@ # # My favorite format # -code_width = 140 +code_width = 240 nl_max = 2 ls_func_split_full = True indent_with_tabs = 0 # 1=indent to level only, 2=indent with tabs diff --git a/doc/rofi-manpage.markdown b/doc/rofi-manpage.markdown index 0e71767c..dc9ca5f1 100644 --- a/doc/rofi-manpage.markdown +++ b/doc/rofi-manpage.markdown @@ -26,6 +26,7 @@ [ -disable-history ] [ -levenshtein-sort ] [ -case-sensitive ] +[ -cycle ] [ -show *mode* ] [ -modi *mode1,mode2* ] [ -eh *element height* ] @@ -185,6 +186,10 @@ Example: Have a mode 'Workspaces' using the `i3_switch_workspace.sh` script: Start in case sensitive mode. +`-cycle` + +Cycle through the results list. Default is 'true'. + `-fuzzy` Enable experimental fuzzy matching. diff --git a/doc/rofi.1 b/doc/rofi.1 index 190f1ac0..ec9bbe16 100644 --- a/doc/rofi.1 +++ b/doc/rofi.1 @@ -7,7 +7,7 @@ \fBrofi\fR \- A window switcher, run launcher, ssh dialog and dmenu replacement . .SH "SYNOPSIS" -\fBrofi\fR [ \-width \fIpct_scr\fR ] [ \-lines \fIlines\fR ] [ \-columns \fIcolumns\fR ] [ \-font \fIpangofont\fR ] [ \-terminal \fIterminal\fR ] [ \-location \fIposition\fR ] [ \-fixed\-num\-lines ] [ \-padding \fIpadding\fR ] [ \-opacity \fIopacity%\fR ] [ \-display \fIdisplay\fR ] [ \-bw \fIwidth\fR ] [ \-dmenu [ \-p \fIprompt\fR ] [ \-sep \fIseparator\fR ] [ \-l \fIselected line\fR ] [ \-mesg ] [ \-select ] [ \-input \fIinput\fR ] ] [ \-filter \fIfilter\fR ] [ \-ssh\-client \fIclient\fR ] [ \-ssh\-command \fIcommand\fR ] [ \-window\-command \fIcommand\fR ] [ \-disable\-history ] [ \-levenshtein\-sort ] [ \-case\-sensitive ] [ \-show \fImode\fR ] [ \-modi \fImode1,mode2\fR ] [ \-eh \fIelement height\fR ] [ \-lazy\-filter\-limit \fIlimit\fR ] [ \-e \fImessage\fR] [ \-a \fIrow\fR ] [ \-u \fIrow\fR ] [ \-pid \fIpath\fR ] [ \-now ] [ \-rnow ] [ \-snow ] [ \-version ] [ \-help ] [ \-dump\-xresources ] [ \-dump\-xresources\-theme ] [ \-auto\-select ] [ \-parse\-hosts ] [ \-no\-parse\-known\-hosts ] [ \-combi\-modi \fImode1,mode2\fR ] [ \-normal\-window ] [ \-fake\-transparency ] [ \-glob ] [ \-regex ] [ \-tokenize ] [ \-threads \fInum\fR ] [ \-config \fIfilename\fR ] +\fBrofi\fR [ \-width \fIpct_scr\fR ] [ \-lines \fIlines\fR ] [ \-columns \fIcolumns\fR ] [ \-font \fIpangofont\fR ] [ \-terminal \fIterminal\fR ] [ \-location \fIposition\fR ] [ \-fixed\-num\-lines ] [ \-padding \fIpadding\fR ] [ \-opacity \fIopacity%\fR ] [ \-display \fIdisplay\fR ] [ \-bw \fIwidth\fR ] [ \-dmenu [ \-p \fIprompt\fR ] [ \-sep \fIseparator\fR ] [ \-l \fIselected line\fR ] [ \-mesg ] [ \-select ] [ \-input \fIinput\fR ] ] [ \-filter \fIfilter\fR ] [ \-ssh\-client \fIclient\fR ] [ \-ssh\-command \fIcommand\fR ] [ \-window\-command \fIcommand\fR ] [ \-disable\-history ] [ \-levenshtein\-sort ] [ \-case\-sensitive ] [ \-cycle ] [ \-show \fImode\fR ] [ \-modi \fImode1,mode2\fR ] [ \-eh \fIelement height\fR ] [ \-lazy\-filter\-limit \fIlimit\fR ] [ \-e \fImessage\fR] [ \-a \fIrow\fR ] [ \-u \fIrow\fR ] [ \-pid \fIpath\fR ] [ \-now ] [ \-rnow ] [ \-snow ] [ \-version ] [ \-help ] [ \-dump\-xresources ] [ \-dump\-xresources\-theme ] [ \-auto\-select ] [ \-parse\-hosts ] [ \-no\-parse\-known\-hosts ] [ \-combi\-modi \fImode1,mode2\fR ] [ \-normal\-window ] [ \-fake\-transparency ] [ \-glob ] [ \-regex ] [ \-tokenize ] [ \-threads \fInum\fR ] [ \-config \fIfilename\fR ] . .SH "DESCRIPTION" \fBrofi\fR is an X11 popup window switcher, run dialog, dmenu replacement and more\. It focuses on being fast to use and have minimal distraction\. It supports keyboard and mouse navigation, type to filter, tokenized search and more\. @@ -268,6 +268,12 @@ rofi \-modi "window,run,ssh,Workspaces:i3_switch_workspaces\.sh" \-show Workspac Start in case sensitive mode\. . .P +\fB\-cycle\fR +. +.P +Cycle through the results list\. Default is 'true'\. +. +.P \fB\-fuzzy\fR . .P diff --git a/doc/test_xr.txt b/doc/test_xr.txt index ce1be8b6..0538c8bc 100644 --- a/doc/test_xr.txt +++ b/doc/test_xr.txt @@ -50,6 +50,8 @@ rofi.disable-history: false rofi.levenshtein-sort: false ! Set case-sensitivity rofi.case-sensitive: false +! Cycle through the results list +rofi.cycle: true ! Enable sidebar-mode rofi.sidebar-mode: false ! Row height (in chars) @@ -96,108 +98,108 @@ rofi.scroll-method: 0 rofi.fake-background: screenshot ! Pidfile location rofi.pid: /tmp/1000-runtime-dir/rofi.pid -! Keybinding +! Paste primary selection rofi.kb-primary-paste: Control+Shift+v,Shift+Insert -! Keybinding +! Paste clipboard rofi.kb-secondary-paste: Control+v,Insert -! Keybinding +! Clear input line rofi.kb-clear-line: Control+u -! Keybinding +! Beginning of line rofi.kb-move-front: Control+a -! Keybinding +! End of line rofi.kb-move-end: Control+e -! Keybinding +! Move back one word rofi.kb-move-word-back: Alt+b -! Keybinding +! Move forward one word rofi.kb-move-word-forward: Alt+f -! Keybinding +! Move back one char rofi.kb-move-char-back: Left,Control+b -! Keybinding +! Move forward one char rofi.kb-move-char-forward: Right,Control+f -! Keybinding +! Delete previous word rofi.kb-remove-word-back: Control+Alt+h -! Keybinding +! Delete next word rofi.kb-remove-word-forward: Control+Alt+d -! Keybinding +! Delete next char rofi.kb-remove-char-forward: Delete,Control+d -! Keybinding +! Delete previous char rofi.kb-remove-char-back: BackSpace,Control+h -! Keybinding +! Accept entry rofi.kb-accept-entry: Control+j,Control+m,Return,KP_Enter -! Keybinding +! Use entered text as command (in ssh/run modi) rofi.kb-accept-custom: Control+Return,Shift+Return -! Keybinding -rofi.kb-mode-next: Shift+Right,Control+Tab -! Keybinding -rofi.kb-mode-previous: Shift+Left,Control+Shift+Tab -! Keybinding -rofi.kb-toggle-case-sensitivity: grave,dead_grave -! Keybinding +! Delete entry from history rofi.kb-delete-entry: Shift+Delete -! Keybinding +! Switch to the next mode. +rofi.kb-mode-next: Shift+Right,Control+Tab +! Switch to the previous mode. +rofi.kb-mode-previous: Shift+Left,Control+Shift+Tab +! Go to the previous column rofi.kb-row-left: Control+Page_Up -! Keybinding +! Go to the next column rofi.kb-row-right: Control+Page_Down -! Keybinding +! Select previous entry rofi.kb-row-up: Up,Control+p,Shift+Tab -! Keybinding +! Select next entry rofi.kb-row-down: Down,Control+n -! Keybinding +! Go to next row, if one left, accept it, if no left next mode. rofi.kb-row-tab: Tab -! Keybinding +! Go to the previous page rofi.kb-page-prev: Page_Up -! Keybinding +! Go to the next page rofi.kb-page-next: Page_Down -! Keybinding +! Go to the first entry rofi.kb-row-first: Home,KP_Home -! Keybinding +! Go to the last entry rofi.kb-row-last: End,KP_End -! Keybinding +! Set selected item as input text rofi.kb-row-select: Control+space -! Keybinding -rofi.kb-cancel: Escape,Control+bracketleft -! Keybinding -rofi.kb-custom-1: Alt+1 -! Keybinding -rofi.kb-custom-2: Alt+2 -! Keybinding -rofi.kb-custom-3: Alt+3 -! Keybinding -rofi.kb-custom-4: Alt+4 -! Keybinding -rofi.kb-custom-5: Alt+5 -! Keybinding -rofi.kb-custom-6: Alt+6 -! Keybinding -rofi.kb-custom-7: Alt+7 -! Keybinding -rofi.kb-custom-8: Alt+8 -! Keybinding -rofi.kb-custom-9: Alt+9 -! Keybinding -rofi.kb-custom-10: Alt+0 -! Keybinding -rofi.kb-custom-11: Alt+Shift+1 -! Keybinding -rofi.kb-custom-12: Alt+Shift+2 -! Keybinding -rofi.kb-custom-13: Alt+Shift+3 -! Keybinding -rofi.kb-custom-14: Alt+Shift+4 -! Keybinding -rofi.kb-custom-15: Alt+Shift+5 -! Keybinding -rofi.kb-custom-16: Alt+Shift+6 -! Keybinding -rofi.kb-custom-18: Alt+Shift+8 -! Keybinding -rofi.kb-custom-17: Alt+Shift+7 -! Keybinding -rofi.kb-custom-19: Alt+Shift+9 -! Keybinding +! Take a screenshot of the rofi window rofi.kb-screenshot: Alt+Shift+S -! Keybinding +! Toggle case sensitivity +rofi.kb-toggle-case-sensitivity: grave,dead_grave +! Toggle sort rofi.kb-toggle-sort: Alt+grave +! Quit rofi +rofi.kb-cancel: Escape,Control+bracketleft +! Custom keybinding 1 +rofi.kb-custom-1: Alt+1 +! Custom keybinding 2 +rofi.kb-custom-2: Alt+2 +! Custom keybinding 3 +rofi.kb-custom-3: Alt+3 +! Custom keybinding 4 +rofi.kb-custom-4: Alt+4 +! Custom Keybinding 5 +rofi.kb-custom-5: Alt+5 +! Custom keybinding 6 +rofi.kb-custom-6: Alt+6 +! Custom Keybinding 7 +rofi.kb-custom-7: Alt+7 +! Custom keybinding 8 +rofi.kb-custom-8: Alt+8 +! Custom keybinding 9 +rofi.kb-custom-9: Alt+9 +! Custom keybinding 10 +rofi.kb-custom-10: Alt+0 +! Custom keybinding 11 +rofi.kb-custom-11: Alt+Shift+1 +! Custom keybinding 12 +rofi.kb-custom-12: Alt+Shift+2 +! Csutom keybinding 13 +rofi.kb-custom-13: Alt+Shift+3 +! Custom keybinding 14 +rofi.kb-custom-14: Alt+Shift+4 +! Custom keybinding 15 +rofi.kb-custom-15: Alt+Shift+5 +! Custom keybinding 16 +rofi.kb-custom-16: Alt+Shift+6 +! Custom keybinding 17 +rofi.kb-custom-17: Alt+Shift+7 +! Custom keybinding 18 +rofi.kb-custom-18: Alt+Shift+8 +! Custom Keybinding 19 +rofi.kb-custom-19: Alt+Shift+9 ! The display name of this browser rofi.display-ssh:  ! The display name of this browser diff --git a/include/dialogs/dialogs.h b/include/dialogs/dialogs.h index 2690bc90..8f5d09b0 100644 --- a/include/dialogs/dialogs.h +++ b/include/dialogs/dialogs.h @@ -15,4 +15,5 @@ #include "dialogs/script.h" #include "dialogs/window.h" #include "dialogs/combi.h" +#include "dialogs/help-keys.h" #endif // ROFI_DIALOGS_DIALOGS_H diff --git a/include/dialogs/help-keys.h b/include/dialogs/help-keys.h new file mode 100644 index 00000000..c7934c55 --- /dev/null +++ b/include/dialogs/help-keys.h @@ -0,0 +1,11 @@ +#ifndef ROFI_DIALOG_HELPKEYS_H +#define ROFI_DIALOG_HELPKEYS_H + +/** + * @defgroup HELPKEYSMode KeysHelp + * @ingroup MODES + * @{ + */ +extern Mode help_keys_mode; +/*@}*/ +#endif // ROFI_DIALOG_HELPKEYS_H diff --git a/include/i3-support.h b/include/i3-support.h index cc14e4ea..1d003b72 100644 --- a/include/i3-support.h +++ b/include/i3-support.h @@ -11,7 +11,6 @@ */ /** - * @param socket_path The I3 IPC socket. * @param id The window to focus on. * * If we want to switch windows in I3, we use I3 IPC mode. @@ -22,7 +21,7 @@ void i3_support_focus_window ( xcb_window_t id ); /** - * @param display The display to read the i3 property from. + * @param xcb The xcb to read the i3 property from. * * Get the i3 socket from the X root window. * @returns TRUE when i3 is running, FALSE when not. diff --git a/include/mode.h b/include/mode.h index 1a0d9b01..4cd2244d 100644 --- a/include/mode.h +++ b/include/mode.h @@ -66,7 +66,7 @@ int mode_init ( Mode *mode ); void mode_destroy ( Mode *mode ); /** - * @param mode The mode to query + * @param sw The mode to query * * Get the number of entries in the mode. * diff --git a/include/settings.h b/include/settings.h index 4ac38af8..848d8a6b 100644 --- a/include/settings.h +++ b/include/settings.h @@ -90,6 +90,8 @@ typedef struct unsigned int levenshtein_sort; /** Search case sensitivity */ unsigned int case_sensitive; + /** Cycle through in the element list */ + unsigned int cycle; /** Height of an element in number of rows */ int element_height; /** Sidebar mode, show the modi */ diff --git a/include/xrmoptions.h b/include/xrmoptions.h index e8967158..218015f7 100644 --- a/include/xrmoptions.h +++ b/include/xrmoptions.h @@ -142,5 +142,7 @@ void print_options ( void ); */ void print_help_msg ( const char *option, const char *type, const char*text, const char *def, int isatty ); +char ** config_parser_return_display_help ( unsigned int *length ); + /* @}*/ #endif diff --git a/libgwater b/libgwater index 75581cad..173f2f55 160000 --- a/libgwater +++ b/libgwater @@ -1 +1 @@ -Subproject commit 75581cadfe6206c35b4229a8848f4faf5c745d54 +Subproject commit 173f2f5566636a1de559cc57f3154db70c3f2e9f diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index fcab4f0e..f0ffd551 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -220,7 +220,7 @@ static void get_apps_dir ( DRunModePrivateData *pd, const char *bp ) } } /** - * @param cmd The command to remove from history + * @param entry The command entry to remove from history * * Remove command from history. */ diff --git a/source/dialogs/help-keys.c b/source/dialogs/help-keys.c new file mode 100644 index 00000000..dc0955e6 --- /dev/null +++ b/source/dialogs/help-keys.c @@ -0,0 +1,134 @@ +/** + * rofi + * + * MIT/X11 License + * Copyright 2013-2016 Qball Cow + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rofi.h" +#include "settings.h" +#include "helper.h" +#include "xrmoptions.h" +#include "dialogs/help-keys.h" +#include "textbox.h" + +typedef struct +{ + char **messages; + unsigned int messages_length; +} KeysHelpModePrivateData; + +static void get_apps ( KeysHelpModePrivateData *pd ) +{ + pd->messages = config_parser_return_display_help ( &( pd->messages_length ) ); +} + +static int help_keys_mode_init ( Mode *sw ) +{ + if ( mode_get_private_data ( sw ) == NULL ) { + KeysHelpModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); + mode_set_private_data ( sw, (void *) pd ); + get_apps ( pd ); + } + return TRUE; +} + +static ModeMode help_keys_mode_result ( G_GNUC_UNUSED Mode *sw, + int mretv, + G_GNUC_UNUSED char **input, + G_GNUC_UNUSED unsigned int selected_line ) +{ + ModeMode retv = MODE_EXIT; + + if ( mretv & MENU_NEXT ) { + retv = NEXT_DIALOG; + } + else if ( mretv & MENU_PREVIOUS ) { + retv = PREVIOUS_DIALOG; + } + else if ( mretv & MENU_QUICK_SWITCH ) { + retv = ( mretv & MENU_LOWER_MASK ); + } + return retv; +} +static void help_keys_mode_destroy ( Mode *sw ) +{ + KeysHelpModePrivateData *rmpd = (KeysHelpModePrivateData *) mode_get_private_data ( sw ); + if ( rmpd != NULL ) { + g_strfreev ( rmpd->messages ); + g_free ( rmpd ); + mode_set_private_data ( sw, NULL ); + } +} + +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, int get_entry ) +{ + KeysHelpModePrivateData *pd = (KeysHelpModePrivateData *) mode_get_private_data ( sw ); + *state |= MARKUP; + if ( !get_entry ) { + return NULL; + } + return g_strdup ( pd->messages[selected_line] ); +} +static int help_keys_token_match ( const Mode *data, + GRegex **tokens, + unsigned int index + ) +{ + KeysHelpModePrivateData *rmpd = (KeysHelpModePrivateData *) mode_get_private_data ( data ); + return token_match ( tokens, rmpd->messages[index] ); +} + +static unsigned int help_keys_mode_get_num_entries ( const Mode *sw ) +{ + const KeysHelpModePrivateData *pd = (const KeysHelpModePrivateData *) mode_get_private_data ( sw ); + return pd->messages_length; +} + +#include "mode-private.h" +Mode help_keys_mode = +{ + .name = "keys", + .cfg_name_key = "display-keys", + ._init = help_keys_mode_init, + ._get_num_entries = help_keys_mode_get_num_entries, + ._result = help_keys_mode_result, + ._destroy = help_keys_mode_destroy, + ._token_match = help_keys_token_match, + ._get_completion = NULL, + ._get_display_value = _get_display_value, + .private_data = NULL, + .free = NULL +}; diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 56ff8d01..d56e76f0 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -367,6 +367,22 @@ static unsigned int window_mode_get_num_entries ( const Mode *sw ) const ModeModePrivateData *pd = (const ModeModePrivateData *) mode_get_private_data ( sw ); return pd->cmd_list_length; } +/** + * Small helper function to find the right entry in the ewmh reply. + * Is there a call for this? + */ +static const char * _window_name_list_entry ( const char *str, uint32_t length, int entry ) +{ + uint32_t offset = 0; + int index = 0; + while ( index < entry && offset < length ) { + if ( str[offset] == 0 ) { + index++; + } + offset++; + } + return &str[offset]; +} static void _window_mode_load_data ( Mode *sw, unsigned int cd ) { ModeModePrivateData *pd = (ModeModePrivateData *) mode_get_private_data ( sw ); @@ -455,6 +471,12 @@ static void _window_mode_load_data ( Mode *sw, unsigned int cd ) } pd->cmd_list = g_malloc0_n ( ( pd->ids->len + 1 ), sizeof ( char* ) ); + c = xcb_ewmh_get_desktop_names ( &xcb->ewmh, xcb->screen_nbr ); + xcb_ewmh_get_utf8_strings_reply_t names; + int has_names = FALSE; + if ( xcb_ewmh_get_desktop_names_reply ( &xcb->ewmh, c, &names, NULL ) ) { + has_names = TRUE; + } // build the actual list for ( i = 0; i < ( pd->ids->len ); i++ ) { xcb_window_t w = pd->ids->array[i]; @@ -462,11 +484,8 @@ static void _window_mode_load_data ( Mode *sw, unsigned int cd ) if ( ( c = window_client ( w ) ) ) { // final line format - char desktop[5]; - desktop[0] = 0; - size_t len = - ( ( c->title != NULL ) ? strlen ( c->title ) : 0 ) + ( c->class ? strlen ( c->class ) : 0 ) + classfield + 50; - char *line = g_malloc ( len ); + char *desktop = NULL; + char *line = NULL; if ( !pd->config_i3_mode ) { uint32_t wmdesktop = 0; // find client's desktop. @@ -492,18 +511,29 @@ static void _window_mode_load_data ( Mode *sw, unsigned int cd ) free ( r ); if ( wmdesktop < 0xFFFFFFFF ) { - snprintf ( desktop, 5, "%u", (uint32_t) wmdesktop ); + if ( has_names ) { + desktop = g_strdup_printf ( "%s", _window_name_list_entry ( names.strings, names.strings_len, wmdesktop ) ); + } + else { + desktop = g_strdup_printf ( "%u", (uint32_t) wmdesktop ); + } + } + else { + desktop = g_strdup ( "" ); } - snprintf ( line, len, pattern, desktop, c->class ? c->class : "", c->title ? c->title : "" ); + line = g_strdup_printf ( pattern, desktop, c->class ? c->class : "", c->title ? c->title : "" ); } else{ - snprintf ( line, len, pattern, c->class ? c->class : "", c->title ? c->title : "" ); + line = g_strdup_printf ( pattern, c->class ? c->class : "", c->title ? c->title : "" ); } - + g_free ( desktop ); pd->cmd_list[pd->cmd_list_length++] = line; } } + if ( has_names ) { + xcb_ewmh_get_utf8_strings_reply_wipe ( &names ); + } } } static int window_mode_init ( Mode *sw ) diff --git a/source/history.c b/source/history.c index 3b2de37a..d404d36b 100644 --- a/source/history.c +++ b/source/history.c @@ -99,7 +99,7 @@ static _element ** __history_get_element_list ( FILE *fd, unsigned int *length ) continue; } start++; - if ( ( l - ( start - buffer ) ) < 3 ) { + if ( ( l - ( start - buffer ) ) < 2 ) { continue; } // Resize and check. diff --git a/source/keyb.c b/source/keyb.c index c0e3bc5a..5ef27029 100644 --- a/source/keyb.c +++ b/source/keyb.c @@ -24,6 +24,7 @@ typedef struct KeyBindingAction id; char *name; char *keybinding; + char *comment; } DefaultBinding; ActionBindingEntry abe[NUM_ABE]; @@ -33,57 +34,57 @@ ActionBindingEntry abe[NUM_ABE]; */ DefaultBinding bindings[NUM_ABE] = { - { .id = PASTE_PRIMARY, .name = "kb-primary-paste", .keybinding = "Control+Shift+v,Shift+Insert", }, - { .id = PASTE_SECONDARY, .name = "kb-secondary-paste", .keybinding = "Control+v,Insert", }, - { .id = CLEAR_LINE, .name = "kb-clear-line", .keybinding = "Control+u", }, - { .id = MOVE_FRONT, .name = "kb-move-front", .keybinding = "Control+a", }, - { .id = MOVE_END, .name = "kb-move-end", .keybinding = "Control+e", }, - { .id = MOVE_WORD_BACK, .name = "kb-move-word-back", .keybinding = "Alt+b", }, - { .id = MOVE_WORD_FORWARD, .name = "kb-move-word-forward", .keybinding = "Alt+f", }, - { .id = MOVE_CHAR_BACK, .name = "kb-move-char-back", .keybinding = "Left,Control+b" }, - { .id = MOVE_CHAR_FORWARD, .name = "kb-move-char-forward", .keybinding = "Right,Control+f" }, - { .id = REMOVE_WORD_BACK, .name = "kb-remove-word-back", .keybinding = "Control+Alt+h", }, - { .id = REMOVE_WORD_FORWARD, .name = "kb-remove-word-forward", .keybinding = "Control+Alt+d", }, - { .id = REMOVE_CHAR_FORWARD, .name = "kb-remove-char-forward", .keybinding = "Delete,Control+d", }, - { .id = REMOVE_CHAR_BACK, .name = "kb-remove-char-back", .keybinding = "BackSpace,Control+h", }, - { .id = ACCEPT_ENTRY, .name = "kb-accept-entry", .keybinding = "Control+j,Control+m,Return,KP_Enter", }, - { .id = ACCEPT_CUSTOM, .name = "kb-accept-custom", .keybinding = "Control+Return,Shift+Return", }, - { .id = MODE_NEXT, .name = "kb-mode-next", .keybinding = "Shift+Right,Control+Tab" }, - { .id = MODE_PREVIOUS, .name = "kb-mode-previous", .keybinding = "Shift+Left,Control+Shift+Tab" }, - { .id = TOGGLE_CASE_SENSITIVITY, .name = "kb-toggle-case-sensitivity", .keybinding = "grave,dead_grave" }, - { .id = DELETE_ENTRY, .name = "kb-delete-entry", .keybinding = "Shift+Delete" }, - { .id = ROW_LEFT, .name = "kb-row-left", .keybinding = "Control+Page_Up" }, - { .id = ROW_RIGHT, .name = "kb-row-right", .keybinding = "Control+Page_Down" }, - { .id = ROW_UP, .name = "kb-row-up", .keybinding = "Up,Control+p,Shift+Tab,Shift+ISO_Left_Tab" }, - { .id = ROW_DOWN, .name = "kb-row-down", .keybinding = "Down,Control+n" }, - { .id = ROW_TAB, .name = "kb-row-tab", .keybinding = "Tab" }, - { .id = PAGE_PREV, .name = "kb-page-prev", .keybinding = "Page_Up" }, - { .id = PAGE_NEXT, .name = "kb-page-next", .keybinding = "Page_Down" }, - { .id = ROW_FIRST, .name = "kb-row-first", .keybinding = "Home,KP_Home" }, - { .id = ROW_LAST, .name = "kb-row-last", .keybinding = "End,KP_End" }, - { .id = ROW_SELECT, .name = "kb-row-select", .keybinding = "Control+space" }, - { .id = CANCEL, .name = "kb-cancel", .keybinding = "Escape,Control+bracketleft" }, - { .id = CUSTOM_1, .name = "kb-custom-1", .keybinding = "Alt+1" }, - { .id = CUSTOM_2, .name = "kb-custom-2", .keybinding = "Alt+2" }, - { .id = CUSTOM_3, .name = "kb-custom-3", .keybinding = "Alt+3" }, - { .id = CUSTOM_4, .name = "kb-custom-4", .keybinding = "Alt+4" }, - { .id = CUSTOM_5, .name = "kb-custom-5", .keybinding = "Alt+5" }, - { .id = CUSTOM_6, .name = "kb-custom-6", .keybinding = "Alt+6" }, - { .id = CUSTOM_7, .name = "kb-custom-7", .keybinding = "Alt+7" }, - { .id = CUSTOM_8, .name = "kb-custom-8", .keybinding = "Alt+8" }, - { .id = CUSTOM_9, .name = "kb-custom-9", .keybinding = "Alt+9" }, - { .id = CUSTOM_10, .name = "kb-custom-10", .keybinding = "Alt+0" }, - { .id = CUSTOM_11, .name = "kb-custom-11", .keybinding = "Alt+Shift+1" }, - { .id = CUSTOM_12, .name = "kb-custom-12", .keybinding = "Alt+Shift+2" }, - { .id = CUSTOM_13, .name = "kb-custom-13", .keybinding = "Alt+Shift+3" }, - { .id = CUSTOM_14, .name = "kb-custom-14", .keybinding = "Alt+Shift+4" }, - { .id = CUSTOM_15, .name = "kb-custom-15", .keybinding = "Alt+Shift+5" }, - { .id = CUSTOM_16, .name = "kb-custom-16", .keybinding = "Alt+Shift+6" }, - { .id = CUSTOM_18, .name = "kb-custom-18", .keybinding = "Alt+Shift+8" }, - { .id = CUSTOM_17, .name = "kb-custom-17", .keybinding = "Alt+Shift+7" }, - { .id = CUSTOM_19, .name = "kb-custom-19", .keybinding = "Alt+Shift+9" }, - { .id = SCREENSHOT, .name = "kb-screenshot", .keybinding = "Alt+Shift+S" }, - { .id = TOGGLE_SORT, .name = "kb-toggle-sort", .keybinding = "Alt+grave" }, + { .id = PASTE_PRIMARY, .name = "kb-primary-paste", .keybinding = "Control+Shift+v,Shift+Insert", .comment = "Paste primary selection" }, + { .id = PASTE_SECONDARY, .name = "kb-secondary-paste", .keybinding = "Control+v,Insert", .comment = "Paste clipboard" }, + { .id = CLEAR_LINE, .name = "kb-clear-line", .keybinding = "Control+u", .comment = "Clear input line" }, + { .id = MOVE_FRONT, .name = "kb-move-front", .keybinding = "Control+a", .comment = "Beginning of line" }, + { .id = MOVE_END, .name = "kb-move-end", .keybinding = "Control+e", .comment = "End of line" }, + { .id = MOVE_WORD_BACK, .name = "kb-move-word-back", .keybinding = "Alt+b", .comment = "Move back one word" }, + { .id = MOVE_WORD_FORWARD, .name = "kb-move-word-forward", .keybinding = "Alt+f", .comment = "Move forward one word" }, + { .id = MOVE_CHAR_BACK, .name = "kb-move-char-back", .keybinding = "Left,Control+b", .comment = "Move back one char" }, + { .id = MOVE_CHAR_FORWARD, .name = "kb-move-char-forward", .keybinding = "Right,Control+f", .comment = "Move forward one char" }, + { .id = REMOVE_WORD_BACK, .name = "kb-remove-word-back", .keybinding = "Control+Alt+h", .comment = "Delete previous word" }, + { .id = REMOVE_WORD_FORWARD, .name = "kb-remove-word-forward", .keybinding = "Control+Alt+d", .comment = "Delete next word" }, + { .id = REMOVE_CHAR_FORWARD, .name = "kb-remove-char-forward", .keybinding = "Delete,Control+d", .comment = "Delete next char" }, + { .id = REMOVE_CHAR_BACK, .name = "kb-remove-char-back", .keybinding = "BackSpace,Control+h", .comment = "Delete previous char" }, + { .id = ACCEPT_ENTRY, .name = "kb-accept-entry", .keybinding = "Control+j,Control+m,Return,KP_Enter", .comment = "Accept entry" }, + { .id = ACCEPT_CUSTOM, .name = "kb-accept-custom", .keybinding = "Control+Return,Shift+Return", .comment = "Use entered text as command (in ssh/run modi)" }, + { .id = DELETE_ENTRY, .name = "kb-delete-entry", .keybinding = "Shift+Delete", .comment = "Delete entry from history" }, + { .id = MODE_NEXT, .name = "kb-mode-next", .keybinding = "Shift+Right,Control+Tab", .comment = "Switch to the next mode." }, + { .id = MODE_PREVIOUS, .name = "kb-mode-previous", .keybinding = "Shift+Left,Control+Shift+Tab", .comment = "Switch to the previous mode." }, + { .id = ROW_LEFT, .name = "kb-row-left", .keybinding = "Control+Page_Up", .comment = "Go to the previous column" }, + { .id = ROW_RIGHT, .name = "kb-row-right", .keybinding = "Control+Page_Down", .comment = "Go to the next column" }, + { .id = ROW_UP, .name = "kb-row-up", .keybinding = "Up,Control+p,Shift+Tab,Shift+ISO_Left_Tab", .comment = "Select previous entry" }, + { .id = ROW_DOWN, .name = "kb-row-down", .keybinding = "Down,Control+n,Tab", .comment = "Select next entry" }, + { .id = ROW_TAB, .name = "kb-row-tab", .keybinding = "Tab", .comment = "Go to next row, if one left, accept it, if no left next mode." }, + { .id = PAGE_PREV, .name = "kb-page-prev", .keybinding = "Page_Up", .comment = "Go to the previous page" }, + { .id = PAGE_NEXT, .name = "kb-page-next", .keybinding = "Page_Down", .comment = "Go to the next page" }, + { .id = ROW_FIRST, .name = "kb-row-first", .keybinding = "Home,KP_Home", .comment = "Go to the first entry" }, + { .id = ROW_LAST, .name = "kb-row-last", .keybinding = "End,KP_End", .comment = "Go to the last entry" }, + { .id = ROW_SELECT, .name = "kb-row-select", .keybinding = "Control+space", .comment = "Set selected item as input text" }, + { .id = SCREENSHOT, .name = "kb-screenshot", .keybinding = "Alt+Shift+S", .comment = "Take a screenshot of the rofi window" }, + { .id = TOGGLE_CASE_SENSITIVITY, .name = "kb-toggle-case-sensitivity", .keybinding = "grave,dead_grave", .comment = "Toggle case sensitivity" }, + { .id = TOGGLE_SORT, .name = "kb-toggle-sort", .keybinding = "Alt+grave", .comment = "Toggle sort" }, + { .id = CANCEL, .name = "kb-cancel", .keybinding = "Escape,Control+bracketleft", .comment = "Quit rofi" }, + { .id = CUSTOM_1, .name = "kb-custom-1", .keybinding = "Alt+1", .comment = "Custom keybinding 1" }, + { .id = CUSTOM_2, .name = "kb-custom-2", .keybinding = "Alt+2", .comment = "Custom keybinding 2" }, + { .id = CUSTOM_3, .name = "kb-custom-3", .keybinding = "Alt+3", .comment = "Custom keybinding 3" }, + { .id = CUSTOM_4, .name = "kb-custom-4", .keybinding = "Alt+4", .comment = "Custom keybinding 4" }, + { .id = CUSTOM_5, .name = "kb-custom-5", .keybinding = "Alt+5", .comment = "Custom Keybinding 5" }, + { .id = CUSTOM_6, .name = "kb-custom-6", .keybinding = "Alt+6", .comment = "Custom keybinding 6" }, + { .id = CUSTOM_7, .name = "kb-custom-7", .keybinding = "Alt+7", .comment = "Custom Keybinding 7" }, + { .id = CUSTOM_8, .name = "kb-custom-8", .keybinding = "Alt+8", .comment = "Custom keybinding 8" }, + { .id = CUSTOM_9, .name = "kb-custom-9", .keybinding = "Alt+9", .comment = "Custom keybinding 9" }, + { .id = CUSTOM_10, .name = "kb-custom-10", .keybinding = "Alt+0", .comment = "Custom keybinding 10" }, + { .id = CUSTOM_11, .name = "kb-custom-11", .keybinding = "Alt+Shift+1", .comment = "Custom keybinding 11" }, + { .id = CUSTOM_12, .name = "kb-custom-12", .keybinding = "Alt+Shift+2", .comment = "Custom keybinding 12" }, + { .id = CUSTOM_13, .name = "kb-custom-13", .keybinding = "Alt+Shift+3", .comment = "Csutom keybinding 13" }, + { .id = CUSTOM_14, .name = "kb-custom-14", .keybinding = "Alt+Shift+4", .comment = "Custom keybinding 14" }, + { .id = CUSTOM_15, .name = "kb-custom-15", .keybinding = "Alt+Shift+5", .comment = "Custom keybinding 15" }, + { .id = CUSTOM_16, .name = "kb-custom-16", .keybinding = "Alt+Shift+6", .comment = "Custom keybinding 16" }, + { .id = CUSTOM_17, .name = "kb-custom-17", .keybinding = "Alt+Shift+7", .comment = "Custom keybinding 17" }, + { .id = CUSTOM_18, .name = "kb-custom-18", .keybinding = "Alt+Shift+8", .comment = "Custom keybinding 18" }, + { .id = CUSTOM_19, .name = "kb-custom-19", .keybinding = "Alt+Shift+9", .comment = "Custom Keybinding 19" }, }; void setup_abe ( void ) @@ -96,7 +97,7 @@ void setup_abe ( void ) abe[id].num_bindings = 0; abe[id].kb = NULL; - config_parser_add_option ( xrm_String, abe[id].name, (void * *) &( abe[id].keystr ), "Keybinding" ); + config_parser_add_option ( xrm_String, abe[id].name, (void * *) &( abe[id].keystr ), bindings[iter].comment ); } } diff --git a/source/rofi.c b/source/rofi.c index 474deebb..9910ebd8 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -282,7 +282,7 @@ static void cleanup () rofi_view_workers_finalize (); if ( main_loop != NULL ) { if ( main_loop_source ) { - g_water_xcb_source_unref ( main_loop_source ); + g_water_xcb_source_free ( main_loop_source ); } g_main_loop_unref ( main_loop ); main_loop = NULL; @@ -334,6 +334,10 @@ static int add_mode ( const char * token ) modi[num_modi] = &ssh_mode; num_modi++; } + else if ( strcasecmp ( token, mode_get_name ( &help_keys_mode ) ) == 0 ) { + modi[num_modi] = &help_keys_mode; + num_modi++; + } // Run dialog else if ( strcasecmp ( token, "run" ) == 0 ) { modi[num_modi] = &run_mode; @@ -389,7 +393,6 @@ static void setup_modi ( void ) } /** - * @param display Pointer to the X connection to use. * Load configuration. * Following priority: (current), X, commandline arguments */ diff --git a/source/view.c b/source/view.c index 6a565aab..f88259f0 100644 --- a/source/view.c +++ b/source/view.c @@ -180,10 +180,7 @@ static void menu_capture_screenshot ( void ) } /** - * @param state the state of the View. - * @param mon the work area. - * - * Calculates the window poslition + * Calculates the window position */ static void calculate_window_position ( void ) { @@ -792,14 +789,16 @@ inline static void rofi_view_nav_left ( RofiViewState *state ) */ inline static void rofi_view_nav_up ( RofiViewState *state ) { + // If no lines or don't cycle, do nothing. + if ( state->filtered_lines == 0 || ( state->selected == 0 && !config.cycle ) ) { + return; + } + // Wrap around. if ( state->selected == 0 ) { state->selected = state->filtered_lines; } - - if ( state->selected > 0 ) { - state->selected--; - } + state->selected--; state->update = TRUE; } @@ -811,8 +810,8 @@ inline static void rofi_view_nav_up ( RofiViewState *state ) */ inline static void rofi_view_nav_down ( RofiViewState *state ) { - // If no lines, do nothing. - if ( state->filtered_lines == 0 ) { + // If no lines or don't cycle, do nothing. + if ( state->filtered_lines == 0 || ( state->selected == state->filtered_lines - 1 && !config.cycle ) ) { return; } state->selected = state->selected < state->filtered_lines - 1 ? MIN ( state->filtered_lines - 1, state->selected + 1 ) : 0; @@ -1116,10 +1115,9 @@ static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t /** * @param state Internal state of the menu. - * @param key the Key being pressed. - * @param modstate the modifier state. + * @param action The action to perform. * - * Keyboard navigation through the elements. + * Perform keyboard navigation action. */ static void rofi_view_keyboard_navigation ( RofiViewState *state, KeyBindingAction action ) { diff --git a/source/xrmoptions.c b/source/xrmoptions.c index 66a1494a..63bf12c5 100644 --- a/source/xrmoptions.c +++ b/source/xrmoptions.c @@ -125,6 +125,8 @@ static XrmOption xrmOptions[] = { "Use levenshtein sorting" }, { xrm_Boolean, "case-sensitive", { .num = &config.case_sensitive }, NULL, "Set case-sensitivity" }, + { xrm_Boolean, "cycle", { .num = &config.cycle }, NULL, + "Cycle through the results list" }, { xrm_Boolean, "sidebar-mode", { .num = &config.sidebar_mode }, NULL, "Enable sidebar-mode" }, { xrm_SNumber, "eh", { .snum = &config.element_height }, NULL, @@ -594,3 +596,71 @@ void config_parse_xresource_init ( void ) { XrmInitialize (); } + +static char * config_parser_return_display_help_entry ( XrmOption *option ) +{ + switch ( option->type ) + { + case xrm_Number: + return g_markup_printf_escaped ( " (%u) %s", + option->name, *( option->value.num ), option->comment ); + case xrm_SNumber: + return g_markup_printf_escaped ( " (%d) %s", + option->name, *( option->value.snum ), option->comment ); + case xrm_String: + return g_markup_printf_escaped ( "%s (%s) %s", + option->name, + ( *( option->value.str ) != NULL ) ? *( option->value.str ) : "null", + option->comment + ); + case xrm_Boolean: + return g_markup_printf_escaped ( "%s (%s) %s", + option->name, ( *( option->value.num ) == TRUE ) ? "true" : "false", option->comment ); + case xrm_Char: + if ( *( option->value.charc ) > 32 && *( option->value.charc ) < 127 ) { + return g_markup_printf_escaped ( "%s (%c) %s", + option->name, *( option->value.charc ), option->comment ); + } + else { + return g_markup_printf_escaped ( " (\\x%02X) %s", + option->name, *( option->value.charc ), option->comment ); + } + default: + break; + } + + return g_strdup ( "failed" ); +} + +char ** config_parser_return_display_help ( unsigned int *length ) +{ + unsigned int entries = sizeof ( xrmOptions ) / sizeof ( *xrmOptions ); + char **retv = NULL; + for ( unsigned int i = 0; i < entries; ++i ) { + if ( ( i + 1 ) < entries ) { + if ( xrmOptions[i].value.str == xrmOptions[i + 1].value.str ) { + continue; + } + } + if ( strncmp ( xrmOptions[i].name, "kb", 2 ) != 0 ) { + continue; + } + + retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) ); + + retv[( *length )] = config_parser_return_display_help_entry ( &xrmOptions[i] ); + ( *length )++; + } + for ( unsigned int i = 0; i < num_extra_options; i++ ) { + if ( strncmp ( extra_options[i].name, "kb", 2 ) != 0 ) { + continue; + } + retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) ); + retv[( *length )] = config_parser_return_display_help_entry ( &extra_options[i] ); + ( *length )++; + } + if ( ( *length ) > 0 ) { + retv[( *length )] = NULL; + } + return retv; +} diff --git a/test/widget-test.c b/test/widget-test.c new file mode 100644 index 00000000..c49ec690 --- /dev/null +++ b/test/widget-test.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +unsigned int test =0; +#define TASSERT( a ) { \ + assert ( a ); \ + printf ( "Test %3i passed (%s)\n", ++test, # a ); \ +} + + +int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) +{ +// box 20 by 40 + Widget widget = { 10,10,20,40 }; + + // Left of box + TASSERT ( widget_intersect ( &widget, 0, 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 0, 10) == 0 ); + TASSERT ( widget_intersect ( &widget, 0, 25) == 0 ); + TASSERT ( widget_intersect ( &widget, 0, 40) == 0 ); + TASSERT ( widget_intersect ( &widget, 0, 50) == 0 ); + TASSERT ( widget_intersect ( &widget, 9, 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 9, 10) == 0 ); + TASSERT ( widget_intersect ( &widget, 9, 25) == 0 ); + TASSERT ( widget_intersect ( &widget, 9, 40) == 0 ); + TASSERT ( widget_intersect ( &widget, 9, 50) == 0 ); + TASSERT ( widget_intersect ( &widget, 10, 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 10, 10) == 1 ); + TASSERT ( widget_intersect ( &widget, 10, 25) == 1 ); + TASSERT ( widget_intersect ( &widget, 10, 40) == 1 ); + TASSERT ( widget_intersect ( &widget, 10, 50) == 0 ); + + // Middle + + TASSERT ( widget_intersect ( &widget, 25, 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 25, 10) == 1 ); + TASSERT ( widget_intersect ( &widget, 25, 25) == 1 ); + TASSERT ( widget_intersect ( &widget, 25, 40) == 1 ); + TASSERT ( widget_intersect ( &widget, 25, 50) == 0 ); + + // Right + TASSERT ( widget_intersect ( &widget, 29, 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 29, 10) == 1 ); + TASSERT ( widget_intersect ( &widget, 29, 25) == 1 ); + TASSERT ( widget_intersect ( &widget, 29, 40) == 1 ); + TASSERT ( widget_intersect ( &widget, 29, 50) == 0 ); + + TASSERT ( widget_intersect ( &widget, 30, 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 30, 10) == 0 ); + TASSERT ( widget_intersect ( &widget, 30, 25) == 0 ); + TASSERT ( widget_intersect ( &widget, 30, 40) == 0 ); + TASSERT ( widget_intersect ( &widget, 30, 50) == 0 ); + + widget_move ( &widget, 30, 30); + // Left of box + TASSERT ( widget_intersect ( &widget, 10, 20) == 0 ); + TASSERT ( widget_intersect ( &widget, 10, 30) == 0 ); + TASSERT ( widget_intersect ( &widget, 10, 45) == 0 ); + TASSERT ( widget_intersect ( &widget, 10, 60) == 0 ); + TASSERT ( widget_intersect ( &widget, 10, 70) == 0 ); + TASSERT ( widget_intersect ( &widget, 19, 20) == 0 ); + TASSERT ( widget_intersect ( &widget, 19, 30) == 0 ); + TASSERT ( widget_intersect ( &widget, 19, 45) == 0 ); + TASSERT ( widget_intersect ( &widget, 19, 60) == 0 ); + TASSERT ( widget_intersect ( &widget, 19, 70) == 0 ); + TASSERT ( widget_intersect ( &widget, 30, 20) == 0 ); + TASSERT ( widget_intersect ( &widget, 30, 30) == 1 ); + TASSERT ( widget_intersect ( &widget, 30, 45) == 1 ); + TASSERT ( widget_intersect ( &widget, 30, 60) == 1 ); + TASSERT ( widget_intersect ( &widget, 30, 70) == 0 ); + + // Middle + + TASSERT ( widget_intersect ( &widget, 20+25,20+ 0) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+25,20+ 10) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+25,20+ 25) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+25,20+ 40) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+25,20+ 50) == 0 ); + + TASSERT ( widget_intersect ( &widget, 20+29, 20+0) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+10) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+25) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+40) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+50) == 0 ); + + TASSERT ( widget_intersect ( &widget, 20+30, 20+0) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+10) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+25) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+40) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+50) == 0 ); + + // Right + TASSERT ( widget_intersect ( &widget, 20+29, 20+0) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+10) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+25) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+40) == 1 ); + TASSERT ( widget_intersect ( &widget, 20+29, 20+50) == 0 ); + + TASSERT ( widget_intersect ( &widget, 20+30, 20+0) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+10) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+25) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+40) == 0 ); + TASSERT ( widget_intersect ( &widget, 20+30, 20+50) == 0 ); + + TASSERT ( widget_intersect ( NULL, 0, 0) == 0 ); + + TASSERT ( widget_intersect ( &widget, -100, -100) == 0); + TASSERT ( widget_intersect ( &widget, INT_MIN, INT_MIN) == 0); + TASSERT ( widget_intersect ( &widget, INT_MAX, INT_MAX) == 0); +}