Merge pull request #828 from psychon/screen-scan2
Stop restarting on RandR changes
This commit is contained in:
commit
6b6cbf4a1f
9
event.c
9
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
|
||||
|
@ -992,10 +991,8 @@ void event_init(void)
|
|||
const xcb_query_extension_reply_t *reply;
|
||||
|
||||
reply = xcb_get_extension_data(globalconf.connection, &xcb_randr_id);
|
||||
if (reply && reply->present) {
|
||||
xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
|
||||
if (reply && reply->present)
|
||||
globalconf.event_base_randr = reply->first_event;
|
||||
}
|
||||
|
||||
reply = xcb_get_extension_data(globalconf.connection, &xcb_shape_id);
|
||||
if (reply && reply->present)
|
||||
|
|
4
event.h
4
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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -446,12 +446,14 @@ function client.object.to_selected_tags(self)
|
|||
end
|
||||
end
|
||||
|
||||
if #tags == 0 then
|
||||
tags = self.screen.selected_tags
|
||||
end
|
||||
if self.screen then
|
||||
if #tags == 0 then
|
||||
tags = self.screen.selected_tags
|
||||
end
|
||||
|
||||
if #tags == 0 then
|
||||
tags = self.screen.tags
|
||||
if #tags == 0 then
|
||||
tags = self.screen.tags
|
||||
end
|
||||
end
|
||||
|
||||
if #tags ~= 0 then
|
||||
|
|
|
@ -285,6 +285,14 @@ end
|
|||
capi.client.connect_signal("property::struts", 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(...)
|
||||
return awfulwibox.new(...)
|
||||
end
|
||||
|
|
420
objects/screen.c
420
objects/screen.c
|
@ -50,6 +50,7 @@
|
|||
#include "banning.h"
|
||||
#include "objects/client.h"
|
||||
#include "objects/drawin.h"
|
||||
#include "event.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -182,6 +183,13 @@ screen_wipe(screen_t *s)
|
|||
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 */
|
||||
screen_t *
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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(new_screen->geometry.x == (*screen_to_test)->geometry.x
|
||||
&& new_screen->geometry.y == (*screen_to_test)->geometry.y)
|
||||
{
|
||||
/* we already have a screen for this area, just check if
|
||||
* it's not bigger and drop it */
|
||||
(*screen_to_test)->geometry.width =
|
||||
MAX(new_screen->geometry.width, (*screen_to_test)->geometry.width);
|
||||
(*screen_to_test)->geometry.height =
|
||||
MAX(new_screen->geometry.height, (*screen_to_test)->geometry.height);
|
||||
lua_remove(L, sidx);
|
||||
if (first_screen->geometry.width < second_screen->geometry.width
|
||||
&& first_screen->geometry.height < second_screen->geometry.height)
|
||||
/* Don't drop a smaller screen */
|
||||
continue;
|
||||
|
||||
if (first_screen->geometry.x == second_screen->geometry.x
|
||||
&& first_screen->geometry.y == second_screen->geometry.y) {
|
||||
/* Found a duplicate */
|
||||
first_screen->geometry.width = MAX(first_screen->geometry.width, second_screen->geometry.width);
|
||||
first_screen->geometry.height = MAX(first_screen->geometry.height, second_screen->geometry.height);
|
||||
|
||||
screen_array_take(screens, second);
|
||||
luaA_object_unref(L, second_screen);
|
||||
|
||||
/* Restart the search */
|
||||
screen_deduplicate(L, screens);
|
||||
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
|
||||
screens_exist(void)
|
||||
static screen_t *
|
||||
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 */
|
||||
#ifdef XCB_RANDR_GET_MONITORS
|
||||
static bool
|
||||
screen_scan_randr_monitors(void)
|
||||
static 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_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);
|
||||
monitor_iter.rem; xcb_randr_monitor_info_next(&monitor_iter))
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
screen_t *new_screen;
|
||||
screen_output_t output;
|
||||
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))
|
||||
continue;
|
||||
|
||||
new_screen = screen_new(L);
|
||||
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;
|
||||
|
@ -285,7 +289,7 @@ screen_scan_randr_monitors(void)
|
|||
output.name[len] = '\0';
|
||||
p_delete(&name_r);
|
||||
} else {
|
||||
output.name = strdup("unknown");
|
||||
output.name = a_strdup("unknown");
|
||||
}
|
||||
randr_output_array_init(&output.outputs);
|
||||
|
||||
|
@ -295,24 +299,19 @@ screen_scan_randr_monitors(void)
|
|||
}
|
||||
|
||||
screen_output_array_append(&new_screen->outputs, output);
|
||||
found = true;
|
||||
|
||||
screen_add(L, -1);
|
||||
}
|
||||
|
||||
p_delete(&monitors_r);
|
||||
return found;
|
||||
}
|
||||
#else
|
||||
static bool
|
||||
screen_scan_randr_monitors(void)
|
||||
static void
|
||||
screen_scan_randr_monitors(lua_State *L, screen_array_t *screens)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
screen_scan_randr_crtcs(void)
|
||||
static void
|
||||
screen_scan_randr_crtcs(lua_State *L, screen_array_t *screens)
|
||||
{
|
||||
/* A quick XRandR recall:
|
||||
* 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_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. */
|
||||
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++)
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
|
||||
/* 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_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;
|
||||
|
||||
/* 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.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);
|
||||
|
||||
|
@ -373,111 +363,119 @@ screen_scan_randr_crtcs(void)
|
|||
|
||||
|
||||
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(&screen_res_r);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
screen_scan_randr(void)
|
||||
static 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 */
|
||||
if(xcb_get_extension_data(globalconf.connection, &xcb_randr_id)->present)
|
||||
{
|
||||
xcb_randr_query_version_reply_t *version_reply =
|
||||
xcb_randr_query_version_reply(globalconf.connection,
|
||||
xcb_randr_query_version(globalconf.connection, 1, 5), 0);
|
||||
if(version_reply)
|
||||
{
|
||||
uint32_t major_version = version_reply->major_version;
|
||||
uint32_t minor_version = version_reply->minor_version;
|
||||
bool found;
|
||||
if(!xcb_get_extension_data(globalconf.connection, &xcb_randr_id)->present)
|
||||
return;
|
||||
|
||||
p_delete(&version_reply);
|
||||
version_reply =
|
||||
xcb_randr_query_version_reply(globalconf.connection,
|
||||
xcb_randr_query_version(globalconf.connection, 1, 5), 0);
|
||||
if(!version_reply)
|
||||
return;
|
||||
|
||||
/* Do we agree on a supported version? */
|
||||
if (major_version != 1 || minor_version < 2)
|
||||
return false;
|
||||
major_version = version_reply->major_version;
|
||||
minor_version = version_reply->minor_version;
|
||||
p_delete(&version_reply);
|
||||
|
||||
globalconf.have_randr_13 = minor_version >= 3;
|
||||
/* Do we agree on a supported version? */
|
||||
if (major_version != 1 || minor_version < 2)
|
||||
return;
|
||||
|
||||
if (minor_version >= 5)
|
||||
found = screen_scan_randr_monitors();
|
||||
else
|
||||
found = screen_scan_randr_crtcs();
|
||||
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 (found)
|
||||
screen_update_primary();
|
||||
else
|
||||
return false;
|
||||
return screens_exist();
|
||||
}
|
||||
}
|
||||
/* We want to know when something changes */
|
||||
xcb_randr_select_input(globalconf.connection,
|
||||
globalconf.screen->root,
|
||||
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
|
||||
|
||||
return false;
|
||||
if (globalconf.have_randr_15)
|
||||
screen_scan_randr_monitors(L, screens);
|
||||
else
|
||||
screen_scan_randr_crtcs(L, screens);
|
||||
}
|
||||
|
||||
static bool
|
||||
screen_scan_xinerama(void)
|
||||
static void
|
||||
screen_scan_xinerama(lua_State *L, screen_array_t *screens)
|
||||
{
|
||||
bool xinerama_is_active = false;
|
||||
bool xinerama_is_active;
|
||||
xcb_xinerama_is_active_reply_t *xia;
|
||||
xcb_xinerama_query_screens_reply_t *xsq;
|
||||
xcb_xinerama_screen_info_t *xsi;
|
||||
int xinerama_screen_number;
|
||||
|
||||
/* Check for extension before checking for Xinerama */
|
||||
if(xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
|
||||
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,
|
||||
xcb_xinerama_query_screens_unchecked(globalconf.connection),
|
||||
NULL);
|
||||
|
||||
xsi = xcb_xinerama_query_screens_screen_info(xsq);
|
||||
xinerama_screen_number = xcb_xinerama_query_screens_screen_info_length(xsq);
|
||||
|
||||
for(int screen = 0; screen < xinerama_screen_number; screen++)
|
||||
{
|
||||
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);
|
||||
screen_t *s = screen_add(L, screens);
|
||||
s->geometry.x = xsi[screen].x_org;
|
||||
s->geometry.y = xsi[screen].y_org;
|
||||
s->geometry.width = xsi[screen].width;
|
||||
s->geometry.height = xsi[screen].height;
|
||||
}
|
||||
|
||||
if(xinerama_is_active)
|
||||
{
|
||||
xcb_xinerama_query_screens_reply_t *xsq;
|
||||
xcb_xinerama_screen_info_t *xsi;
|
||||
int xinerama_screen_number;
|
||||
|
||||
xsq = xcb_xinerama_query_screens_reply(globalconf.connection,
|
||||
xcb_xinerama_query_screens_unchecked(globalconf.connection),
|
||||
NULL);
|
||||
|
||||
xsi = xcb_xinerama_query_screens_screen_info(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++)
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
screen_t *s = screen_new(L);
|
||||
s->geometry = screen_xsitoarea(xsi[screen]);
|
||||
screen_add(L, -1);
|
||||
}
|
||||
|
||||
p_delete(&xsq);
|
||||
|
||||
return screens_exist();
|
||||
}
|
||||
|
||||
return false;
|
||||
p_delete(&xsq);
|
||||
}
|
||||
|
||||
static void screen_scan_x11(void)
|
||||
static void screen_scan_x11(lua_State *L, screen_array_t *screens)
|
||||
{
|
||||
lua_State *L = globalconf_get_lua_State();
|
||||
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.y = 0;
|
||||
s->geometry.width = xcb_screen->width_in_pixels;
|
||||
s->geometry.height = xcb_screen->height_in_pixels;
|
||||
screen_add(L, -1);
|
||||
}
|
||||
|
||||
/** Get screens informations and fill global configuration.
|
||||
|
@ -485,8 +483,145 @@ static void screen_scan_x11(void)
|
|||
void
|
||||
screen_scan(void)
|
||||
{
|
||||
if(!screen_scan_randr() && !screen_scan_xinerama())
|
||||
screen_scan_x11();
|
||||
lua_State *L;
|
||||
|
||||
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.
|
||||
|
@ -904,7 +1039,7 @@ screen_class_setup(lua_State *L)
|
|||
luaA_class_setup(L, &screen_class, "screen", NULL,
|
||||
(lua_class_allocator_t) screen_new,
|
||||
(lua_class_collector_t) screen_wipe,
|
||||
NULL,
|
||||
(lua_class_checker_t) screen_checker,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
screen_methods, screen_meta);
|
||||
luaA_class_add_property(&screen_class, "geometry",
|
||||
|
@ -925,6 +1060,8 @@ screen_class_setup(lua_State *L)
|
|||
NULL);
|
||||
|
||||
signal_add(&screen_class.signals, "property::workarea");
|
||||
signal_add(&screen_class.signals, "property::geometry");
|
||||
signal_add(&screen_class.signals, "property::outputs");
|
||||
/**
|
||||
* @signal .primary_changed
|
||||
*/
|
||||
|
@ -934,6 +1071,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
|
||||
|
|
|
@ -33,10 +33,14 @@ ARRAY_TYPE(screen_output_t, screen_output)
|
|||
struct a_screen
|
||||
{
|
||||
LUA_OBJECT_HEADER
|
||||
/** Is this screen still valid and may be used? */
|
||||
bool valid;
|
||||
/** Screen geometry */
|
||||
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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue