From b651373cda98c4a78c4a12d9e9a018743cdf28b6 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 15 Apr 2016 20:29:08 +0200 Subject: [PATCH] Stop restarting on RandR changes This commit adds a "removed" signal to screens. Together with the "added" signal that we have since a while, this allows the C code to update the list of available screens dynamically without needing to restart. So far, this code received only minimal testing. So far, I don't have a nice idea on how to easily test this... Closes: https://github.com/awesomeWM/awesome/issues/672 Signed-off-by: Uli Schlachter --- event.c | 5 ++-- event.h | 4 +++ globalconf.h | 4 +++ objects/screen.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-- objects/screen.h | 2 ++ 5 files changed, 83 insertions(+), 6 deletions(-) diff --git a/event.c b/event.c index 3ae40ced0..920b09c74 100644 --- a/event.c +++ b/event.c @@ -400,8 +400,7 @@ event_handle_configurenotify(xcb_configure_notify_event_t *ev) xcb_screen_t *screen = globalconf.screen; if(ev->window == screen->root) - /* it's not that we panic, but restart */ - awesome_restart(); + globalconf.screen_need_refresh = true; /* Copy what XRRUpdateConfiguration() would do: Update the configuration */ if(ev->window == screen->root) { @@ -782,7 +781,7 @@ event_handle_randr_screen_change_notify(xcb_randr_screen_change_notify_event_t * globalconf.screen->height_in_pixels = ev->height; } - awesome_restart(); + globalconf.screen_need_refresh = true; } /** XRandR event handler for RRNotify subtype XRROutputChangeNotifyEvent diff --git a/event.h b/event.h index 1d471aa3b..5849f7324 100644 --- a/event.h +++ b/event.h @@ -38,9 +38,13 @@ void drawin_refresh(void); void client_focus_refresh(void); void client_border_refresh(void); +/* objects/screen.c */ +void screen_refresh(void); + static inline int awesome_refresh(void) { + screen_refresh(); luaA_emit_refresh(); banning_refresh(); stack_refresh(); diff --git a/globalconf.h b/globalconf.h index dc407596b..877be221c 100644 --- a/globalconf.h +++ b/globalconf.h @@ -92,6 +92,10 @@ typedef struct xcb_window_t selection_owner_window; /** Do we have RandR 1.3 or newer? */ bool have_randr_13; + /** Do we have RandR 1.5 or newer? */ + bool have_randr_15; + /** Do we have a RandR screen update pending? */ + bool screen_need_refresh; /** Check for XTest extension */ bool have_xtest; /** Check for SHAPE extension */ diff --git a/objects/screen.c b/objects/screen.c index 9ba884dcd..5b07b9484 100644 --- a/objects/screen.c +++ b/objects/screen.c @@ -50,6 +50,7 @@ #include "banning.h" #include "objects/client.h" #include "objects/drawin.h" +#include "event.h" #include @@ -231,8 +232,9 @@ screen_scan_randr_monitors(lua_State *L, screen_array_t *screens) new_screen = screen_add(L, screens); new_screen->geometry.x = monitor_iter.data->x; new_screen->geometry.y = monitor_iter.data->y; - new_screen->geometry.width= monitor_iter.data->width; - new_screen->geometry.height= monitor_iter.data->height; + new_screen->geometry.width = monitor_iter.data->width; + new_screen->geometry.height = monitor_iter.data->height; + new_screen->xid = monitor_iter.data->name; output.mm_width = monitor_iter.data->width_in_millimeters; output.mm_height = monitor_iter.data->height_in_millimeters; @@ -296,6 +298,7 @@ screen_scan_randr_crtcs(lua_State *L, screen_array_t *screens) new_screen->geometry.y = crtc_info_r->y; new_screen->geometry.width= crtc_info_r->width; new_screen->geometry.height= crtc_info_r->height; + new_screen->xid = randr_crtcs[i]; xcb_randr_output_t *randr_outputs = xcb_randr_get_crtc_info_outputs(crtc_info_r); @@ -370,13 +373,18 @@ screen_scan_randr(lua_State *L, screen_array_t *screens) return; globalconf.have_randr_13 = minor_version >= 3; +#if XCB_RANDR_MAJOR_VERSION > 1 || XCB_RANDR_MINOR_VERSION >= 5 + globalconf.have_randr_15 = minor_version >= 5; +#else + globalconf.have_randr_15 = false; +#endif /* We want to know when something changes */ xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE); - if (minor_version >= 5) + if (globalconf.have_randr_15) screen_scan_randr_monitors(L, screens); else screen_scan_randr_crtcs(L, screens); @@ -455,6 +463,61 @@ screen_scan(void) screen_update_primary(); } +void +screen_refresh(void) +{ + if(!globalconf.screen_need_refresh) + return; + globalconf.screen_need_refresh = false; + + screen_array_t new_screens; + lua_State *L = globalconf_get_lua_State(); + + screen_array_init(&new_screens); + if (globalconf.have_randr_15) + screen_scan_randr_monitors(L, &new_screens); + else + screen_scan_randr_crtcs(L, &new_screens); + + /* Add new screens */ + foreach(new_screen, new_screens) { + bool found = false; + foreach(old_screen, globalconf.screens) + found |= (*new_screen)->xid == (*old_screen)->xid; + if(!found) { + screen_array_append(&globalconf.screens, *new_screen); + luaA_object_push(L, *new_screen); + luaA_object_emit_signal(L, -1, "added", 0); + /* Get an extra reference since both new_screens and + * globalconf.screens reference this screen now */ + luaA_object_ref(L, -1); + } + } + + /* Remove screens which are gone */ + for(int i = 0; i < globalconf.screens.len; i++) { + screen_t *old_screen = globalconf.screens.tab[i]; + bool found = false; + foreach(new_screen, new_screens) + found |= (*new_screen)->xid == old_screen->xid; + if(!found) { + luaA_object_push(L, old_screen); + luaA_object_emit_signal(L, -1, "removed", 0); + lua_pop(L, 1); + screen_array_take(&globalconf.screens, i); + luaA_object_unref(L, old_screen); + + i--; + } + } + + foreach(screen, new_screens) + luaA_object_unref(L, *screen); + screen_array_wipe(&new_screens); + + screen_update_primary(); +} + /** Return the squared distance of the given screen to the coordinates. * \param screen The screen * \param x X coordinate @@ -900,6 +963,11 @@ screen_class_setup(lua_State *L) * @signal .added */ signal_add(&screen_class.signals, "added"); + /** + * This signal is emitted when a screen is removed from the setup. + * @signal removed + */ + signal_add(&screen_class.signals, "removed"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/objects/screen.h b/objects/screen.h index d6e6149ff..949e4615a 100644 --- a/objects/screen.h +++ b/objects/screen.h @@ -37,6 +37,8 @@ struct a_screen area_t geometry; /** The screen outputs informations */ screen_output_array_t outputs; + /** Some XID identifying this screen */ + uint32_t xid; }; ARRAY_FUNCS(screen_t *, screen, DO_NOTHING)