From 72aab3daf4dbca48387876b9e79e76106531b6cb Mon Sep 17 00:00:00 2001 From: Nikos Tsipinakis Date: Sun, 6 May 2018 19:47:16 +0300 Subject: [PATCH] Refactor window creation and destruction Move the main window reference from xctx to draw.c and at the same time make each X11 function that modifies the window require the pointer as a parameter. This makes it easier to implement features that require multiple windows. --- src/draw.c | 20 +++++++---------- src/draw.h | 3 +++ src/dunst.c | 10 ++++----- src/x11/x.c | 64 ++++++++++++++++++++++++++++++----------------------- src/x11/x.h | 6 ++--- 5 files changed, 55 insertions(+), 48 deletions(-) diff --git a/src/draw.c b/src/draw.c index ad389b6..410e918 100644 --- a/src/draw.c +++ b/src/draw.c @@ -31,8 +31,7 @@ typedef struct { notification *n; } colored_layout; -cairo_surface_t *root_surface; -cairo_t *c_context; +window_x11 *win; PangoFontDescription *pango_fdesc; @@ -40,8 +39,7 @@ void draw_setup(void) { x_setup(); - root_surface = x_create_cairo_surface(); - c_context = cairo_create(root_surface); + win = x_win_create(); pango_fdesc = pango_font_description_from_string(settings.font); } @@ -555,7 +553,7 @@ static void calc_window_pos(int width, int height, int *ret_x, int *ret_y) void draw(void) { - GSList *layouts = create_layouts(c_context); + GSList *layouts = create_layouts(win->c_ctx); struct dimensions dim = calculate_dimensions(layouts); int width = dim.w; @@ -566,7 +564,7 @@ void draw(void) calc_window_pos(dim.w, dim.h, &win_x, &win_y); x_win_move(win_x, win_y, width, height); - cairo_xlib_surface_set_size(root_surface, width, height); + cairo_xlib_surface_set_size(win->root_surface, width, height); bool first = true; for (GSList *iter = layouts; iter; iter = iter->next) { @@ -578,9 +576,9 @@ void draw(void) first = false; } - cairo_set_source_surface(c_context, image_surface, 0, 0); - cairo_paint(c_context); - cairo_show_page(c_context); + cairo_set_source_surface(win->c_ctx, image_surface, 0, 0); + cairo_paint(win->c_ctx); + cairo_show_page(win->c_ctx); XFlush(xctx.dpy); @@ -590,9 +588,7 @@ void draw(void) void draw_deinit(void) { - cairo_destroy(c_context); - cairo_surface_destroy(root_surface); - + x_win_destroy(win); x_free(); } /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/draw.h b/src/draw.h index de9fb28..3a3ea88 100644 --- a/src/draw.h +++ b/src/draw.h @@ -1,6 +1,9 @@ #ifndef DUNST_DRAW_H #define DUNST_DRAW_H +#include "src/x11/x.h" +extern window_x11 *win; // Temporary + void draw_setup(void); void draw(void); diff --git a/src/dunst.c b/src/dunst.c index 79e648c..cea339b 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -59,19 +59,19 @@ static gboolean run(void *data) static gint64 next_timeout = 0; - if (!xctx.win.visible && queues_length_displayed() > 0) { + if (!win->visible && queues_length_displayed() > 0) { x_win_show(); } - if (xctx.win.visible && queues_length_displayed() == 0) { + if (win->visible && queues_length_displayed() == 0) { x_win_hide(); } - if (xctx.win.visible) { + if (win->visible) { draw(); } - if (xctx.win.visible) { + if (win->visible) { gint64 now = time_monotonic_now(); gint64 sleep = queues_get_next_datachange(now); gint64 timeout_at = now + sleep; @@ -190,7 +190,7 @@ int dunst_main(int argc, char *argv[]) GSource *x11_source = g_source_new(&x11_source_funcs, sizeof(x11_source_t)); ((x11_source_t *) x11_source)->dpy = xctx.dpy; - ((x11_source_t *) x11_source)->w = xctx.win.xwin; + ((x11_source_t *) x11_source)->w = win->xwin; g_source_add_poll(x11_source, &dpy_pollfd); g_source_attach(x11_source, NULL); diff --git a/src/x11/x.c b/src/x11/x.c index 731986c..d722b4b 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -43,13 +43,6 @@ static void x_shortcut_setup_error_handler(void); 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_setup(void); - -cairo_surface_t *x_create_cairo_surface(void) -{ - return cairo_xlib_surface_create(xctx.dpy, - xctx.win.xwin, DefaultVisual(xctx.dpy, 0), WIDTH, HEIGHT); -} void x_win_move(int x, int y, int width, int height) { @@ -59,14 +52,14 @@ void x_win_move(int x, int y, int width, int height) /* move and resize */ if (x != window_dim.x || y != window_dim.y) { - XMoveWindow(xctx.dpy, xctx.win.xwin, x, y); + XMoveWindow(xctx.dpy, win->xwin, x, y); window_dim.x = x; window_dim.y = y; } if (width != window_dim.w || height != window_dim.h) { - XResizeWindow(xctx.dpy, xctx.win.xwin, width, height); + XResizeWindow(xctx.dpy, win->xwin, width, height); window_dim.h = height; window_dim.w = width; @@ -175,12 +168,12 @@ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer switch (ev.type) { case Expose: - if (ev.xexpose.count == 0 && xctx.win.visible) { + if (ev.xexpose.count == 0 && win->visible) { draw(); } break; case ButtonRelease: - if (ev.xbutton.window == xctx.win.xwin) { + if (ev.xbutton.window == win->xwin) { x_handle_click(ev); wake_up(); } @@ -226,9 +219,9 @@ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer wake_up(); break; case CreateNotify: - if (xctx.win.visible && + if (win->visible && ev.xcreatewindow.override_redirect == 0) - XRaiseWindow(xctx.dpy, xctx.win.xwin); + XRaiseWindow(xctx.dpy, win->xwin); break; case PropertyNotify: fullscreen_now = have_fullscreen_window(); @@ -242,10 +235,10 @@ gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer * same screen. PropertyNotify is only neccessary * to detect a focus change to another screen */ - && xctx.win.visible - && scr->id != xctx.win.cur_screen) { + && win->visible + && scr->id != win->cur_screen) { draw(); - xctx.win.cur_screen = scr->id; + win->cur_screen = scr->id; } break; default: @@ -362,7 +355,6 @@ void x_setup(void) xctx.screensaver_info = XScreenSaverAllocInfo(); init_screens(); - x_win_setup(); x_shortcut_grab(&settings.history_ks); } @@ -455,8 +447,9 @@ static void x_set_wm(Window win) /* * Setup the window */ -static void x_win_setup(void) +window_x11 *x_win_create(void) { + window_x11 *win = g_malloc0(sizeof(window_x11)); Window root; XSetWindowAttributes wa; @@ -470,7 +463,7 @@ static void x_win_setup(void) ButtonReleaseMask | FocusChangeMask| StructureNotifyMask; screen_info *scr = get_active_screen(); - xctx.win.xwin = XCreateWindow(xctx.dpy, + win->xwin = XCreateWindow(xctx.dpy, root, scr->x, scr->y, @@ -483,19 +476,34 @@ static void x_win_setup(void) CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); - x_set_wm(xctx.win.xwin); + x_set_wm(win->xwin); settings.transparency = settings.transparency > 100 ? 100 : settings.transparency; - setopacity(xctx.win.xwin, + setopacity(win->xwin, (unsigned long)((100 - settings.transparency) * (0xffffffff / 100))); + win->root_surface = cairo_xlib_surface_create(xctx.dpy, win->xwin, + DefaultVisual(xctx.dpy, 0), + WIDTH, HEIGHT); + win->c_ctx = cairo_create(win->root_surface); long root_event_mask = SubstructureNotifyMask; if (settings.f_mode != FOLLOW_NONE) { root_event_mask |= FocusChangeMask | PropertyChangeMask; } XSelectInput(xctx.dpy, root, root_event_mask); + + return win; +} + +void x_win_destroy(window_x11 *win) +{ + cairo_destroy(win->c_ctx); + cairo_surface_destroy(win->root_surface); + XDestroyWindow(xctx.dpy, win->xwin); + + g_free(win); } /* @@ -504,7 +512,7 @@ static void x_win_setup(void) void x_win_show(void) { /* window is already mapped or there's nothing to show */ - if (xctx.win.visible || queues_length_displayed() == 0) { + if (win->visible || queues_length_displayed() == 0) { return; } @@ -516,7 +524,7 @@ void x_win_show(void) XGrabButton(xctx.dpy, AnyButton, AnyModifier, - xctx.win.xwin, + win->xwin, false, BUTTONMASK, GrabModeAsync, @@ -527,8 +535,8 @@ void x_win_show(void) LOG_W("Unable to grab mouse button(s)."); } - XMapRaised(xctx.dpy, xctx.win.xwin); - xctx.win.visible = true; + XMapRaised(xctx.dpy, win->xwin); + win->visible = true; } /* @@ -540,10 +548,10 @@ void x_win_hide(void) x_shortcut_ungrab(&settings.close_all_ks); x_shortcut_ungrab(&settings.context_ks); - XUngrabButton(xctx.dpy, AnyButton, AnyModifier, xctx.win.xwin); - XUnmapWindow(xctx.dpy, xctx.win.xwin); + XUngrabButton(xctx.dpy, AnyButton, AnyModifier, win->xwin); + XUnmapWindow(xctx.dpy, win->xwin); XFlush(xctx.dpy); - xctx.win.visible = false; + win->visible = false; } /* diff --git a/src/x11/x.h b/src/x11/x.h index 851be0a..606c092 100644 --- a/src/x11/x.h +++ b/src/x11/x.h @@ -36,6 +36,7 @@ struct dimensions { typedef struct { Window xwin; cairo_surface_t *root_surface; + cairo_t *c_ctx; int cur_screen; bool visible; struct dimensions dim; @@ -43,7 +44,6 @@ typedef struct { typedef struct _xctx { Display *dpy; - window_x11 win; const char *colors[3][3]; XScreenSaverInfo *screensaver_info; } xctx_t; @@ -57,9 +57,11 @@ typedef struct _color_t { extern xctx_t xctx; /* window */ +window_x11 *x_win_create(void); void x_win_move(int x, int y, int width, int height); void x_win_hide(void); void x_win_show(void); +void x_win_destroy(window_x11 *win); /* shortcut */ void x_shortcut_init(keyboard_shortcut *shortcut); @@ -74,8 +76,6 @@ void x_free(void); struct geometry x_parse_geometry(const char *geom_str); -cairo_surface_t *x_create_cairo_surface(void); - gboolean x_mainloop_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data); gboolean x_mainloop_fd_check(GSource *source);