schange now also handles output changes, so I can use it for automatically adding and removing monitors
also I now pass some parameters to the handler program so it knows event details
This commit is contained in:
parent
d2777092d1
commit
ec243ccb7d
1 changed files with 73 additions and 10 deletions
83
schange.c
83
schange.c
|
|
@ -1,9 +1,11 @@
|
||||||
/*
|
/*
|
||||||
schange.c : run command on screen change events from RandR.
|
schange.c : run command on crtc and output change events from RandR.
|
||||||
(C)2015 Marisa Kirisame, UnSX Team. For personal use mostly.
|
(C)2015-2017 Marisa Kirisame, UnSX Team. For personal use mostly.
|
||||||
Released under the GNU GPLv3 (or any later version).
|
Released under the GNU GPLv3 (or any later version).
|
||||||
Please refer to <https://gnu.org/licenses/gpl.txt> for license terms.
|
Please refer to <https://gnu.org/licenses/gpl.txt> for license terms.
|
||||||
*/
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
@ -11,30 +13,91 @@
|
||||||
#include <xcb/xcb_event.h>
|
#include <xcb/xcb_event.h>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
|
|
||||||
|
const xcb_query_extension_reply_t *r;
|
||||||
xcb_connection_t *c;
|
xcb_connection_t *c;
|
||||||
xcb_screen_t *s;
|
xcb_screen_t *s;
|
||||||
|
|
||||||
char **cmdline;
|
char *handler = 0;
|
||||||
|
|
||||||
void handle_event( xcb_generic_event_t *e )
|
void handle_event( xcb_generic_event_t *e )
|
||||||
{
|
{
|
||||||
const xcb_query_extension_reply_t *r;
|
|
||||||
r = xcb_get_extension_data(c,&xcb_randr_id);
|
|
||||||
if ( (e->response_type&0x7f) != (r->first_event+XCB_RANDR_NOTIFY) )
|
if ( (e->response_type&0x7f) != (r->first_event+XCB_RANDR_NOTIFY) )
|
||||||
return;
|
return;
|
||||||
/* fork and exec command */
|
xcb_randr_notify_data_t d = ((xcb_randr_notify_event_t*)e)->u;
|
||||||
|
char* hargs[8];
|
||||||
|
hargs[0] = handler;
|
||||||
|
char geom[64];
|
||||||
|
char oname[32];
|
||||||
|
int rot, len;
|
||||||
|
char *nm;
|
||||||
|
switch ( ((xcb_randr_notify_event_t*)e)->subCode )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
rot = d.cc.rotation&0xf;
|
||||||
|
hargs[1] = "cc";
|
||||||
|
hargs[2] = (rot==1)?"0":(rot==2)?"90":(rot==4)?"180":"270";
|
||||||
|
hargs[3] = (d.cc.rotation&0x10)?(d.cc.rotation&0x20)?"xy":"x"
|
||||||
|
:(d.cc.rotation&0x20)?"y":"none";
|
||||||
|
snprintf(geom,64,"%ux%u%+d%+d",d.cc.width,d.cc.height,d.cc.x,
|
||||||
|
d.cc.y);
|
||||||
|
hargs[4] = geom;
|
||||||
|
hargs[5] = 0;
|
||||||
|
printf("schange: crtc change\n rotation: %s\n"
|
||||||
|
" reflection: %s\n geometry: %s\n",hargs[2],hargs[3],
|
||||||
|
hargs[4]);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
hargs[1] = "oc";
|
||||||
|
xcb_randr_get_output_info_cookie_t ck;
|
||||||
|
ck = xcb_randr_get_output_info_unchecked(c,d.oc.output,
|
||||||
|
d.oc.config_timestamp);
|
||||||
|
xcb_randr_get_output_info_reply_t *inf;
|
||||||
|
inf = xcb_randr_get_output_info_reply(c,ck,0);
|
||||||
|
if ( !inf ) hargs[2] = "UNKNOWN";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = xcb_randr_get_output_info_name_length(inf);
|
||||||
|
nm = (char*)xcb_randr_get_output_info_name(inf);
|
||||||
|
strncpy(oname,nm,len);
|
||||||
|
oname[len] = 0;
|
||||||
|
hargs[2] = oname;
|
||||||
|
}
|
||||||
|
hargs[3] = (d.oc.connection==0)?"connected"
|
||||||
|
:(d.oc.connection==1)?"disconnected":"unknown";
|
||||||
|
hargs[4] = 0;
|
||||||
|
printf("schange: output change\n name: %s\n"
|
||||||
|
" connection: %s\n",hargs[2],hargs[3]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* ??? */
|
||||||
|
printf("schange: unhandled subcode %u\n",
|
||||||
|
((xcb_randr_notify_event_t*)e)->subCode);
|
||||||
|
hargs[1] = "unknown";
|
||||||
|
hargs[2] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* skip everything if there's no handler registered */
|
||||||
|
if ( !handler ) return;
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if ( !pid ) execvp(cmdline[0],cmdline);
|
if ( !pid ) execvp(hargs[0],hargs);
|
||||||
else waitpid(pid,0,0);
|
else waitpid(pid,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
if ( argc < 2 ) return 1;
|
if ( argc > 1 ) handler = argv[1];
|
||||||
cmdline = argv+1;
|
else printf("schange: warning, no handler assigned.\n");
|
||||||
c = xcb_connect(0,0);
|
c = xcb_connect(0,0);
|
||||||
|
r = xcb_get_extension_data(c,&xcb_randr_id);
|
||||||
|
if ( !r->present )
|
||||||
|
{
|
||||||
|
printf("schange: no RandR extension present\n");
|
||||||
|
xcb_disconnect(c);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
|
s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
|
||||||
xcb_randr_select_input(c,s->root,XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE);
|
xcb_randr_select_input(c,s->root,XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE
|
||||||
|
|XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
|
||||||
xcb_flush(c);
|
xcb_flush(c);
|
||||||
xcb_generic_event_t *e;
|
xcb_generic_event_t *e;
|
||||||
while ( (e=xcb_wait_for_event(c)) )
|
while ( (e=xcb_wait_for_event(c)) )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue