summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2019-10-17 21:19:19 +0200
committerDave Davenport <qball@gmpclient.org>2019-10-17 21:19:19 +0200
commitaeecf34c279bbbf035f6d7be179d37936c5fe1a6 (patch)
tree5223f52349a23b57c655742ef308ad9d60b9bd5d
parent8590a7ccf2f73552a0501fa39c54cceae1f2f79c (diff)
[Window] Add thumbnail of windows as option.
-rw-r--r--config/config.c1
-rw-r--r--doc/default_theme.rasi70
-rw-r--r--doc/old-theme-convert-output.rasi70
-rw-r--r--doc/test_xr.txt2
-rw-r--r--include/settings.h3
-rw-r--r--include/xcb.h9
-rw-r--r--source/dialogs/window.c7
-rw-r--r--source/xcb.c68
-rw-r--r--source/xrmoptions.c2
9 files changed, 161 insertions, 71 deletions
diff --git a/config/config.c b/config/config.c
index 32d13228..c885447e 100644
--- a/config/config.c
+++ b/config/config.c
@@ -159,4 +159,5 @@ Settings config = {
.matching_negate_char = '-',
.cache_dir = NULL,
+ .window_thumbnail = FALSE,
};
diff --git a/doc/default_theme.rasi b/doc/default_theme.rasi
index 65736b08..345749c0 100644
--- a/doc/default_theme.rasi
+++ b/doc/default_theme.rasi
@@ -2,39 +2,39 @@
* rofi -dump-theme output.
**/
* {
- selected-normal-foreground: var(lightbg);
- foreground: rgba ( 0, 43, 54, 100 % );
- normal-foreground: var(foreground);
- alternate-normal-background: var(lightbg);
red: rgba ( 220, 50, 47, 100 % );
- selected-urgent-foreground: var(background);
- blue: rgba ( 38, 139, 210, 100 % );
+ selected-active-foreground: var(background);
+ lightfg: rgba ( 88, 104, 117, 100 % );
+ separatorcolor: var(foreground);
urgent-foreground: var(red);
alternate-urgent-background: var(lightbg);
- active-foreground: var(blue);
lightbg: rgba ( 238, 232, 213, 100 % );
- selected-active-foreground: var(background);
- alternate-active-background: var(lightbg);
- background: rgba ( 253, 246, 227, 100 % );
- alternate-normal-foreground: var(foreground);
- normal-background: var(background);
- lightfg: rgba ( 88, 104, 117, 100 % );
- selected-normal-background: var(lightfg);
- border-color: var(foreground);
spacing: 2;
- separatorcolor: var(foreground);
+ border-color: var(foreground);
+ normal-background: var(background);
+ background-color: rgba ( 0, 0, 0, 0 % );
+ alternate-active-background: var(lightbg);
+ active-foreground: var(blue);
+ blue: rgba ( 38, 139, 210, 100 % );
urgent-background: var(background);
+ alternate-normal-foreground: var(foreground);
+ selected-active-background: var(blue);
+ background: rgba ( 253, 246, 227, 100 % );
+ selected-normal-foreground: var(lightbg);
+ active-background: var(background);
+ alternate-active-foreground: var(blue);
+ alternate-normal-background: var(lightbg);
+ foreground: rgba ( 0, 43, 54, 100 % );
selected-urgent-background: var(red);
+ selected-urgent-foreground: var(background);
+ normal-foreground: var(foreground);
alternate-urgent-foreground: var(red);
- background-color: rgba ( 0, 0, 0, 0 % );
- alternate-active-foreground: var(blue);
- active-background: var(background);
- selected-active-background: var(blue);
+ selected-normal-background: var(lightfg);
}
element {
- border: 0;
- spacing: 5px ;
padding: 1px ;
+ spacing: 5px ;
+ border: 0;
}
element normal.normal {
background-color: var(normal-background);
@@ -82,40 +82,40 @@ element-icon {
text-color: inherit;
}
window {
+ padding: 5;
background-color: var(background);
border: 1;
- padding: 5;
}
mainbox {
- border: 0;
padding: 0;
+ border: 0;
}
message {
- border: 2px dash 0px 0px ;
- border-color: var(separatorcolor);
padding: 1px ;
+ border-color: var(separatorcolor);
+ border: 2px dash 0px 0px ;
}
textbox {
text-color: var(foreground);
}
listview {
- fixed-height: 0;
- border: 2px dash 0px 0px ;
+ padding: 2px 0px 0px ;
+ scrollbar: true;
border-color: var(separatorcolor);
spacing: 2px ;
- scrollbar: true;
- padding: 2px 0px 0px ;
+ fixed-height: 0;
+ border: 2px dash 0px 0px ;
}
scrollbar {
width: 4px ;
+ padding: 0;
+ handle-width: 8px ;
border: 0;
handle-color: var(normal-foreground);
- handle-width: 8px ;
- padding: 0;
}
sidebar {
- border: 2px dash 0px 0px ;
border-color: var(separatorcolor);
+ border: 2px dash 0px 0px ;
}
button {
spacing: 0;
@@ -126,9 +126,9 @@ button selected {
text-color: var(selected-normal-foreground);
}
inputbar {
+ padding: 1px ;
spacing: 0px ;
text-color: var(normal-foreground);
- padding: 1px ;
children: [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
case-indicator {
@@ -144,8 +144,8 @@ prompt {
text-color: var(normal-foreground);
}
textbox-prompt-colon {
+ margin: 0px 0.3000em 0.0000em 0.0000em ;
expand: false;
str: ":";
- margin: 0px 0.3000em 0.0000em 0.0000em ;
text-color: inherit;
}
diff --git a/doc/old-theme-convert-output.rasi b/doc/old-theme-convert-output.rasi
index bb64476c..86b9b89c 100644
--- a/doc/old-theme-convert-output.rasi
+++ b/doc/old-theme-convert-output.rasi
@@ -2,39 +2,39 @@
* rofi -dump-theme output.
**/
* {
- selected-normal-foreground: rgba ( 2, 20, 63, 100 % );
- foreground: rgba ( 219, 223, 188, 100 % );
- normal-foreground: var(foreground);
- alternate-normal-background: rgba ( 0, 0, 0, 0 % );
red: rgba ( 220, 50, 47, 100 % );
- selected-urgent-foreground: rgba ( 2, 20, 63, 100 % );
- blue: rgba ( 38, 139, 210, 100 % );
+ selected-active-foreground: rgba ( 2, 20, 63, 100 % );
+ lightfg: rgba ( 88, 104, 117, 100 % );
+ separatorcolor: rgba ( 219, 223, 188, 100 % );
urgent-foreground: rgba ( 255, 129, 255, 100 % );
alternate-urgent-background: rgba ( 0, 0, 0, 0 % );
- active-foreground: rgba ( 138, 196, 255, 100 % );
lightbg: rgba ( 238, 232, 213, 100 % );
- selected-active-foreground: rgba ( 2, 20, 63, 100 % );
- alternate-active-background: rgba ( 0, 0, 0, 0 % );
- background: rgba ( 0, 0, 33, 87 % );
- alternate-normal-foreground: var(foreground);
- normal-background: rgba ( 0, 0, 0, 0 % );
- lightfg: rgba ( 88, 104, 117, 100 % );
- selected-normal-background: rgba ( 219, 223, 188, 100 % );
- border-color: rgba ( 219, 223, 188, 100 % );
spacing: 2;
- separatorcolor: rgba ( 219, 223, 188, 100 % );
+ border-color: rgba ( 219, 223, 188, 100 % );
+ normal-background: rgba ( 0, 0, 0, 0 % );
+ background-color: rgba ( 0, 0, 0, 0 % );
+ alternate-active-background: rgba ( 0, 0, 0, 0 % );
+ active-foreground: rgba ( 138, 196, 255, 100 % );
+ blue: rgba ( 38, 139, 210, 100 % );
urgent-background: rgba ( 0, 0, 0, 0 % );
+ alternate-normal-foreground: var(foreground);
+ selected-active-background: rgba ( 138, 196, 255, 100 % );
+ background: rgba ( 0, 0, 33, 87 % );
+ selected-normal-foreground: rgba ( 2, 20, 63, 100 % );
+ active-background: rgba ( 0, 0, 0, 0 % );
+ alternate-active-foreground: var(active-foreground);
+ alternate-normal-background: rgba ( 0, 0, 0, 0 % );
+ foreground: rgba ( 219, 223, 188, 100 % );
selected-urgent-background: rgba ( 255, 129, 127, 100 % );
+ selected-urgent-foreground: rgba ( 2, 20, 63, 100 % );
+ normal-foreground: var(foreground);
alternate-urgent-foreground: var(urgent-foreground);
- background-color: rgba ( 0, 0, 0, 0 % );
- alternate-active-foreground: var(active-foreground);
- active-background: rgba ( 0, 0, 0, 0 % );
- selected-active-background: rgba ( 138, 196, 255, 100 % );
+ selected-normal-background: rgba ( 219, 223, 188, 100 % );
}
element {
- border: 0;
- spacing: 5px ;
padding: 1px ;
+ spacing: 5px ;
+ border: 0;
}
element normal.normal {
background-color: var(normal-background);
@@ -82,40 +82,40 @@ element-icon {
text-color: inherit;
}
window {
+ padding: 5;
background-color: var(background);
border: 1;
- padding: 5;
}
mainbox {
- border: 0;
padding: 0;
+ border: 0;
}
message {
- border: 2px 0px 0px ;
- border-color: var(separatorcolor);
padding: 1px ;
+ border-color: var(separatorcolor);
+ border: 2px 0px 0px ;
}
textbox {
text-color: var(foreground);
}
listview {
- fixed-height: 0;
- border: 2px 0px 0px ;
+ padding: 2px 0px 0px ;
+ scrollbar: true;
border-color: var(separatorcolor);
spacing: 2px ;
- scrollbar: true;
- padding: 2px 0px 0px ;
+ fixed-height: 0;
+ border: 2px 0px 0px ;
}
scrollbar {
width: 4px ;
+ padding: 0;
+ handle-width: 8px ;
border: 0;
handle-color: var(normal-foreground);
- handle-width: 8px ;
- padding: 0;
}
sidebar {
- border: 2px dash 0px 0px ;
border-color: var(separatorcolor);
+ border: 2px dash 0px 0px ;
}
button {
spacing: 0;
@@ -126,9 +126,9 @@ button selected {
text-color: var(selected-normal-foreground);
}
inputbar {
+ padding: 1px ;
spacing: 0px ;
text-color: var(normal-foreground);
- padding: 1px ;
children: [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
case-indicator {
@@ -144,9 +144,9 @@ prompt {
text-color: var(normal-foreground);
}
textbox-prompt-colon {
+ margin: 0px 0.3000em 0.0000em 0.0000em ;
expand: false;
str: ":";
- margin: 0px 0.3000em 0.0000em 0.0000em ;
text-color: inherit;
}
mode-switcher {
diff --git a/doc/test_xr.txt b/doc/test_xr.txt
index faadacc6..695e47ee 100644
--- a/doc/test_xr.txt
+++ b/doc/test_xr.txt
@@ -126,6 +126,8 @@ rofi.scroll-method: 0
! rofi.matching-negate-char: -
! "Directory where history and temporary files are stored." Set from: Default
! rofi.cache-dir:
+! "Show window thumbnail in window switcher if availalbe." Set from: Default
+! rofi.window-thumbnail: false
! "Pidfile location" Set from: File
rofi.pid: /tmp/rofi.pid
! "Paste primary selection" Set from: File
diff --git a/include/settings.h b/include/settings.h
index 0c575f19..88b63a32 100644
--- a/include/settings.h
+++ b/include/settings.h
@@ -189,6 +189,9 @@ typedef struct
/** Cache directory. */
char *cache_dir;
+
+ /** Window Thumbnails */
+ gboolean window_thumbnail;
} Settings;
/** Global Settings structure. */
extern Settings config;
diff --git a/include/xcb.h b/include/xcb.h
index c956b37f..b68caad5 100644
--- a/include/xcb.h
+++ b/include/xcb.h
@@ -181,4 +181,13 @@ typedef enum
*/
extern WindowManagerQuirk current_window_manager;
+/**
+ * @param window the window the screenshot
+ * @param size Size of the thumbnail
+ *
+ * Creates a thumbnail of the window.
+ *
+ * @returns NULL if window was not found, or unmapped, otherwise returns a cairo_surface.
+ */
+cairo_surface_t *x11_helper_get_screenshot_surface_window ( xcb_window_t window, int size );
#endif
diff --git a/source/dialogs/window.c b/source/dialogs/window.c
index f1512eb5..ba244a03 100644
--- a/source/dialogs/window.c
+++ b/source/dialogs/window.c
@@ -112,6 +112,7 @@ typedef struct
cairo_surface_t *icon;
gboolean icon_checked;
uint32_t icon_fetch_uid;
+ gboolean thumbnail_checked;
} client;
// window lists
@@ -910,7 +911,11 @@ static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line,
{
ModeModePrivateData *rmpd = mode_get_private_data ( sw );
client *c = window_client ( rmpd, rmpd->ids->array[selected_line] );
- if ( c->icon_checked == FALSE ) {
+ if ( config.window_thumbnail && c->thumbnail_checked == FALSE ) {
+ c->icon = x11_helper_get_screenshot_surface_window ( c->window, size );
+ c->thumbnail_checked = TRUE;
+ }
+ if ( c->icon == NULL && c->icon_checked == FALSE ) {
c->icon = get_net_wm_icon ( rmpd->ids->array[selected_line], size );
c->icon_checked = TRUE;
}
diff --git a/source/xcb.c b/source/xcb.c
index f211da0e..9e941acc 100644
--- a/source/xcb.c
+++ b/source/xcb.c
@@ -99,6 +99,74 @@ static xcb_visualtype_t *root_visual = NULL;
xcb_atom_t netatoms[NUM_NETATOMS];
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
+static xcb_visualtype_t * lookup_visual (xcb_screen_t *s, xcb_visualid_t visual)
+{
+ xcb_depth_iterator_t d;
+ d = xcb_screen_allowed_depths_iterator (s);
+ for (; d.rem; xcb_depth_next (&d)) {
+ xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator (d.data);
+ for (; v.rem; xcb_visualtype_next (&v)) {
+ if (v.data->visual_id == visual)
+ return v.data;
+ }
+ }
+ return 0;
+}
+
+
+cairo_surface_t *x11_helper_get_screenshot_surface_window ( xcb_window_t window, int size )
+{
+ xcb_get_geometry_cookie_t cookie;
+ xcb_get_geometry_reply_t *reply;
+
+ cookie = xcb_get_geometry(xcb->connection, window);
+ reply = xcb_get_geometry_reply(xcb->connection, cookie, NULL);
+ if ( reply == NULL ) {
+ return NULL;
+ }
+
+ xcb_get_window_attributes_cookie_t attributesCookie = xcb_get_window_attributes (xcb->connection, window);
+ xcb_get_window_attributes_reply_t *attributes = xcb_get_window_attributes_reply (xcb->connection,
+ attributesCookie,
+ NULL );
+ if ( attributes == NULL || ( attributes->map_state != XCB_MAP_STATE_VIEWABLE ) ) {
+ free(reply);
+ if ( attributes ) free(attributes);
+ return NULL;
+ }
+ // Create a cairo surface for the window.
+ xcb_visualtype_t * vt = lookup_visual(xcb->screen, attributes->visual);
+ free ( attributes );
+
+ cairo_surface_t *t = cairo_xcb_surface_create ( xcb->connection, window, vt , reply->width, reply->height );
+
+ if ( cairo_surface_status ( t ) != CAIRO_STATUS_SUCCESS ) {
+ cairo_surface_destroy(t);
+ free(reply);
+ return NULL;
+ }
+
+ // Scale the image, as we don't want to keep large one around.
+ int max = MAX(reply->width, reply->height);
+ double scale = (double)size/ max;
+
+ cairo_surface_t *s2 = cairo_surface_create_similar_image ( t, CAIRO_FORMAT_ARGB32, reply->width*scale,reply->height*scale );
+ free ( reply );
+
+ if ( cairo_surface_status ( s2 ) != CAIRO_STATUS_SUCCESS ) {
+ cairo_surface_destroy ( t ) ;
+ return NULL;
+ }
+ // Paint it in.
+ cairo_t *d = cairo_create (s2);
+ cairo_scale ( d, scale, scale );
+ cairo_set_source_surface ( d, t, 0, 0 );
+ cairo_paint ( d);
+ cairo_destroy(d);
+
+ cairo_surface_destroy(t);
+ return s2;
+}
/**
* Holds for each supported modifier the possible modifier mask.
* Check x11_mod_masks[MODIFIER]&mask != 0 to see if MODIFIER is activated.
diff --git a/source/xrmoptions.c b/source/xrmoptions.c
index ce0c5056..d81c46cd 100644
--- a/source/xrmoptions.c
+++ b/source/xrmoptions.c
@@ -223,6 +223,8 @@ static XrmOption xrmOptions[] = {
"Set the character used to negate the matching. ('\\0' to disable)", CONFIG_DEFAULT },
{ xrm_String, "cache-dir", { .str = &config.cache_dir }, NULL,
"Directory where history and temporary files are stored.", CONFIG_DEFAULT },
+ { xrm_Boolean, "window-thumbnail", { .snum = &config.window_thumbnail }, NULL,
+ "Show window thumbnail in window switcher if availalbe.", CONFIG_DEFAULT },
};
/** Dynamic array of extra options */