aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/libLumina/LuminaRandR-X11.cpp
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2017-06-22 06:46:54 -0400
committerKen Moore <ken@ixsystems.com>2017-06-22 06:46:54 -0400
commitee833dfa9e17521e59ad84634cf3ef4115bda606 (patch)
treec9101032fe84ba42823e0616de2216a6eaaf67a7 /src-qt5/core/libLumina/LuminaRandR-X11.cpp
parentMerge branch 'master' of github.com:trueos/lumina (diff)
downloadlumina-ee833dfa9e17521e59ad84634cf3ef4115bda606.tar.gz
lumina-ee833dfa9e17521e59ad84634cf3ef4115bda606.tar.bz2
lumina-ee833dfa9e17521e59ad84634cf3ef4115bda606.zip
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.
Diffstat (limited to 'src-qt5/core/libLumina/LuminaRandR-X11.cpp')
-rw-r--r--src-qt5/core/libLumina/LuminaRandR-X11.cpp312
1 files changed, 89 insertions, 223 deletions
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; i<out_len; i++){ p_obj->outputs << xcb_randr_monitor_info_outputs(info)[i]; }
- qDebug() << "Info Loaded:" << p_obj->name;
- for(int i=0; i<p_obj->outputs.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; j<mode_len; j++){
p_obj->modes.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<QSize> resolutions;
- QSize physicalSizeMM;
- QString name;
- QList<xcb_randr_output_t> outputs;
-
- p_objects(){
- // Set the defaults for non-default-constructed variables
- primary = automatic = false;
- monitor_atom = 0;
- }
-
-};*/
-
-//Global Listing of Devices
-QList<OutputDevice> OutputDevice::availableMonitors(){
- QList<OutputDevice> 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; p<pinfo_len; p++){
+ xcb_atom_t atom = xcb_randr_list_output_properties_atoms(pinfo)[p];
+ //Property Name
+ QString name = atomToName(atom);
+ //Property Value
+ xcb_randr_query_output_property_reply_t *pvalue = xcb_randr_query_output_property_reply(QX11Info::connection(),
+ xcb_randr_query_output_property_unchecked(QX11Info::connection(), output, atom),
+ NULL);
+ QStringList values = atomsToNames ( (xcb_atom_t*) xcb_randr_query_output_property_valid_values(pvalue), xcb_randr_query_output_property_valid_values_length(pvalue) ); //need to read values
+ free(pvalue);
+ qDebug() << " -- " << name << "=" << values;
- //Free up any objects we are done with
- free(reply);
- //Return the list
- return list;
-}
+ }
+*/
-//FUNCTIONS (do not use directly - use the static list function instead)
+//FUNCTIONS (do not use typically use manually - use the OutputDeviceList class instead)
OutputDevice::OutputDevice(QString id){
//p_obj = new p_objects();
p_obj.name = id;
- p_obj.primary = p_obj.automatic = false;
- p_obj.monitor_atom = 0;
+ p_obj.primary = false;
p_obj.output = 0;
bool ok = false;
p_obj.output = id.toInt(&ok);
@@ -158,43 +135,32 @@ OutputDevice::~OutputDevice(){
QString OutputDevice::ID(){ return p_obj.name; }
bool OutputDevice::isEnabled(){ return !p_obj.geometry.isNull(); }
bool OutputDevice::isPrimary(){ return p_obj.primary; }
-bool OutputDevice::isAutomatic(){ return p_obj.automatic; }
bool OutputDevice::isConnected(){ return !p_obj.modes.isEmpty(); }
QList<QSize> OutputDevice::availableResolutions(){ return p_obj.resolutions; }
QSize OutputDevice::currentResolution(){ return p_obj.geometry.size(); } //no concept of panning/scaling yet
QRect OutputDevice::currentGeometry(){ return p_obj.geometry; }
QSize OutputDevice::physicalSizeMM(){ return p_obj.physicalSizeMM; }
+QSize OutputDevice::physicalDPI(){
+ QSize dpi( qRound((p_obj.geometry.width() * 25.4)/p_obj.physicalSizeMM.width()), qRound((p_obj.geometry.height() * 25.4)/p_obj.physicalSizeMM.height() ) );
+ return dpi;
+}
//Modification
bool OutputDevice::setAsPrimary(bool set){
if(p_obj.primary == set){ return true; } //no change needed
- bool ok = false;
- for(int i=0; i<p_obj.outputs.length(); i++){
- if(set){ xcb_randr_set_output_primary (QX11Info::connection(), QX11Info::appRootWindow(), p_obj.outputs[i]); }
+ if(set){ xcb_randr_set_output_primary (QX11Info::connection(), QX11Info::appRootWindow(), p_obj.output); }
p_obj.primary = set; //Only need to push a "set" primary up through XCB - will automatically deactivate the other monitors
- ok = true;
- break;
- }
- return ok;
+ return true;
}
bool OutputDevice::disable(){
- //qDebug() << "Disable Monitor:" << p_obj.monitor_atom;
- if(p_obj.monitor_atom!=0){
+ if(p_obj.output!=0 && p_obj.current_mode!=0){
//qDebug() << " - Go ahead";
- for(int o=0; o<p_obj.outputs.length(); o++){
- for(int m=0; m<p_obj.modes.length(); m++){
- qDebug() << "Deleting Mode for Output:" << "Mode:" << p_obj.modes[m] << "Output:" << p_obj.outputs[o];
//XLib version
- //XRRDeleteOutputMode(QX11Info::display(), p_obj.outputs[o], p_obj.modes[m]);
+ //XRRDeleteOutputMode(QX11Info::display(), p_obj.output, p_obj.current_mode);
//XCB version
- xcb_randr_delete_output_mode(QX11Info::connection(), p_obj.outputs[o], p_obj.modes[m]);
- xcb_flush(QX11Info::connection());
- }
- }
- //xcb_randr_delete_monitor_checked(QX11Info::connection(), QX11Info::appRootWindow(), p_obj.monitor_atom);
- //p_obj.monitor_atom = 0;
+ xcb_randr_delete_output_mode(QX11Info::connection(), p_obj.output, p_obj.current_mode);
return true;
}
return false;
@@ -202,7 +168,7 @@ bool OutputDevice::disable(){
void OutputDevice::enable(QRect geom){
//if no geom provided, will add as the right-most screen at optimal resolution
- if(p_obj.monitor_atom!=0){ return; }
+ if(this->isEnabled()){ 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; i<outputnum; i++){
- xcb_randr_output_t output = xcb_randr_get_screen_resources_outputs(reply)[i];
- if(p_obj->output==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; i<outputnum; i++){
+ xcb_randr_output_t output = xcb_randr_get_screen_resources_outputs(reply)[i];
xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(QX11Info::connection(),
xcb_randr_get_output_info_unchecked(QX11Info::connection(), output, QX11Info::appTime()),
NULL);
- //Name
+ //Compare names
QString name = QString::fromLocal8Bit( (char*) xcb_randr_get_output_info_name(info), xcb_randr_get_output_info_name_length(info));
- if(
+ if(name == p_obj.name){ p_obj.output = output; break; }
+ }
+ free(reply);
}
-
- //Find the **active** monitor with the given id/name
- if(p_obj.monitor_atom !=0 || !p_obj.name.isEmpty() ){
- bool found = false;
- for(int i=0; i<2 && !found; i++){
- xcb_randr_get_monitors_cookie_t cookie = xcb_randr_get_monitors_unchecked(QX11Info::connection(), QX11Info::appRootWindow(), (i==0 ? 1 : 0) ); //toggle between active/not monitors
- xcb_randr_get_monitors_reply_t *reply = xcb_randr_get_monitors_reply(QX11Info::connection(), cookie, NULL);
- if(reply!=0){
- 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){
- 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<outputnum; i++){
xcb_randr_output_t output = xcb_randr_get_screen_resources_outputs(reply)[i];
- //Now display the info about this output
- xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(QX11Info::connection(),
- xcb_randr_get_output_info_unchecked(QX11Info::connection(), output, QX11Info::appTime()),
- NULL);
- //Name
- QString name = QString::fromLocal8Bit( (char*) xcb_randr_get_output_info_name(info), xcb_randr_get_output_info_name_length(info));
- OutputDevice dev(name);
+ OutputDevice dev(QString::number(output)); //use the raw output integer
out_devs.append(dev); //add to the internal list
}
- //QList<xcb_atom_t> 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<mode_len; m++){
- xcb_randr_mode_info_t mode = xcb_randr_get_screen_resources_modes(reply)[m];
- //qDebug() << " -- Mode:" << mode.id;
- qDebug() << " - Size Option:" << mode.width <<"x"<<mode.height;
- }*/
- for(int i=0; i<outputnum; i++){
- xcb_randr_output_t output = xcb_randr_get_screen_resources_outputs(reply)[i];
- //Now display the info about this output
- xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(QX11Info::connection(),
- xcb_randr_get_output_info_unchecked(QX11Info::connection(), output, QX11Info::appTime()),
- NULL);
- qDebug() << "==== Output Information #"+QString::number(i);
- //Name
- int name_len = xcb_randr_get_output_info_name_length(info);
- qDebug() << "Name:" << QString::fromLocal8Bit( (char*) xcb_randr_get_output_info_name(info), name_len);
-
- //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
-
-
- //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; p<pinfo_len; p++){
- xcb_atom_t atom = xcb_randr_list_output_properties_atoms(pinfo)[p];
- //Property Name
- QString name = atomToName(atom);
- //Property Value
- xcb_randr_query_output_property_reply_t *pvalue = xcb_randr_query_output_property_reply(QX11Info::connection(),
- xcb_randr_query_output_property_unchecked(QX11Info::connection(), output, atom),
- NULL);
- QStringList values = atomsToNames ( (xcb_atom_t*) xcb_randr_query_output_property_valid_values(pvalue), xcb_randr_query_output_property_valid_values_length(pvalue) ); //need to read values
- free(pvalue);
- qDebug() << " -- " << name << "=" << values;
-
- }
- free(pinfo);
- */
- free(info);
- }
-
free(reply);
}
@@ -366,7 +223,16 @@ OutputDeviceList::~OutputDeviceList(){
//Simplification functions for dealing with multiple monitors
void OutputDeviceList::setPrimaryMonitor(QString id){
+ for(int i=0; i<out_devs.length(); i++){
+ out_devs[i].setAsPrimary(out_devs[i].ID() == id);
+ }
+}
+QString OutputDeviceList::primaryMonitor(){
+ for(int i=0; i<out_devs.length(); i++){
+ if(out_devs[i].isPrimary()){ return out_devs[i].ID(); }
+ }
+ return "";
}
void OutputDeviceList::disableMonitor(QString id){
bgstack15