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.
|
||||
(C)2015 Marisa Kirisame, UnSX Team. For personal use mostly.
|
||||
schange.c : run command on crtc and output change events from RandR.
|
||||
(C)2015-2017 Marisa Kirisame, UnSX Team. For personal use mostly.
|
||||
Released under the GNU GPLv3 (or any later version).
|
||||
Please refer to <https://gnu.org/licenses/gpl.txt> for license terms.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -11,30 +13,91 @@
|
|||
#include <xcb/xcb_event.h>
|
||||
#include <xcb/randr.h>
|
||||
|
||||
const xcb_query_extension_reply_t *r;
|
||||
xcb_connection_t *c;
|
||||
xcb_screen_t *s;
|
||||
|
||||
char **cmdline;
|
||||
char *handler = 0;
|
||||
|
||||
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) )
|
||||
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();
|
||||
if ( !pid ) execvp(cmdline[0],cmdline);
|
||||
if ( !pid ) execvp(hargs[0],hargs);
|
||||
else waitpid(pid,0,0);
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
if ( argc < 2 ) return 1;
|
||||
cmdline = argv+1;
|
||||
if ( argc > 1 ) handler = argv[1];
|
||||
else printf("schange: warning, no handler assigned.\n");
|
||||
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;
|
||||
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_generic_event_t *e;
|
||||
while ( (e=xcb_wait_for_event(c)) )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue