diff --git a/event.c b/event.c index f52723330..ee121362d 100644 --- a/event.c +++ b/event.c @@ -827,6 +827,9 @@ event_handle_randr_output_change_notify(xcb_randr_notify_event_t *ev) p_delete(&output_name); p_delete(&info); + + /* The docs for RRSetOutputPrimary say we get this signal */ + screen_update_primary(); } } diff --git a/globalconf.h b/globalconf.h index 4d44d9d96..8d5791cc6 100644 --- a/globalconf.h +++ b/globalconf.h @@ -82,6 +82,8 @@ typedef struct screen_array_t screens; /** The primary screen, access through screen_get_primary() */ screen_t *primary_screen; + /** Do we have RandR 1.3 or newer? */ + bool have_randr_13; /** Root window key bindings */ key_array_t keys; /** Root window mouse bindings */ diff --git a/objects/screen.c b/objects/screen.c index d0cecc527..a18d9646c 100644 --- a/objects/screen.c +++ b/objects/screen.c @@ -61,6 +61,8 @@ struct screen_output_t char *name; /** The size in millimeters */ uint32_t mm_width, mm_height; + /** The XID */ + xcb_randr_output_t output; }; static void @@ -151,11 +153,20 @@ screen_scan_randr(void) { xcb_randr_query_version_reply_t *version_reply = xcb_randr_query_version_reply(globalconf.connection, - xcb_randr_query_version(globalconf.connection, 1, 1), 0); + xcb_randr_query_version(globalconf.connection, 1, 3), 0); if(version_reply) { + uint32_t major_version = version_reply->major_version; + uint32_t minor_version = version_reply->minor_version; + p_delete(&version_reply); + /* Do we agree on a supported version? */ + if (major_version != 1 || minor_version < 2) + return false; + + globalconf.have_randr_13 = minor_version >= 3; + /* A quick XRandR recall: * You have CRTC that manages a part of a SCREEN. * Each CRTC can draw stuff on one or more OUTPUT. */ @@ -207,7 +218,8 @@ screen_scan_randr(void) screen_output_array_append(&new_screen->outputs, (screen_output_t) { .name = name, .mm_width = output_info_r->mm_width, - .mm_height = output_info_r->mm_height }); + .mm_height = output_info_r->mm_height, + .output = randr_outputs[j] }); p_delete(&output_info_r); } @@ -218,6 +230,7 @@ screen_scan_randr(void) } p_delete(&screen_res_r); + screen_update_primary(); return screens_exist(); } @@ -537,6 +550,47 @@ screen_get_index(screen_t *s) return 0; } +void +screen_update_primary(void) +{ + if (!globalconf.have_randr_13) + return; + + screen_t *primary_screen = NULL; + xcb_randr_get_output_primary_reply_t *primary = + xcb_randr_get_output_primary_reply(globalconf.connection, + xcb_randr_get_output_primary(globalconf.connection, globalconf.screen->root), + NULL); + + if (!primary) + return; + + foreach(screen, globalconf.screens) + { + foreach(output, (*screen)->outputs) + if (output->output == primary->output) + primary_screen = *screen; + } + p_delete(&primary); + + if (!primary_screen || primary_screen == globalconf.primary_screen) + return; + + lua_State *L = globalconf_get_lua_State(); + screen_t *old = globalconf.primary_screen; + globalconf.primary_screen = primary_screen; + + if (old) + { + luaA_object_push(L, old); + luaA_object_emit_signal(L, -1, "primary_changed", 0); + lua_pop(L, 1); + } + luaA_object_push(L, primary_screen); + luaA_object_emit_signal(L, -1, "primary_changed", 0); + lua_pop(L, 1); +} + screen_t * screen_get_primary(void) { @@ -662,6 +716,10 @@ screen_class_setup(lua_State *L) * @signal property::workarea */ signal_add(&screen_class.signals, "property::workarea"); + /** + * @signal primary_changed + */ + signal_add(&screen_class.signals, "primary_changed"); } // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/objects/screen.h b/objects/screen.h index 9cad113c4..28ecf6b20 100644 --- a/objects/screen.h +++ b/objects/screen.h @@ -47,6 +47,7 @@ bool screen_coord_in_screen(screen_t *, int, int); int screen_get_index(screen_t *); area_t display_area_get(void); void screen_client_moveto(client_t *, screen_t *, bool); +void screen_update_primary(void); screen_t *screen_get_primary(void); void luaA_pushscreen(lua_State *, screen_t *);