From a3639dc7a22fca8aa0667329018de8cb80e5ca98 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 14 Dec 2015 19:36:09 +0200 Subject: [PATCH] Provide geometry correction data through the X11 selection mechanism This will be the basis of an interactive adjustment mode. --- source/main.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/source/main.c b/source/main.c index 061d7b7..8aa377f 100644 --- a/source/main.c +++ b/source/main.c @@ -49,6 +49,8 @@ typedef struct CompositedMonitor unsigned vertex_array; unsigned tessellation; unsigned nelements; + short *geometry_data; + unsigned geometry_data_size; } CompositedMonitor; typedef struct CompositedScreen @@ -95,6 +97,8 @@ typedef struct Compositor Atom root_pmap_atom; Atom correction_atom; Atom monitors_atom; + Atom geometry_data_atom; + Window selection_window; int dirty; } Compositor; @@ -641,6 +645,20 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito } } + monitor->geometry_data[0] = t; + for(i=0; i<3; ++i) + monitor->geometry_data[1+i] = eye[i]*10000; + for(y=0; y<2; ++y) + for(x=0; x<2; ++x) + { + i = 1+(1+y*2+x)*3; + monitor->geometry_data[i] = ((x-0.5f)*distance/monitor->perspective)*10000; + monitor->geometry_data[i+1] = (eye[1]+look[1]*distance-(y-0.5f)*look[2]*distance/monitor->perspective/aspect)*10000; + monitor->geometry_data[i+2] = (eye[2]+look[2]*distance+(y-0.5f)*look[1]*distance/monitor->perspective/aspect)*10000; + } + for(i=0; i<(t+1)*(t+1)*3; ++i) + monitor->geometry_data[16+i] = vertex_data[i]*10000; + for(y=t; y<=t; --y) for(x=t; x<=t; --x) { @@ -705,6 +723,7 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScre if(!monitor->enabled) { XRRFreeOutputInfo(output); + monitor->geometry_data = NULL; return 1; } @@ -726,6 +745,8 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScre monitor->index_buffer = buffers[1]; monitor->tessellation = 50; + monitor->geometry_data_size = (monitor->tessellation+1)*(monitor->tessellation+1)*3+16; + monitor->geometry_data = (short *)malloc(monitor->geometry_data_size*sizeof(short)); update_monitor_vertices(screen, monitor); stride = 4*sizeof(float); @@ -754,6 +775,24 @@ CompositedMonitor *find_monitor_by_name(CompositedScreen *screen, char *name) return NULL; } +CompositedMonitor *find_monitor_by_name_global(Compositor *compositor, char *name, CompositedScreen **screen) +{ + unsigned i, j; + + for(i=0; inscreens; ++i) + for(j=0; jscreens[i].nmonitors; ++j) + if(!strcmp(compositor->screens[i].monitors[j].name, name)) + { + if(screen) + *screen = &compositor->screens[i]; + return &compositor->screens[i].monitors[j]; + } + + if(screen) + *screen = NULL; + return NULL; +} + void update_geometry_correction(Compositor *compositor, CompositedScreen *screen) { Atom prop_type; @@ -970,6 +1009,7 @@ int initialize_compositor(Compositor *compositor) compositor->root_pmap_atom = XInternAtom(compositor->display, "_XROOTPMAP_ID", False); compositor->correction_atom = XInternAtom(compositor->display, "_MSP_GEOMETRY_CORRECTION", False); compositor->monitors_atom = XInternAtom(compositor->display, "_MSP_GEOMETRY_CORRECTION_MONITORS", False); + compositor->geometry_data_atom = XInternAtom(compositor->display, "_MSP_GEOMETRY_CORRECTION_DATA", False); compositor->nscreens = ScreenCount(compositor->display); compositor->screens = (CompositedScreen *)malloc(compositor->nscreens*sizeof(CompositedScreen)); @@ -977,6 +1017,9 @@ int initialize_compositor(Compositor *compositor) if(!initialize_screen(compositor, i)) return 0; + compositor->selection_window = XCreateWindow(compositor->display, compositor->screens[0].root, 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL); + XSetSelectionOwner(compositor->display, compositor->geometry_data_atom, compositor->selection_window, CurrentTime); + compositor->dirty = 1; return 1; @@ -1009,6 +1052,8 @@ void shutdown_screen(Compositor *compositor, CompositedScreen *screen) glDeleteBuffers(1, &screen->monitors[i].index_buffer); glDeleteVertexArrays(1, &screen->monitors[i].vertex_array); } + if(screen->monitors[i].geometry_data) + free(screen->monitors[i].geometry_data); } glDeleteTextures(1, &screen->root_texture); @@ -1042,6 +1087,8 @@ void shutdown_compositor(Compositor *compositor) shutdown_screen(compositor, &compositor->screens[i]); free(compositor->screens); + XDestroyWindow(compositor->display, compositor->selection_window); + XCloseDisplay(compositor->display); } @@ -1174,6 +1221,38 @@ void process_property_event(Compositor *compositor, XPropertyEvent *event) update_root_pixmap(compositor, screen); } +void process_selection_request_event(Compositor *compositor, XSelectionRequestEvent *event) +{ + Atom prop_type; + int prop_format; + unsigned long overflow; + unsigned long names_length; + XSelectionEvent notify; + + if(event->selection==compositor->geometry_data_atom) + { + char *monitor_name; + CompositedMonitor *monitor; + + XGetWindowProperty(compositor->display, event->requestor, event->property, 0, 64, False, XA_STRING, + &prop_type, &prop_format, &names_length, &overflow, (unsigned char **)&monitor_name); + if(prop_type!=XA_STRING || prop_format!=8) + return; + + monitor = find_monitor_by_name_global(compositor, monitor_name, NULL); + if(monitor && monitor->enabled) + XChangeProperty(compositor->display, event->requestor, event->property, XA_INTEGER, 16, PropModeReplace, (unsigned char *)monitor->geometry_data, monitor->geometry_data_size); + + notify.type = SelectionNotify; + notify.requestor = event->requestor; + notify.selection = event->selection; + notify.target = event->target; + notify.property = (monitor ? event->property : None); + notify.time = event->time; + XSendEvent(compositor->display, event->requestor, False, 0, (XEvent *)¬ify); + } +} + void process_damage_event(Compositor *compositor, XDamageNotifyEvent *event) { CompositedScreen *screen; @@ -1238,6 +1317,9 @@ void process_events(Compositor *compositor) case PropertyNotify: process_property_event(compositor, &event.xproperty); break; + case SelectionRequest: + process_selection_request_event(compositor, &event.xselectionrequest); + break; default: if(event.type==compositor->damage_event+XDamageNotify) process_damage_event(compositor, (XDamageNotifyEvent *)&event); -- 2.45.2