From ee833dfa9e17521e59ad84634cf3ef4115bda606 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 22 Jun 2017 06:46:54 -0400 Subject: Get the LuminaRandR class all finished up for *information purposes only*. 1. All the information retrieval systems are now in place and functional (much easier to use than parsing xrandr output manually). 2. Also get the "setPrimaryMonitor" functionality all setup and working. This *does* change the running X session in an atomic fashion. --- src-qt5/core/libLumina/LuminaRandR-X11.cpp | 312 ++++++++--------------------- src-qt5/core/libLumina/LuminaRandR.h | 23 +-- src-qt5/core/libLumina/test/main.cpp | 32 ++- 3 files changed, 123 insertions(+), 244 deletions(-) (limited to 'src-qt5/core') diff --git a/src-qt5/core/libLumina/LuminaRandR-X11.cpp b/src-qt5/core/libLumina/LuminaRandR-X11.cpp index 0e68cfd2..2e42aa48 100644 --- a/src-qt5/core/libLumina/LuminaRandR-X11.cpp +++ b/src-qt5/core/libLumina/LuminaRandR-X11.cpp @@ -32,36 +32,46 @@ inline QStringList atomsToNames(xcb_atom_t *atoms, unsigned int num){ return names; }; -inline bool loadScreenInfo(p_objects *p_obj, xcb_randr_monitor_info_t *info){ - if(p_obj->monitor_atom == 0){ p_obj->monitor_atom = info->name; } - if(p_obj->name.isEmpty()){ p_obj->name = atomToName(info->name); } - //Now update all the info in the cache - p_obj->primary = (info->primary == 1); - p_obj->automatic = (info->automatic == 1); - p_obj->geometry = QRect(info->x, info->y, info->width, info->height); - p_obj->physicalSizeMM = QSize(info->width_in_millimeters, info->height_in_millimeters); - //Load the "outputs" - /*p_obj->outputs.clear(); - int out_len = xcb_randr_monitor_info_outputs_length(info); - for(int i=0; ioutputs << xcb_randr_monitor_info_outputs(info)[i]; } - qDebug() << "Info Loaded:" << p_obj->name; - for(int i=0; ioutputs.length(); i++){*/ - xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(QX11Info::connection(), +inline bool loadScreenInfo(p_objects *p_obj){ + //Get the information associated with the output and save it in the p_objects cache + xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(QX11Info::connection(), xcb_randr_get_output_info_unchecked(QX11Info::connection(), p_obj->output, QX11Info::appTime()), NULL); - if(info==0){ continue; } //bad output + if(info==0){ return false; } //bad output value + //First read off the information associated with the output itself + if(p_obj->name.isEmpty()){ p_obj->name = QString::fromLocal8Bit( (char*) xcb_randr_get_output_info_name(info), xcb_randr_get_output_info_name_length(info)); } + p_obj->physicalSizeMM = QSize(info->mm_width, info->mm_height); + //Modes int mode_len = xcb_randr_get_output_info_modes_length(info); - //qDebug() << "Number of Modes:" << mode_len; - if(mode_len<=0){ continue; } //skip this output - not a physical screen which can be used p_obj->modes.clear(); for(int j=0; jmodes.append( xcb_randr_get_output_info_modes(info)[j] ); } - //} - //qDebug() << "INFO:" << p_obj->name; - //qDebug() << "Found Outputs:" << p_obj->outputs; - //qDebug() << "Found Modes:" << p_obj->modes; + xcb_randr_crtc_t crtc = info->crtc; + free(info); //done with output_info + + //Now load the current status of the output (crtc information) + xcb_randr_get_crtc_info_reply_t *cinfo = xcb_randr_get_crtc_info_reply(QX11Info::connection(), + xcb_randr_get_crtc_info_unchecked(QX11Info::connection(), crtc, QX11Info::appTime()), + NULL); + if(cinfo==0){ return false; } + p_obj->geometry = QRect(cinfo->x, cinfo->y, cinfo->width, cinfo->height); + p_obj->current_mode = cinfo->mode; + + free(cinfo); //done with crtc_info + + //And see if this output is currently the primary output + xcb_randr_get_output_primary_reply_t *preply = xcb_randr_get_output_primary_reply(QX11Info::connection(), + xcb_randr_get_output_primary_unchecked(QX11Info::connection(), QX11Info::appRootWindow()), NULL); + + if(preply !=0){ + p_obj->primary = (preply->output == p_obj->output); + free(preply); + }else{ + p_obj->primary = false; + } + //Now load all the screen resources information, and find matches for the current modes p_obj->resolutions.clear(); xcb_randr_get_screen_resources_reply_t *srreply = xcb_randr_get_screen_resources_reply(QX11Info::connection(), xcb_randr_get_screen_resources_unchecked(QX11Info::connection(), QX11Info::appRootWindow()), NULL); @@ -78,68 +88,35 @@ inline bool loadScreenInfo(p_objects *p_obj, xcb_randr_monitor_info_t *info){ return true; } -/*class OutputDevice::p_objects{ -public: - xcb_atom_t monitor_atom; //This is the index used to identify particular monitors (unique ID) - - //Cached Information - bool primary, automatic; - QRect geometry; - QList resolutions; - QSize physicalSizeMM; - QString name; - QList outputs; - - p_objects(){ - // Set the defaults for non-default-constructed variables - primary = automatic = false; - monitor_atom = 0; - } - -};*/ - -//Global Listing of Devices -QList OutputDevice::availableMonitors(){ - QList list; - //Get the list of monitors - xcb_randr_get_monitors_cookie_t cookie = xcb_randr_get_monitors_unchecked(QX11Info::connection(), QX11Info::appRootWindow(), 1); - xcb_randr_get_monitors_reply_t *reply = xcb_randr_get_monitors_reply(QX11Info::connection(), cookie, NULL); - if(reply==0){ - qDebug() << "Could not get monitor list"; - return list; - } - xcb_randr_monitor_info_iterator_t iter = xcb_randr_get_monitors_monitors_iterator(reply); - qDebug() << "Number of Monitors:" << xcb_randr_get_monitors_monitors_length(reply); - while(iter.rem>0){ - qDebug() << "Found Monitor:"; - //qDebug() << " Index:" << iter.index << "Rem:" << iter.rem; - QString name = atomToName(iter.data->name); - /*xcb_get_atom_name_reply_t *nreply = xcb_get_atom_name_reply(QX11Info::connection(), xcb_get_atom_name_unchecked(QX11Info::connection(), iter.data->name), NULL); - QString name = QString::fromLocal8Bit(xcb_get_atom_name_name(nreply), xcb_get_atom_name_name_length(nreply)); - free(nreply);*/ - - qDebug() << " - Name:" << iter.data->name << name; - qDebug() << " - Primary:" << (iter.data->primary == 1); - qDebug() << " - Automatic:" << (iter.data->automatic == 1); - qDebug() << " - nOutput:" << iter.data->nOutput; - qDebug() << " - Geometry:" << QRect(iter.data->x, iter.data->y, iter.data->width, iter.data->height); - qDebug() << " - Physical Size (mm):" << iter.data->width_in_millimeters << "x" << iter.data->height_in_millimeters; - qDebug() << " - Number of outputs:" << xcb_randr_monitor_info_outputs_length(iter.data); - xcb_randr_monitor_info_next(&iter); - } +/* + //Clones + qDebug() << "Number of Clones:" << xcb_randr_get_output_info_clones_length(info); + //Properties + /* xcb_randr_list_output_properties_reply_t *pinfo = xcb_randr_list_output_properties_reply(QX11Info::connection(), + xcb_randr_list_output_properties_unchecked(QX11Info::connection(), output), + NULL); + int pinfo_len = xcb_randr_list_output_properties_atoms_length(pinfo); + qDebug() << "Properties:" << pinfo_len; + for(int p=0; pisEnabled()){ return; } //already enabled qDebug() << "Enable Monitor:" << geom; } @@ -212,44 +178,25 @@ void OutputDevice::changeResolution(QSize){ } void OutputDevice::updateInfoCache(){ - xcb_randr_get_screen_resources_reply_t *reply = xcb_randr_get_screen_resources_reply(QX11Info::connection(), + if(p_obj.output==0){ + //Only have a name (first run) - need to find the corresponding output for this ID + xcb_randr_get_screen_resources_reply_t *reply = xcb_randr_get_screen_resources_reply(QX11Info::connection(), xcb_randr_get_screen_resources_unchecked(QX11Info::connection(), QX11Info::appRootWindow()), NULL); - int outputnum = xcb_randr_get_screen_resources_outputs_length(reply); - for(int i=0; ioutput==0){ - //Need to detect the name for this output (inefficient - better to pass in the output number directly) + int outputnum = xcb_randr_get_screen_resources_outputs_length(reply); + for(int i=0; i0){ - if( p_obj.monitor_atom == iter.data->name || p_obj.name == atomToName(iter.data->name) ){ - loadScreenInfo(&p_obj, iter.data); - found = true; - break; //Finished with the information for this particular monitor - } - xcb_randr_monitor_info_next(&iter); - } - free(reply); - } //end check for reply structure - } //end loop over active/inactive monitor state - } //end loading of active/enabled monitor information - + if(p_obj.output == 0){ return; } //bad ID/output? + loadScreenInfo(&p_obj); } // ============================ @@ -260,103 +207,13 @@ OutputDeviceList::OutputDeviceList(){ xcb_randr_get_screen_resources_reply_t *reply = xcb_randr_get_screen_resources_reply(QX11Info::connection(), xcb_randr_get_screen_resources_unchecked(QX11Info::connection(), QX11Info::appRootWindow()), NULL); + if(reply==0){ return; } //could not get screen information int outputnum = xcb_randr_get_screen_resources_outputs_length(reply); for(int i=0; i usedOutputs; - //Get the information about all the "enabled" monitors - /*for(int i=0; i<2; i++){ //loop over active/inactive monitors - qDebug() << "Scanning For Monitors:" << (i==0 ? "active" : "inactive"); - xcb_randr_get_monitors_cookie_t cookieA = xcb_randr_get_monitors_unchecked(QX11Info::connection(), QX11Info::appRootWindow(), (i==0 ? 1 : 10)); //toggle active/inactive monitors - xcb_randr_get_monitors_reply_t *replyA = xcb_randr_get_monitors_reply(QX11Info::connection(), cookieA, NULL); - if(replyA!=0){ - xcb_randr_monitor_info_iterator_t iter = xcb_randr_get_monitors_monitors_iterator(replyA); - qDebug() << "Number of Monitors:" << xcb_randr_get_monitors_monitors_length(replyA); - while(iter.rem>0){ - //qDebug() << "Found Monitor:"; - //qDebug() << " Index:" << iter.index << "Rem:" << iter.rem; - if(!usedOutputs.contains(iter.data->name)){ - QString name = atomToName(iter.data->name); - OutputDevice dev(name); - usedOutputs << iter.data->name; - out_devs.append(dev); //add to the internal list - } - xcb_randr_monitor_info_next(&iter); - } - //Free up any objects we are done with - free(replyA); - } //end loading of active/enabled monitors - } //end loop over active/inactive monitors - */ - qDebug() << "========================="; - //Now get the information about any **UNUSED** monitors/outputs - xcb_randr_get_screen_resources_reply_t *reply = xcb_randr_get_screen_resources_reply(QX11Info::connection(), - xcb_randr_get_screen_resources_unchecked(QX11Info::connection(), QX11Info::appRootWindow()), - NULL); - int outputnum = xcb_randr_get_screen_resources_outputs_length(reply); - qDebug() << "Probing Screen Resources:"; - qDebug() << " - Number of Outputs:" << outputnum; - //qDebug() << " - Number of CRTC's:" << xcb_randr_get_screen_resources_crtcs_length(reply); - //int mode_len =xcb_randr_get_screen_resources_modes_length(reply); - //qDebug() << " - Modes:" << mode_len; - /*for(int m=0; m resolutions; - QSize physicalSizeMM; + + QSize physicalSizeMM; //physical size of the display in MM QString name; - xcb_randr_output_t output; - QList modes; - /*p_objects(){ - // Set the defaults for non-default-constructed variables - primary = automatic = false; - monitor_atom = 0; - }*/ + xcb_randr_mode_t current_mode; + QList modes; //each mode is a combination of resolution + refresh rate + QList resolutions; //smaller subset of modes - just unique resolutions }; @@ -68,12 +63,12 @@ public: bool isEnabled(); bool isPrimary(); - bool isAutomatic(); bool isConnected(); QList availableResolutions(); QSize currentResolution(); //could be different from geometry.size() if things like panning/rotation are enabled QRect currentGeometry(); QSize physicalSizeMM(); + QSize physicalDPI(); //Modification bool setAsPrimary(bool); @@ -107,6 +102,8 @@ public: //Simplification functions for dealing with multiple monitors void setPrimaryMonitor(QString id); + QString primaryMonitor(); + void disableMonitor(QString id); //void enableMonitor(QString id, QRect geom); diff --git a/src-qt5/core/libLumina/test/main.cpp b/src-qt5/core/libLumina/test/main.cpp index 5c6fa67f..22f068dd 100644 --- a/src-qt5/core/libLumina/test/main.cpp +++ b/src-qt5/core/libLumina/test/main.cpp @@ -11,16 +11,32 @@ int main(int argc, char** argv){ qDebug() << "Detected Information:"; for(int i=0; iID()+"]"; - qDebug() << " - isEnabled:" << devList.at(i)->isEnabled(); - qDebug() << " - isPrimary:" << devList.at(i)->isPrimary(); - qDebug() << " - isAutomatic:" << devList.at(i)->isAutomatic(); - qDebug() << " - Current Geometry:" << devList.at(i)->currentGeometry(); - qDebug() << " - Physical Size (mm):" << devList.at(i)->physicalSizeMM(); - qDebug() << " - Available Resolutions:" << devList.at(i)->availableResolutions(); + qDebug() << " - isConnected:" << devList.at(i)->isConnected(); + if(devList.at(i)->isConnected()){ + qDebug() << " - isEnabled:" << devList.at(i)->isEnabled(); + qDebug() << " - isPrimary:" << devList.at(i)->isPrimary(); + qDebug() << " - Current Geometry:" << devList.at(i)->currentGeometry(); + qDebug() << " - Physical Size (mm):" << devList.at(i)->physicalSizeMM(); + qDebug() << " - Current DPI:" << devList.at(i)->physicalDPI(); + qDebug() << " - Available Resolutions:" << devList.at(i)->availableResolutions(); + } } - QString disable = "DVI-I-1"; + /*QString disable = "DVI-I-1"; qDebug() << "Try Disabling Monitor:" << disable; - devList.disableMonitor(disable); + devList.disableMonitor(disable);*/ + + QString setprimary = "eDP-1"; + if(devList.primaryMonitor() != setprimary){ + qDebug() << "Try setting monitor as primary:" << setprimary; + devList.setPrimaryMonitor(setprimary); + //Now see if the status changed on X itself + for(int i=0; iID() == setprimary){ + devList.at(i)->updateInfoCache(); //resync with X server info + qDebug() << "Successful:" << devList.at(i)->isPrimary(); + } + } + } qDebug() << "Finished Test!"; return 0; } -- cgit