Merge pull request #828 from psychon/screen-scan2

Stop restarting on RandR changes
This commit is contained in:
Daniel Hahler 2016-05-01 17:00:05 +02:00
commit 6b6cbf4a1f
7 changed files with 311 additions and 150 deletions

View File

@ -400,8 +400,7 @@ event_handle_configurenotify(xcb_configure_notify_event_t *ev)
xcb_screen_t *screen = globalconf.screen; xcb_screen_t *screen = globalconf.screen;
if(ev->window == screen->root) if(ev->window == screen->root)
/* it's not that we panic, but restart */ globalconf.screen_need_refresh = true;
awesome_restart();
/* Copy what XRRUpdateConfiguration() would do: Update the configuration */ /* Copy what XRRUpdateConfiguration() would do: Update the configuration */
if(ev->window == screen->root) { 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; globalconf.screen->height_in_pixels = ev->height;
} }
awesome_restart(); globalconf.screen_need_refresh = true;
} }
/** XRandR event handler for RRNotify subtype XRROutputChangeNotifyEvent /** XRandR event handler for RRNotify subtype XRROutputChangeNotifyEvent
@ -992,10 +991,8 @@ void event_init(void)
const xcb_query_extension_reply_t *reply; const xcb_query_extension_reply_t *reply;
reply = xcb_get_extension_data(globalconf.connection, &xcb_randr_id); reply = xcb_get_extension_data(globalconf.connection, &xcb_randr_id);
if (reply && reply->present) { if (reply && reply->present)
xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
globalconf.event_base_randr = reply->first_event; globalconf.event_base_randr = reply->first_event;
}
reply = xcb_get_extension_data(globalconf.connection, &xcb_shape_id); reply = xcb_get_extension_data(globalconf.connection, &xcb_shape_id);
if (reply && reply->present) if (reply && reply->present)

View File

@ -38,9 +38,13 @@ void drawin_refresh(void);
void client_focus_refresh(void); void client_focus_refresh(void);
void client_border_refresh(void); void client_border_refresh(void);
/* objects/screen.c */
void screen_refresh(void);
static inline int static inline int
awesome_refresh(void) awesome_refresh(void)
{ {
screen_refresh();
luaA_emit_refresh(); luaA_emit_refresh();
banning_refresh(); banning_refresh();
stack_refresh(); stack_refresh();

View File

@ -92,6 +92,10 @@ typedef struct
xcb_window_t selection_owner_window; xcb_window_t selection_owner_window;
/** Do we have RandR 1.3 or newer? */ /** Do we have RandR 1.3 or newer? */
bool have_randr_13; 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 */ /** Check for XTest extension */
bool have_xtest; bool have_xtest;
/** Check for SHAPE extension */ /** Check for SHAPE extension */

View File

@ -446,6 +446,7 @@ function client.object.to_selected_tags(self)
end end
end end
if self.screen then
if #tags == 0 then if #tags == 0 then
tags = self.screen.selected_tags tags = self.screen.selected_tags
end end
@ -453,6 +454,7 @@ function client.object.to_selected_tags(self)
if #tags == 0 then if #tags == 0 then
tags = self.screen.tags tags = self.screen.tags
end end
end
if #tags ~= 0 then if #tags ~= 0 then
self:tags(tags) self:tags(tags)

View File

@ -285,6 +285,14 @@ end
capi.client.connect_signal("property::struts", update_wiboxes_on_struts) capi.client.connect_signal("property::struts", update_wiboxes_on_struts)
capi.client.connect_signal("unmanage", update_wiboxes_on_struts) capi.client.connect_signal("unmanage", update_wiboxes_on_struts)
capi.screen.connect_signal("removed", function(s)
for _, wprop in ipairs(wiboxes) do
if wprop.screen == s then
wprop.wibox.visible = false
end
end
end)
function awfulwibox.mt:__call(...) function awfulwibox.mt:__call(...)
return awfulwibox.new(...) return awfulwibox.new(...)
end end

View File

@ -50,6 +50,7 @@
#include "banning.h" #include "banning.h"
#include "objects/client.h" #include "objects/client.h"
#include "objects/drawin.h" #include "objects/drawin.h"
#include "event.h"
#include <stdio.h> #include <stdio.h>
@ -182,6 +183,13 @@ screen_wipe(screen_t *s)
screen_output_array_wipe(&s->outputs); screen_output_array_wipe(&s->outputs);
} }
/** Check if a screen is valid */
static bool
screen_checker(screen_t *s)
{
return s->valid;
}
/** Get a screen argument from the lua stack */ /** Get a screen argument from the lua stack */
screen_t * screen_t *
luaA_checkscreen(lua_State *L, int sidx) luaA_checkscreen(lua_State *L, int sidx)
@ -197,56 +205,52 @@ luaA_checkscreen(lua_State *L, int sidx)
return luaA_checkudata(L, sidx, &screen_class); return luaA_checkudata(L, sidx, &screen_class);
} }
static inline area_t
screen_xsitoarea(xcb_xinerama_screen_info_t si)
{
area_t a =
{
.x = si.x_org,
.y = si.y_org,
.width = si.width,
.height = si.height
};
return a;
}
static void static void
screen_add(lua_State *L, int sidx) screen_deduplicate(lua_State *L, screen_array_t *screens)
{ {
screen_t *new_screen = luaA_checkudata(L, sidx, &screen_class); /* Remove duplicate screens */
for(int first = 0; first < screens->len; first++) {
screen_t *first_screen = screens->tab[first];
for(int second = 0; second < screens->len; second++) {
screen_t *second_screen = screens->tab[second];
if (first == second)
continue;
foreach(screen_to_test, globalconf.screens) if (first_screen->geometry.width < second_screen->geometry.width
if(new_screen->geometry.x == (*screen_to_test)->geometry.x && first_screen->geometry.height < second_screen->geometry.height)
&& new_screen->geometry.y == (*screen_to_test)->geometry.y) /* Don't drop a smaller screen */
{ continue;
/* we already have a screen for this area, just check if
* it's not bigger and drop it */ if (first_screen->geometry.x == second_screen->geometry.x
(*screen_to_test)->geometry.width = && first_screen->geometry.y == second_screen->geometry.y) {
MAX(new_screen->geometry.width, (*screen_to_test)->geometry.width); /* Found a duplicate */
(*screen_to_test)->geometry.height = first_screen->geometry.width = MAX(first_screen->geometry.width, second_screen->geometry.width);
MAX(new_screen->geometry.height, (*screen_to_test)->geometry.height); first_screen->geometry.height = MAX(first_screen->geometry.height, second_screen->geometry.height);
lua_remove(L, sidx);
screen_array_take(screens, second);
luaA_object_unref(L, second_screen);
/* Restart the search */
screen_deduplicate(L, screens);
return; return;
} }
}
sidx = luaA_absindex(L, sidx); }
lua_pushvalue(L, sidx);
luaA_object_ref(L, sidx);
screen_array_append(&globalconf.screens, new_screen);
luaA_object_emit_signal(L, -1, "added", 0);
lua_pop(L, 1);
} }
static bool static screen_t *
screens_exist(void) screen_add(lua_State *L, screen_array_t *screens)
{ {
return globalconf.screens.len > 0; screen_t *new_screen = screen_new(L);
luaA_object_ref(L, -1);
screen_array_append(screens, new_screen);
return new_screen;
} }
/* Monitors were introduced in RandR 1.5 */ /* Monitors were introduced in RandR 1.5 */
#ifdef XCB_RANDR_GET_MONITORS #ifdef XCB_RANDR_GET_MONITORS
static bool static void
screen_scan_randr_monitors(void) screen_scan_randr_monitors(lua_State *L, screen_array_t *screens)
{ {
xcb_randr_get_monitors_cookie_t monitors_c = xcb_randr_get_monitors(globalconf.connection, globalconf.screen->root, 1); xcb_randr_get_monitors_cookie_t monitors_c = xcb_randr_get_monitors(globalconf.connection, globalconf.screen->root, 1);
xcb_randr_get_monitors_reply_t *monitors_r = xcb_randr_get_monitors_reply(globalconf.connection, monitors_c, NULL); xcb_randr_get_monitors_reply_t *monitors_r = xcb_randr_get_monitors_reply(globalconf.connection, monitors_c, NULL);
@ -256,7 +260,6 @@ screen_scan_randr_monitors(void)
for(monitor_iter = xcb_randr_get_monitors_monitors_iterator(monitors_r); for(monitor_iter = xcb_randr_get_monitors_monitors_iterator(monitors_r);
monitor_iter.rem; xcb_randr_monitor_info_next(&monitor_iter)) monitor_iter.rem; xcb_randr_monitor_info_next(&monitor_iter))
{ {
lua_State *L = globalconf_get_lua_State();
screen_t *new_screen; screen_t *new_screen;
screen_output_t output; screen_output_t output;
xcb_randr_output_t *randr_outputs; xcb_randr_output_t *randr_outputs;
@ -266,11 +269,12 @@ screen_scan_randr_monitors(void)
if(!xcb_randr_monitor_info_outputs_length(monitor_iter.data)) if(!xcb_randr_monitor_info_outputs_length(monitor_iter.data))
continue; continue;
new_screen = screen_new(L); new_screen = screen_add(L, screens);
new_screen->geometry.x = monitor_iter.data->x; new_screen->geometry.x = monitor_iter.data->x;
new_screen->geometry.y = monitor_iter.data->y; new_screen->geometry.y = monitor_iter.data->y;
new_screen->geometry.width = monitor_iter.data->width; new_screen->geometry.width = monitor_iter.data->width;
new_screen->geometry.height = monitor_iter.data->height; 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_width = monitor_iter.data->width_in_millimeters;
output.mm_height = monitor_iter.data->height_in_millimeters; output.mm_height = monitor_iter.data->height_in_millimeters;
@ -285,7 +289,7 @@ screen_scan_randr_monitors(void)
output.name[len] = '\0'; output.name[len] = '\0';
p_delete(&name_r); p_delete(&name_r);
} else { } else {
output.name = strdup("unknown"); output.name = a_strdup("unknown");
} }
randr_output_array_init(&output.outputs); randr_output_array_init(&output.outputs);
@ -295,24 +299,19 @@ screen_scan_randr_monitors(void)
} }
screen_output_array_append(&new_screen->outputs, output); screen_output_array_append(&new_screen->outputs, output);
found = true;
screen_add(L, -1);
} }
p_delete(&monitors_r); p_delete(&monitors_r);
return found;
} }
#else #else
static bool static void
screen_scan_randr_monitors(void) screen_scan_randr_monitors(lua_State *L, screen_array_t *screens)
{ {
return false;
} }
#endif #endif
static bool static void
screen_scan_randr_crtcs(void) screen_scan_randr_crtcs(lua_State *L, screen_array_t *screens)
{ {
/* A quick XRandR recall: /* A quick XRandR recall:
* You have CRTC that manages a part of a SCREEN. * You have CRTC that manages a part of a SCREEN.
@ -320,21 +319,11 @@ screen_scan_randr_crtcs(void)
xcb_randr_get_screen_resources_cookie_t screen_res_c = xcb_randr_get_screen_resources(globalconf.connection, globalconf.screen->root); xcb_randr_get_screen_resources_cookie_t screen_res_c = xcb_randr_get_screen_resources(globalconf.connection, globalconf.screen->root);
xcb_randr_get_screen_resources_reply_t *screen_res_r = xcb_randr_get_screen_resources_reply(globalconf.connection, screen_res_c, NULL); xcb_randr_get_screen_resources_reply_t *screen_res_r = xcb_randr_get_screen_resources_reply(globalconf.connection, screen_res_c, NULL);
/* Only use the data from XRandR if there is more than one screen
* defined. This should work around the broken nvidia driver. */
if (screen_res_r->num_crtcs <= 1)
{
p_delete(&screen_res_r);
return false;
}
/* We go through CRTC, and build a screen for each one. */ /* We go through CRTC, and build a screen for each one. */
xcb_randr_crtc_t *randr_crtcs = xcb_randr_get_screen_resources_crtcs(screen_res_r); xcb_randr_crtc_t *randr_crtcs = xcb_randr_get_screen_resources_crtcs(screen_res_r);
for(int i = 0; i < screen_res_r->num_crtcs; i++) for(int i = 0; i < screen_res_r->num_crtcs; i++)
{ {
lua_State *L = globalconf_get_lua_State();
/* Get info on the output crtc */ /* Get info on the output crtc */
xcb_randr_get_crtc_info_cookie_t crtc_info_c = xcb_randr_get_crtc_info(globalconf.connection, randr_crtcs[i], XCB_CURRENT_TIME); xcb_randr_get_crtc_info_cookie_t crtc_info_c = xcb_randr_get_crtc_info(globalconf.connection, randr_crtcs[i], XCB_CURRENT_TIME);
xcb_randr_get_crtc_info_reply_t *crtc_info_r = xcb_randr_get_crtc_info_reply(globalconf.connection, crtc_info_c, NULL); xcb_randr_get_crtc_info_reply_t *crtc_info_r = xcb_randr_get_crtc_info_reply(globalconf.connection, crtc_info_c, NULL);
@ -344,11 +333,12 @@ screen_scan_randr_crtcs(void)
continue; continue;
/* Prepare the new screen */ /* Prepare the new screen */
screen_t *new_screen = screen_new(L); screen_t *new_screen = screen_add(L, screens);
new_screen->geometry.x = crtc_info_r->x; new_screen->geometry.x = crtc_info_r->x;
new_screen->geometry.y = crtc_info_r->y; new_screen->geometry.y = crtc_info_r->y;
new_screen->geometry.width= crtc_info_r->width; new_screen->geometry.width= crtc_info_r->width;
new_screen->geometry.height= crtc_info_r->height; 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); xcb_randr_output_t *randr_outputs = xcb_randr_get_crtc_info_outputs(crtc_info_r);
@ -373,77 +363,92 @@ screen_scan_randr_crtcs(void)
p_delete(&output_info_r); p_delete(&output_info_r);
}
screen_add(L, -1); if (A_STREQ(name, "default"))
{
/* non RandR 1.2+ X driver don't return any usable multihead
* data. I'm looking at you, nvidia binary blob!
*/
warn("Ignoring RandR, only a compatibility layer is present.");
/* Get rid of the screens that we already created */
foreach(screen, *screens)
luaA_object_unref(L, *screen);
screen_array_wipe(screens);
screen_array_init(screens);
return;
}
}
p_delete(&crtc_info_r); p_delete(&crtc_info_r);
} }
p_delete(&screen_res_r); p_delete(&screen_res_r);
return true;
} }
static bool static void
screen_scan_randr(void) screen_scan_randr(lua_State *L, screen_array_t *screens)
{ {
xcb_randr_query_version_reply_t *version_reply;
uint32_t major_version;
uint32_t minor_version;
/* Check for extension before checking for XRandR */ /* Check for extension before checking for XRandR */
if(xcb_get_extension_data(globalconf.connection, &xcb_randr_id)->present) if(!xcb_get_extension_data(globalconf.connection, &xcb_randr_id)->present)
{ return;
xcb_randr_query_version_reply_t *version_reply =
version_reply =
xcb_randr_query_version_reply(globalconf.connection, xcb_randr_query_version_reply(globalconf.connection,
xcb_randr_query_version(globalconf.connection, 1, 5), 0); xcb_randr_query_version(globalconf.connection, 1, 5), 0);
if(version_reply) if(!version_reply)
{ return;
uint32_t major_version = version_reply->major_version;
uint32_t minor_version = version_reply->minor_version;
bool found;
major_version = version_reply->major_version;
minor_version = version_reply->minor_version;
p_delete(&version_reply); p_delete(&version_reply);
/* Do we agree on a supported version? */ /* Do we agree on a supported version? */
if (major_version != 1 || minor_version < 2) if (major_version != 1 || minor_version < 2)
return false; return;
globalconf.have_randr_13 = minor_version >= 3; 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
if (minor_version >= 5) /* We want to know when something changes */
found = screen_scan_randr_monitors(); xcb_randr_select_input(globalconf.connection,
globalconf.screen->root,
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
if (globalconf.have_randr_15)
screen_scan_randr_monitors(L, screens);
else else
found = screen_scan_randr_crtcs(); screen_scan_randr_crtcs(L, screens);
if (found)
screen_update_primary();
else
return false;
return screens_exist();
}
} }
return false; static void
} screen_scan_xinerama(lua_State *L, screen_array_t *screens)
static bool
screen_scan_xinerama(void)
{
bool xinerama_is_active = false;
/* Check for extension before checking for Xinerama */
if(xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
{ {
bool xinerama_is_active;
xcb_xinerama_is_active_reply_t *xia; xcb_xinerama_is_active_reply_t *xia;
xia = xcb_xinerama_is_active_reply(globalconf.connection, xcb_xinerama_is_active(globalconf.connection), NULL);
xinerama_is_active = xia->state;
p_delete(&xia);
}
if(xinerama_is_active)
{
xcb_xinerama_query_screens_reply_t *xsq; xcb_xinerama_query_screens_reply_t *xsq;
xcb_xinerama_screen_info_t *xsi; xcb_xinerama_screen_info_t *xsi;
int xinerama_screen_number; int xinerama_screen_number;
/* Check for extension before checking for Xinerama */
if(!xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
return;
xia = xcb_xinerama_is_active_reply(globalconf.connection, xcb_xinerama_is_active(globalconf.connection), NULL);
xinerama_is_active = xia->state;
p_delete(&xia);
if(!xinerama_is_active)
return;
xsq = xcb_xinerama_query_screens_reply(globalconf.connection, xsq = xcb_xinerama_query_screens_reply(globalconf.connection,
xcb_xinerama_query_screens_unchecked(globalconf.connection), xcb_xinerama_query_screens_unchecked(globalconf.connection),
NULL); NULL);
@ -451,33 +456,26 @@ screen_scan_xinerama(void)
xsi = xcb_xinerama_query_screens_screen_info(xsq); xsi = xcb_xinerama_query_screens_screen_info(xsq);
xinerama_screen_number = xcb_xinerama_query_screens_screen_info_length(xsq); xinerama_screen_number = xcb_xinerama_query_screens_screen_info_length(xsq);
/* now check if screens overlaps (same x,y): if so, we take only the biggest one */
for(int screen = 0; screen < xinerama_screen_number; screen++) for(int screen = 0; screen < xinerama_screen_number; screen++)
{ {
lua_State *L = globalconf_get_lua_State(); screen_t *s = screen_add(L, screens);
screen_t *s = screen_new(L); s->geometry.x = xsi[screen].x_org;
s->geometry = screen_xsitoarea(xsi[screen]); s->geometry.y = xsi[screen].y_org;
screen_add(L, -1); s->geometry.width = xsi[screen].width;
s->geometry.height = xsi[screen].height;
} }
p_delete(&xsq); p_delete(&xsq);
return screens_exist();
} }
return false; static void screen_scan_x11(lua_State *L, screen_array_t *screens)
}
static void screen_scan_x11(void)
{ {
lua_State *L = globalconf_get_lua_State();
xcb_screen_t *xcb_screen = globalconf.screen; xcb_screen_t *xcb_screen = globalconf.screen;
screen_t *s = screen_new(L); screen_t *s = screen_add(L, screens);
s->geometry.x = 0; s->geometry.x = 0;
s->geometry.y = 0; s->geometry.y = 0;
s->geometry.width = xcb_screen->width_in_pixels; s->geometry.width = xcb_screen->width_in_pixels;
s->geometry.height = xcb_screen->height_in_pixels; s->geometry.height = xcb_screen->height_in_pixels;
screen_add(L, -1);
} }
/** Get screens informations and fill global configuration. /** Get screens informations and fill global configuration.
@ -485,8 +483,145 @@ static void screen_scan_x11(void)
void void
screen_scan(void) screen_scan(void)
{ {
if(!screen_scan_randr() && !screen_scan_xinerama()) lua_State *L;
screen_scan_x11();
L = globalconf_get_lua_State();
screen_scan_randr(L, &globalconf.screens);
if (globalconf.screens.len == 0)
screen_scan_xinerama(L, &globalconf.screens);
if (globalconf.screens.len == 0)
screen_scan_x11(L, &globalconf.screens);
assert(globalconf.screens.len > 0);
screen_deduplicate(L, &globalconf.screens);
foreach(screen, globalconf.screens) {
(*screen)->valid = true;
luaA_object_push(L, *screen);
luaA_object_emit_signal(L, -1, "added", 0);
lua_pop(L, 1);
}
screen_update_primary();
}
/* Called when a screen is removed, removes references to the old screen */
static void
screen_removed(lua_State *L, int sidx)
{
screen_t *screen = luaA_checkudata(L, sidx, &screen_class);
luaA_object_emit_signal(L, sidx, "removed", 0);
if (globalconf.primary_screen == screen)
globalconf.primary_screen = NULL;
foreach(c, globalconf.clients) {
if((*c)->screen == screen)
screen_client_moveto(*c, screen_getbycoord(
(*c)->geometry.x, (*c)->geometry.y), false);
}
}
static void
screen_modified(screen_t *existing_screen, screen_t *other_screen)
{
lua_State *L = globalconf_get_lua_State();
if(!AREA_EQUAL(existing_screen->geometry, other_screen->geometry)) {
existing_screen->geometry = other_screen->geometry;
luaA_object_push(L, existing_screen);
luaA_object_emit_signal(L, -1, "property::geometry", 0);
luaA_object_emit_signal(L, -1, "property::workarea", 0);
lua_pop(L, 1);
}
bool outputs_changed = existing_screen->outputs.len != other_screen->outputs.len;
if(!outputs_changed)
for(int i = 0; i < existing_screen->outputs.len; i++) {
screen_output_t *existing_output = &existing_screen->outputs.tab[i];
screen_output_t *other_output = &other_screen->outputs.tab[i];
outputs_changed |= existing_output->mm_width != other_output->mm_width;
outputs_changed |= existing_output->mm_height != other_output->mm_height;
outputs_changed |= A_STRNEQ(existing_output->name, other_output->name);
}
/* Brute-force update the outputs by swapping */
screen_output_array_t tmp = other_screen->outputs;
other_screen->outputs = existing_screen->outputs;
existing_screen->outputs = tmp;
if(outputs_changed) {
luaA_object_push(L, existing_screen);
luaA_object_emit_signal(L, -1, "property::outputs", 0);
lua_pop(L, 1);
}
}
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);
screen_deduplicate(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);
(*new_screen)->valid = true;
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) {
screen_array_take(&globalconf.screens, i);
i--;
luaA_object_push(L, old_screen);
screen_removed(L, -1);
lua_pop(L, 1);
luaA_object_unref(L, old_screen);
old_screen->valid = false;
}
}
/* Update changed screens */
foreach(existing_screen, globalconf.screens)
foreach(new_screen, new_screens)
if((*existing_screen)->xid == (*new_screen)->xid)
screen_modified(*existing_screen, *new_screen);
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. /** Return the squared distance of the given screen to the coordinates.
@ -904,7 +1039,7 @@ screen_class_setup(lua_State *L)
luaA_class_setup(L, &screen_class, "screen", NULL, luaA_class_setup(L, &screen_class, "screen", NULL,
(lua_class_allocator_t) screen_new, (lua_class_allocator_t) screen_new,
(lua_class_collector_t) screen_wipe, (lua_class_collector_t) screen_wipe,
NULL, (lua_class_checker_t) screen_checker,
luaA_class_index_miss_property, luaA_class_newindex_miss_property, luaA_class_index_miss_property, luaA_class_newindex_miss_property,
screen_methods, screen_meta); screen_methods, screen_meta);
luaA_class_add_property(&screen_class, "geometry", luaA_class_add_property(&screen_class, "geometry",
@ -925,6 +1060,8 @@ screen_class_setup(lua_State *L)
NULL); NULL);
signal_add(&screen_class.signals, "property::workarea"); signal_add(&screen_class.signals, "property::workarea");
signal_add(&screen_class.signals, "property::geometry");
signal_add(&screen_class.signals, "property::outputs");
/** /**
* @signal .primary_changed * @signal .primary_changed
*/ */
@ -934,6 +1071,11 @@ screen_class_setup(lua_State *L)
* @signal .added * @signal .added
*/ */
signal_add(&screen_class.signals, "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 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -33,10 +33,14 @@ ARRAY_TYPE(screen_output_t, screen_output)
struct a_screen struct a_screen
{ {
LUA_OBJECT_HEADER LUA_OBJECT_HEADER
/** Is this screen still valid and may be used? */
bool valid;
/** Screen geometry */ /** Screen geometry */
area_t geometry; area_t geometry;
/** The screen outputs informations */ /** The screen outputs informations */
screen_output_array_t outputs; screen_output_array_t outputs;
/** Some XID identifying this screen */
uint32_t xid;
}; };
ARRAY_FUNCS(screen_t *, screen, DO_NOTHING) ARRAY_FUNCS(screen_t *, screen, DO_NOTHING)