Create abstract output and fix wayland bug
This commit adds an output struct which abstracts the X11 specific functions and makes it possible to easily create a drop-in wayland output. It also fixes a bug in wayland where notifications won't disappear. This is because wayland doesn't give access to user input when a client is not in focus. This way it seems like the user is always idle. The idle functionality is now disabled in Wayland until proper support is added.
This commit is contained in:
parent
3001f79fc3
commit
58d215ddfe
@ -238,6 +238,8 @@ Set to 0 to disable.
|
||||
A client can mark a notification as transient to bypass this setting and timeout
|
||||
anyway. Use a rule with 'set_transient = no' to disable this behavior.
|
||||
|
||||
Note: this doesn't work on wayland yet.
|
||||
|
||||
=item B<font> (default: "Monospace 8")
|
||||
|
||||
Defines the font or font set used. Optionally set the size as a decimal number
|
||||
|
38
src/draw.c
38
src/draw.c
@ -1,7 +1,6 @@
|
||||
#include "draw.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cairo.h>
|
||||
#include <math.h>
|
||||
#include <pango/pango-attributes.h>
|
||||
#include <pango/pangocairo.h>
|
||||
@ -10,6 +9,7 @@
|
||||
#include <pango/pango-types.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "dunst.h"
|
||||
#include "icon.h"
|
||||
@ -17,7 +17,15 @@
|
||||
#include "markup.h"
|
||||
#include "notification.h"
|
||||
#include "queues.h"
|
||||
#include "x11/x.h"
|
||||
#include "output.h"
|
||||
#include "settings.h"
|
||||
|
||||
struct color {
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
double a;
|
||||
};
|
||||
|
||||
struct colored_layout {
|
||||
PangoLayout *l;
|
||||
@ -30,7 +38,8 @@ struct colored_layout {
|
||||
const struct notification *n;
|
||||
};
|
||||
|
||||
struct window_x11 *win;
|
||||
const struct output *output;
|
||||
window win;
|
||||
|
||||
PangoFontDescription *pango_fdesc;
|
||||
|
||||
@ -38,9 +47,12 @@ PangoFontDescription *pango_fdesc;
|
||||
|
||||
void draw_setup(void)
|
||||
{
|
||||
x_setup();
|
||||
const struct output *out = output_create();
|
||||
output = out;
|
||||
|
||||
out->init();
|
||||
win = out->win_create();
|
||||
|
||||
win = x_win_create();
|
||||
pango_fdesc = pango_font_description_from_string(settings.font);
|
||||
}
|
||||
|
||||
@ -170,7 +182,7 @@ static struct dimensions calculate_dimensions(GSList *layouts)
|
||||
{
|
||||
struct dimensions dim = { 0 };
|
||||
|
||||
struct screen_info *scr = get_active_screen();
|
||||
const struct screen_info *scr = output->get_active_screen();
|
||||
if (have_dynamic_width()) {
|
||||
/* dynamic width */
|
||||
dim.w = 0;
|
||||
@ -250,10 +262,10 @@ static struct dimensions calculate_dimensions(GSList *layouts)
|
||||
|
||||
static PangoLayout *layout_create(cairo_t *c)
|
||||
{
|
||||
struct screen_info *screen = get_active_screen();
|
||||
const struct screen_info *screen = output->get_active_screen();
|
||||
|
||||
PangoContext *context = pango_cairo_create_context(c);
|
||||
pango_cairo_context_set_resolution(context, screen_dpi_get(screen));
|
||||
pango_cairo_context_set_resolution(context, screen->dpi);
|
||||
|
||||
PangoLayout *layout = pango_layout_new(context);
|
||||
|
||||
@ -664,7 +676,7 @@ static struct dimensions layout_render(cairo_surface_t *srf,
|
||||
*/
|
||||
static void calc_window_pos(int width, int height, int *ret_x, int *ret_y)
|
||||
{
|
||||
struct screen_info *scr = get_active_screen();
|
||||
const struct screen_info *scr = output->get_active_screen();
|
||||
|
||||
if (ret_x) {
|
||||
if (settings.geometry.negative_x) {
|
||||
@ -687,7 +699,7 @@ void draw(void)
|
||||
{
|
||||
assert(queues_length_displayed() > 0);
|
||||
|
||||
GSList *layouts = create_layouts(x_win_get_context(win));
|
||||
GSList *layouts = create_layouts(output->win_get_context(win));
|
||||
|
||||
struct dimensions dim = calculate_dimensions(layouts);
|
||||
|
||||
@ -705,7 +717,7 @@ void draw(void)
|
||||
}
|
||||
|
||||
calc_window_pos(dim.w, dim.h, &dim.x, &dim.y);
|
||||
x_display_surface(image_surface, win, &dim);
|
||||
output->display_surface(image_surface, win, &dim);
|
||||
|
||||
cairo_surface_destroy(image_surface);
|
||||
g_slist_free_full(layouts, free_colored_layout);
|
||||
@ -713,7 +725,7 @@ void draw(void)
|
||||
|
||||
void draw_deinit(void)
|
||||
{
|
||||
x_win_destroy(win);
|
||||
x_free();
|
||||
output->win_destroy(win);
|
||||
output->deinit();
|
||||
}
|
||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
||||
|
@ -1,8 +1,12 @@
|
||||
#ifndef DUNST_DRAW_H
|
||||
#define DUNST_DRAW_H
|
||||
|
||||
#include "x11/x.h"
|
||||
extern struct window_x11 *win; // Temporary
|
||||
#include <stdbool.h>
|
||||
#include <cairo.h>
|
||||
#include "output.h"
|
||||
|
||||
extern window win; // Temporary
|
||||
extern const struct output *output;
|
||||
|
||||
void draw_setup(void);
|
||||
|
||||
|
11
src/dunst.c
11
src/dunst.c
@ -20,8 +20,7 @@
|
||||
#include "queues.h"
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
#include "x11/screen.h"
|
||||
#include "x11/x.h"
|
||||
#include "output.h"
|
||||
|
||||
GMainLoop *mainloop = NULL;
|
||||
|
||||
@ -67,8 +66,8 @@ static gboolean run(void *data)
|
||||
|
||||
LOG_D("RUN");
|
||||
|
||||
dunst_status(S_FULLSCREEN, have_fullscreen_window());
|
||||
dunst_status(S_IDLE, x_is_idle());
|
||||
dunst_status(S_FULLSCREEN, output->have_fullscreen_window());
|
||||
dunst_status(S_IDLE, output->is_idle());
|
||||
|
||||
queues_update(status);
|
||||
|
||||
@ -77,9 +76,9 @@ static gboolean run(void *data)
|
||||
if (active) {
|
||||
// Call draw before showing the window to avoid flickering
|
||||
draw();
|
||||
x_win_show(win);
|
||||
output->win_show(win);
|
||||
} else {
|
||||
x_win_hide(win);
|
||||
output->win_hide(win);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
|
62
src/output.c
Normal file
62
src/output.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "output.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "x11/x.h"
|
||||
#include "x11/screen.h"
|
||||
/* #include "wayland/wl.h" */ // Not yet
|
||||
|
||||
const bool is_running_wayland(void){
|
||||
char* wayland_display = getenv("WAYLAND_DISPLAY");
|
||||
return !(wayland_display == NULL);
|
||||
}
|
||||
|
||||
const struct output output_x11 = {
|
||||
x_setup,
|
||||
x_free,
|
||||
|
||||
x_win_create,
|
||||
x_win_destroy,
|
||||
|
||||
x_win_show,
|
||||
x_win_hide,
|
||||
|
||||
x_display_surface,
|
||||
x_win_visible,
|
||||
x_win_get_context,
|
||||
|
||||
get_active_screen,
|
||||
|
||||
x_is_idle,
|
||||
have_fullscreen_window
|
||||
};
|
||||
|
||||
/* const struct output output_wl = { */
|
||||
/* wl_init, */
|
||||
/* wl_deinit, */
|
||||
|
||||
/* wl_win_create, */
|
||||
/* wl_win_destroy, */
|
||||
|
||||
/* wl_win_show, */
|
||||
/* wl_win_hide, */
|
||||
|
||||
/* wl_display_surface, */
|
||||
/* wl_win_visible, */
|
||||
/* wl_win_get_context, */
|
||||
|
||||
/* wl_get_active_screen, */
|
||||
|
||||
/* wl_is_idle, */
|
||||
/* wl_have_fullscreen_window */
|
||||
/* }; */
|
||||
|
||||
const struct output* output_create(void)
|
||||
{
|
||||
if (is_running_wayland()) {
|
||||
LOG_I("System is running wayland");
|
||||
} else{
|
||||
LOG_I("System is running X11");
|
||||
}
|
||||
return &output_x11;
|
||||
}
|
||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
55
src/output.h
Normal file
55
src/output.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef DUNST_OUTPUT_H
|
||||
#define DUNST_OUTPUT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <glib.h>
|
||||
#include <cairo.h>
|
||||
|
||||
typedef gpointer window;
|
||||
|
||||
struct dimensions {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
int corner_radius;
|
||||
};
|
||||
|
||||
struct screen_info {
|
||||
int id;
|
||||
int x;
|
||||
int y;
|
||||
unsigned int h;
|
||||
unsigned int mmh;
|
||||
unsigned int w;
|
||||
int dpi;
|
||||
};
|
||||
|
||||
struct output {
|
||||
void (*init)(void);
|
||||
void (*deinit)(void);
|
||||
|
||||
window (*win_create)(void);
|
||||
void (*win_destroy)(window);
|
||||
|
||||
void (*win_show)(window);
|
||||
void (*win_hide)(window);
|
||||
|
||||
void (*display_surface)(cairo_surface_t *srf, window win, const struct dimensions*);
|
||||
|
||||
bool (*win_visible)(window);
|
||||
cairo_t* (*win_get_context)(window);
|
||||
|
||||
const struct screen_info* (*get_active_screen)(void);
|
||||
|
||||
bool (*is_idle)(void);
|
||||
bool (*have_fullscreen_window)(void);
|
||||
};
|
||||
|
||||
const struct output* output_create(void);
|
||||
|
||||
const bool is_running_wayland(void);
|
||||
|
||||
#endif
|
||||
/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|
@ -25,6 +25,7 @@
|
||||
#include "notification.h"
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
#include "output.h" // For checking if wayland is active.
|
||||
|
||||
/* notification lists */
|
||||
static GQueue *waiting = NULL; /**< all new notifications get into here */
|
||||
@ -143,7 +144,8 @@ static bool queues_notification_is_finished(struct notification *n, struct dunst
|
||||
bool is_idle = status.fullscreen ? false : status.idle;
|
||||
|
||||
/* don't timeout when user is idle */
|
||||
if (is_idle && !n->transient) {
|
||||
/* NOTE: Idle is not working on wayland */
|
||||
if (is_idle && !n->transient && !is_running_wayland()) {
|
||||
n->start = time_monotonic_now();
|
||||
return false;
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ static double screen_dpi_get_from_xft(void)
|
||||
return screen_dpi_xft_cache;
|
||||
}
|
||||
|
||||
static double screen_dpi_get_from_monitor(struct screen_info *scr)
|
||||
static double screen_dpi_get_from_monitor(const struct screen_info *scr)
|
||||
{
|
||||
return (double)scr->h * 25.4 / (double)scr->mmh;
|
||||
}
|
||||
|
||||
double screen_dpi_get(struct screen_info *scr)
|
||||
double screen_dpi_get(const struct screen_info *scr)
|
||||
{
|
||||
if ( ! settings.force_xinerama
|
||||
&& settings.per_monitor_dpi)
|
||||
@ -156,6 +156,7 @@ void randr_update(void)
|
||||
screens[i].w = m[i].width;
|
||||
screens[i].h = m[i].height;
|
||||
screens[i].mmh = m[i].mheight;
|
||||
screens[i].dpi = screen_dpi_get(&screens[i]);
|
||||
}
|
||||
|
||||
XRRFreeMonitors(m);
|
||||
@ -300,7 +301,7 @@ bool window_is_fullscreen(Window window)
|
||||
* Select the screen on which the Window
|
||||
* should be displayed.
|
||||
*/
|
||||
struct screen_info *get_active_screen(void)
|
||||
const struct screen_info *get_active_screen(void)
|
||||
{
|
||||
int ret = 0;
|
||||
bool force_follow_mouse = false;
|
||||
|
@ -7,21 +7,12 @@
|
||||
|
||||
#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh))
|
||||
|
||||
struct screen_info {
|
||||
int id;
|
||||
int x;
|
||||
int y;
|
||||
unsigned int h;
|
||||
unsigned int mmh;
|
||||
unsigned int w;
|
||||
};
|
||||
|
||||
void init_screens(void);
|
||||
void screen_dpi_xft_cache_purge(void);
|
||||
bool screen_check_event(XEvent *ev);
|
||||
|
||||
struct screen_info *get_active_screen(void);
|
||||
double screen_dpi_get(struct screen_info *scr);
|
||||
const struct screen_info *get_active_screen(void);
|
||||
double screen_dpi_get(const struct screen_info *scr);
|
||||
|
||||
/**
|
||||
* Find the currently focused window and check if it's in
|
||||
|
37
src/x11/x.c
37
src/x11/x.c
@ -67,8 +67,10 @@ static int x_shortcut_tear_down_error_handler(void);
|
||||
static void setopacity(Window win, unsigned long opacity);
|
||||
static void x_handle_click(XEvent ev);
|
||||
|
||||
static void x_win_move(struct window_x11 *win, int x, int y, int width, int height)
|
||||
static void x_win_move(window winptr, int x, int y, int width, int height)
|
||||
{
|
||||
struct window_x11 *win = (struct window_x11*)winptr;
|
||||
|
||||
/* move and resize */
|
||||
if (x != win->dim.x || y != win->dim.y) {
|
||||
XMoveWindow(xctx.dpy, win->xwin, x, y);
|
||||
@ -126,8 +128,9 @@ static void x_win_corners_shape(struct window_x11 *win, const int rad)
|
||||
win->xwin, ShapeNotifyMask);
|
||||
}
|
||||
|
||||
static void x_win_corners_unshape(struct window_x11 *win)
|
||||
static void x_win_corners_unshape(window winptr)
|
||||
{
|
||||
struct window_x11 *win = (struct window_x11*)winptr;
|
||||
XRectangle rect = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
@ -153,8 +156,9 @@ static bool x_win_composited(struct window_x11 *win)
|
||||
}
|
||||
}
|
||||
|
||||
void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struct dimensions *dim)
|
||||
void x_display_surface(cairo_surface_t *srf, window winptr, const struct dimensions *dim)
|
||||
{
|
||||
struct window_x11 *win = (struct window_x11*)winptr;
|
||||
x_win_move(win, dim->x, dim->y, dim->w, dim->h);
|
||||
cairo_xlib_surface_set_size(win->root_surface, dim->w, dim->h);
|
||||
|
||||
@ -173,14 +177,14 @@ void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struc
|
||||
|
||||
}
|
||||
|
||||
bool x_win_visible(struct window_x11 *win)
|
||||
bool x_win_visible(window winptr)
|
||||
{
|
||||
return win->visible;
|
||||
return ((struct window_x11*)winptr)->visible;
|
||||
}
|
||||
|
||||
cairo_t* x_win_get_context(struct window_x11 *win)
|
||||
cairo_t* x_win_get_context(window winptr)
|
||||
{
|
||||
return win->c_ctx;
|
||||
return ((struct window_x11*)win)->c_ctx;
|
||||
}
|
||||
|
||||
static void setopacity(Window win, unsigned long opacity)
|
||||
@ -278,7 +282,7 @@ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer
|
||||
struct window_x11 *win = ((struct x11_source*) source)->win;
|
||||
|
||||
bool fullscreen_now;
|
||||
struct screen_info *scr;
|
||||
const struct screen_info *scr;
|
||||
XEvent ev;
|
||||
unsigned int state;
|
||||
while (XPending(xctx.dpy) > 0) {
|
||||
@ -641,7 +645,7 @@ GSource* x_win_reg_source(struct window_x11 *win)
|
||||
/*
|
||||
* Setup the window
|
||||
*/
|
||||
struct window_x11 *x_win_create(void)
|
||||
window x_win_create(void)
|
||||
{
|
||||
struct window_x11 *win = g_malloc0(sizeof(struct window_x11));
|
||||
|
||||
@ -671,7 +675,7 @@ struct window_x11 *x_win_create(void)
|
||||
ExposureMask | KeyPressMask | VisibilityChangeMask |
|
||||
ButtonReleaseMask | FocusChangeMask| StructureNotifyMask;
|
||||
|
||||
struct screen_info *scr = get_active_screen();
|
||||
const struct screen_info *scr = get_active_screen();
|
||||
win->xwin = XCreateWindow(xctx.dpy,
|
||||
root,
|
||||
scr->x,
|
||||
@ -713,11 +717,13 @@ struct window_x11 *x_win_create(void)
|
||||
}
|
||||
XSelectInput(xctx.dpy, root, root_event_mask);
|
||||
|
||||
return win;
|
||||
return (window)win;
|
||||
}
|
||||
|
||||
void x_win_destroy(struct window_x11 *win)
|
||||
void x_win_destroy(window winptr)
|
||||
{
|
||||
struct window_x11 *win = (struct window_x11*)winptr;
|
||||
|
||||
g_source_destroy(win->esrc);
|
||||
g_source_unref(win->esrc);
|
||||
|
||||
@ -731,8 +737,10 @@ void x_win_destroy(struct window_x11 *win)
|
||||
/*
|
||||
* Show the window and grab shortcuts.
|
||||
*/
|
||||
void x_win_show(struct window_x11 *win)
|
||||
void x_win_show(window winptr)
|
||||
{
|
||||
struct window_x11 *win = (struct window_x11*)winptr;
|
||||
|
||||
/* window is already mapped or there's nothing to show */
|
||||
if (win->visible)
|
||||
return;
|
||||
@ -763,8 +771,9 @@ void x_win_show(struct window_x11 *win)
|
||||
/*
|
||||
* Hide the window and ungrab unused keyboard_shortcuts
|
||||
*/
|
||||
void x_win_hide(struct window_x11 *win)
|
||||
void x_win_hide(window winptr)
|
||||
{
|
||||
struct window_x11 *win = (struct window_x11*)winptr;
|
||||
ASSERT_OR_RET(win->visible,);
|
||||
|
||||
x_shortcut_ungrab(&settings.close_ks);
|
||||
|
34
src/x11/x.h
34
src/x11/x.h
@ -11,6 +11,8 @@
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "../output.h"
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
struct keyboard_shortcut {
|
||||
@ -24,42 +26,24 @@ struct keyboard_shortcut {
|
||||
// Cyclical dependency
|
||||
#include "../settings.h"
|
||||
|
||||
struct window_x11;
|
||||
|
||||
struct dimensions {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
int corner_radius;
|
||||
};
|
||||
|
||||
struct x_context {
|
||||
Display *dpy;
|
||||
XScreenSaverInfo *screensaver_info;
|
||||
};
|
||||
|
||||
struct color {
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
double a;
|
||||
};
|
||||
|
||||
extern struct x_context xctx;
|
||||
|
||||
/* window */
|
||||
struct window_x11 *x_win_create(void);
|
||||
void x_win_destroy(struct window_x11 *win);
|
||||
window x_win_create(void);
|
||||
void x_win_destroy(window);
|
||||
|
||||
void x_win_show(struct window_x11 *win);
|
||||
void x_win_hide(struct window_x11 *win);
|
||||
void x_win_show(window);
|
||||
void x_win_hide(window);
|
||||
|
||||
void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struct dimensions *dim);
|
||||
void x_display_surface(cairo_surface_t *srf, window, const struct dimensions *dim);
|
||||
|
||||
bool x_win_visible(struct window_x11 *win);
|
||||
cairo_t* x_win_get_context(struct window_x11 *win);
|
||||
bool x_win_visible(window);
|
||||
cairo_t* x_win_get_context(window);
|
||||
|
||||
/* X misc */
|
||||
bool x_is_idle(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user