mirror of
https://github.com/davatorium/rofi.git
synced 2025-04-14 17:43:01 -04:00
[Window] Add thumbnail of windows as option.
This commit is contained in:
parent
8590a7ccf2
commit
aeecf34c27
9 changed files with 163 additions and 73 deletions
|
@ -159,4 +159,5 @@ Settings config = {
|
|||
.matching_negate_char = '-',
|
||||
|
||||
.cache_dir = NULL,
|
||||
.window_thumbnail = FALSE,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
urgent-background: var(background);
|
||||
selected-urgent-background: var(red);
|
||||
alternate-urgent-foreground: var(red);
|
||||
border-color: var(foreground);
|
||||
normal-background: var(background);
|
||||
background-color: rgba ( 0, 0, 0, 0 % );
|
||||
alternate-active-foreground: var(blue);
|
||||
active-background: var(background);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 % );
|
||||
urgent-background: rgba ( 0, 0, 0, 0 % );
|
||||
selected-urgent-background: rgba ( 255, 129, 127, 100 % );
|
||||
alternate-urgent-foreground: var(urgent-foreground);
|
||||
border-color: rgba ( 219, 223, 188, 100 % );
|
||||
normal-background: rgba ( 0, 0, 0, 0 % );
|
||||
background-color: rgba ( 0, 0, 0, 0 % );
|
||||
alternate-active-foreground: var(active-foreground);
|
||||
active-background: 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);
|
||||
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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -189,6 +189,9 @@ typedef struct
|
|||
|
||||
/** Cache directory. */
|
||||
char *cache_dir;
|
||||
|
||||
/** Window Thumbnails */
|
||||
gboolean window_thumbnail;
|
||||
} Settings;
|
||||
/** Global Settings structure. */
|
||||
extern Settings config;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
68
source/xcb.c
68
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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue