diff --git a/docs/dunst.pod b/docs/dunst.pod index 45864f9..5f6b398 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -264,6 +264,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 (default: "Monospace 8") Defines the font or font set used. Optionally set the size as a decimal number diff --git a/src/draw.c b/src/draw.c index bd404f9..bb70b1c 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,7 +1,6 @@ #include "draw.h" #include -#include #include #include #include @@ -10,6 +9,7 @@ #include #include #include +#include #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; @@ -31,7 +39,8 @@ struct colored_layout { const struct notification *n; }; -struct window_x11 *win; +const struct output *output; +window win; PangoFontDescription *pango_fdesc; @@ -39,9 +48,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); } @@ -176,7 +188,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; @@ -261,10 +273,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); @@ -723,7 +735,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) { @@ -746,7 +758,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); @@ -764,7 +776,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); @@ -772,7 +784,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: */ diff --git a/src/draw.h b/src/draw.h index 533b521..43303a4 100644 --- a/src/draw.h +++ b/src/draw.h @@ -1,8 +1,12 @@ #ifndef DUNST_DRAW_H #define DUNST_DRAW_H -#include "x11/x.h" -extern struct window_x11 *win; // Temporary +#include +#include +#include "output.h" + +extern window win; // Temporary +extern const struct output *output; void draw_setup(void); diff --git a/src/dunst.c b/src/dunst.c index 4fde2e9..51bf38b 100644 --- a/src/dunst.c +++ b/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) { diff --git a/src/output.c b/src/output.c new file mode 100644 index 0000000..1a48e30 --- /dev/null +++ b/src/output.c @@ -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: */ diff --git a/src/output.h b/src/output.h new file mode 100644 index 0000000..a66c293 --- /dev/null +++ b/src/output.h @@ -0,0 +1,55 @@ +#ifndef DUNST_OUTPUT_H +#define DUNST_OUTPUT_H + +#include +#include +#include + +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: */ diff --git a/src/queues.c b/src/queues.c index a7ba3c8..604a175 100644 --- a/src/queues.c +++ b/src/queues.c @@ -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; } diff --git a/src/x11/screen.c b/src/x11/screen.c index 99aa775..0a31054 100644 --- a/src/x11/screen.c +++ b/src/x11/screen.c @@ -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; diff --git a/src/x11/screen.h b/src/x11/screen.h index 398ad41..19646d3 100644 --- a/src/x11/screen.h +++ b/src/x11/screen.h @@ -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 diff --git a/src/x11/x.c b/src/x11/x.c index 41f1316..bd6139d 100644 --- a/src/x11/x.c +++ b/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); diff --git a/src/x11/x.h b/src/x11/x.h index a4c319b..f43a752 100644 --- a/src/x11/x.h +++ b/src/x11/x.h @@ -11,6 +11,8 @@ #include #include +#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);