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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2016-04-15 20:29:08 +02:00
parent 8de8df1415
commit b651373cda
5 changed files with 83 additions and 6 deletions

View File

@ -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

View File

@ -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();

View File

@ -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 */

View File

@ -50,6 +50,7 @@
#include "banning.h"
#include "objects/client.h"
#include "objects/drawin.h"
#include "event.h"
#include <stdio.h>
@ -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

View File

@ -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)