aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-qt5/core/libLumina/LuminaRandR-X11.cpp171
-rw-r--r--src-qt5/core/libLumina/LuminaRandR.h60
-rw-r--r--src-qt5/core/libLumina/test/main.cpp15
3 files changed, 191 insertions, 55 deletions
diff --git a/src-qt5/core/libLumina/LuminaRandR-X11.cpp b/src-qt5/core/libLumina/LuminaRandR-X11.cpp
index 85251b64..f8907741 100644
--- a/src-qt5/core/libLumina/LuminaRandR-X11.cpp
+++ b/src-qt5/core/libLumina/LuminaRandR-X11.cpp
@@ -6,13 +6,13 @@
//===========================================
#include "LuminaRandR.h"
-#include "xcb/randr.h"
-#include "xcb/xcb_atom.h"
+//#include "xcb/randr.h"
+//#include "xcb/xcb_atom.h"
#include <QDebug>
#include <QX11Info>
-static QString atomToName(xcb_atom_t atom){
+inline QString atomToName(xcb_atom_t atom){
xcb_get_atom_name_reply_t *nreply = xcb_get_atom_name_reply(QX11Info::connection(), xcb_get_atom_name_unchecked(QX11Info::connection(), atom), NULL);
QString name = QString::fromLocal8Bit(xcb_get_atom_name_name(nreply), xcb_get_atom_name_name_length(nreply));
free(nreply);
@@ -20,7 +20,7 @@ static QString atomToName(xcb_atom_t atom){
};
//More efficient method for converting lots of atoms to strings
-static QStringList atomsToNames(xcb_atom_t *atoms, unsigned int num){
+inline QStringList atomsToNames(xcb_atom_t *atoms, unsigned int num){
//qDebug() << "atomsToNames:" << num;
QList< xcb_get_atom_name_cookie_t > cookies;
//qDebug() << " - Get cookies";
@@ -36,12 +36,25 @@ static QStringList atomsToNames(xcb_atom_t *atoms, unsigned int num){
return names;
};
-class OutputDevice::p_objects{
+/*class OutputDevice::p_objects{
public:
- xcb_atom_t monitor_atom;
- QList<xcb_randr_output_t> outputs; //the actual output devices used by the monitor
+ 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(){
@@ -80,30 +93,44 @@ QList<OutputDevice> OutputDevice::availableMonitors(){
}
//FUNCTIONS (do not use directly - use the static list function instead)
-OutputDevice::OutputDevice(){
- enabled = false;
- p_obj = new p_objects();
- p_obj->monitor_atom = 0;
+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;
+ updateInfoCache();
}
OutputDevice::~OutputDevice(){
-
+ //delete p_obj;
}
+// INFORMATION FUNCTIONS (simply read from cache)
+QString OutputDevice::ID(){ qDebug() << "Find ID"; return p_obj.name; }
+bool OutputDevice::isEnabled(){ return p_obj.monitor_atom !=0; }
+bool OutputDevice::isPrimary(){ return p_obj.primary; }
+bool OutputDevice::isAutomatic(){ return p_obj.automatic; }
+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; }
+
//Modification
-bool OutputDevice::setAsPrimary(){
- if(isPrimary){ return true; }
- if( !p_obj->outputs.isEmpty() ){
- xcb_randr_set_output_primary (QX11Info::connection(), QX11Info::appRootWindow(), p_obj->outputs[0]);
- isPrimary = true;
+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]); }
+ p_obj.primary = set; //Only need to push a "set" primary up through XCB - will automatically deactivate the other monitors
+ ok = true;
+ break;
}
- return isPrimary;
+ return ok;
}
bool OutputDevice::disable(){
- if(p_obj->monitor_atom!=0){
- xcb_randr_delete_monitor(QX11Info::connection(), QX11Info::appRootWindow(), p_obj->monitor_atom);
- p_obj->monitor_atom = 0;
+ if(p_obj.monitor_atom!=0){
+ xcb_randr_delete_monitor(QX11Info::connection(), QX11Info::appRootWindow(), p_obj.monitor_atom);
+ p_obj.monitor_atom = 0;
return true;
}
return false;
@@ -111,7 +138,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(p_obj.monitor_atom!=0){ return; }
qDebug() << "Enable Monitor:" << geom;
}
@@ -120,7 +147,86 @@ void OutputDevice::changeResolution(QSize){
}
+void OutputDevice::updateInfoCache(){
+ //Find the **active** monitor with the given id/name
+ if(p_obj.monitor_atom !=0 || !p_obj.name.isEmpty() ){
+ 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){
+ 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() << " Index:" << iter.index << "Rem:" << iter.rem;
+ if( p_obj.monitor_atom == iter.data->name || p_obj.name == atomToName(iter.data->name) ){
+ if(p_obj.monitor_atom == 0){ p_obj.monitor_atom = iter.data->name; }
+ if(p_obj.name.isEmpty()){ p_obj.name = atomToName(iter.data->name); }
+ //Now update all the info in the cache
+ p_obj.primary = (iter.data->primary == 1);
+ p_obj.automatic = (iter.data->automatic == 1);
+ p_obj.geometry = QRect(iter.data->x, iter.data->y, iter.data->width, iter.data->height);
+ p_obj.physicalSizeMM = QSize(iter.data->width_in_millimeters, iter.data->height_in_millimeters);
+ //Load the "outputs"
+ p_obj.outputs.clear();
+ int out_len = xcb_randr_monitor_info_outputs_length(iter.data);
+ for(int i=0; i<out_len; i++){ p_obj.outputs << xcb_randr_monitor_info_outputs(iter.data)[i]; }
+ qDebug() << "Info Loaded:" << p_obj.name;
+ //break; //Finished with the information for this particular monitor
+ }
+ xcb_randr_monitor_info_next(&iter);
+ }
+ free(reply);
+ } //end check for reply structure
+ } //end loading of active/enabled monitor information
+
+ //Now load any information from the outputs
+ 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(),
+ xcb_randr_get_output_info_unchecked(QX11Info::connection(), p_obj.outputs[i], QX11Info::appTime()),
+ NULL);
+ if(info==0){ continue; } //bad output
+ //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.resolutions.clear();
+ for(int j=0; j<mode_len; j++){
+ xcb_randr_mode_t mode = xcb_randr_get_output_info_modes(info)[j];
+ //Still need to convert the mode into the resolution somehow
+ p_obj.resolutions << QSize(mode,1);
+ }
+ }
+
+}
+
+// ============================
+// OutputDeviceList
+// ============================
+
OutputDeviceList::OutputDeviceList(){
+
+ QList<xcb_randr_output_t> usedOutputs;
+ //Get the information about all the "enabled" monitors
+ xcb_randr_get_monitors_cookie_t cookieA = xcb_randr_get_monitors_unchecked(QX11Info::connection(), QX11Info::appRootWindow(), 1);
+ 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(reply);
+ while(iter.rem>0){
+ //qDebug() << "Found Monitor:";
+ //qDebug() << " Index:" << iter.index << "Rem:" << iter.rem;
+ QString name = atomToName(iter.data->name);
+ OutputDevice dev(name);
+ usedOutputs << dev.p_obj.outputs;
+
+ this->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
+
+/*
+ //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);
@@ -132,12 +238,9 @@ OutputDeviceList::OutputDeviceList(){
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:" << mode.width <<"x"<<mode.height;
+ //qDebug() << " -- Mode:" << mode.id;
+ qDebug() << " - Size Option:" << mode.width <<"x"<<mode.height;
}
- //qDebug() << " -- " << atomsToNames( (xcb_atom_t*) xcb_randr_get_screen_resources_modes(reply), xcb_randr_get_screen_resources_modes_length(reply) );
- qDebug() << " - Names:" << xcb_randr_get_screen_resources_names_length(reply);
- //qDebug() << " -- " << atomsToNames( (xcb_atom_t*) xcb_randr_get_screen_resources_names(reply), xcb_randr_get_screen_resources_names_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
@@ -147,7 +250,9 @@ OutputDeviceList::OutputDeviceList(){
qDebug() << "==== Output Information #"+QString::number(i);
//Modes
- qDebug() << "Number of Modes:" << xcb_randr_get_output_info_modes_length(info);
+ 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
@@ -155,7 +260,7 @@ OutputDeviceList::OutputDeviceList(){
//Names
int name_len = xcb_randr_get_output_info_name_length(info);
- qDebug() << "Names:" << atomsToNames( (xcb_atom_t*) xcb_randr_get_output_info_name(info), name_len);
+ qDebug() << "Names:"; //<< atomsToNames( (xcb_atom_t*) xcb_randr_get_output_info_name(info), name_len);
for(int n=0; n<name_len; n++){
QString name = atomToName( xcb_randr_get_output_info_name(info)[n] );
qDebug() << " -- " << name;
@@ -176,10 +281,6 @@ OutputDeviceList::OutputDeviceList(){
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
- /*for(int v=0; v<xcb_randr_query_output_property_valid_values_length(pvalue); v++){
- //values << QString::number(xcb_randr_query_output_property_valid_values(pvalue)[v] );
- values << atomToName( xcb_randr_query_output_property_valid_values(pvalue)[v] );
- }*/
free(pvalue);
qDebug() << " -- " << name << "=" << values;
@@ -189,7 +290,7 @@ OutputDeviceList::OutputDeviceList(){
free(info);
}
- free(reply);
+ free(reply);*/
}
OutputDeviceList::~OutputDeviceList(){
diff --git a/src-qt5/core/libLumina/LuminaRandR.h b/src-qt5/core/libLumina/LuminaRandR.h
index 448c676d..86c713db 100644
--- a/src-qt5/core/libLumina/LuminaRandR.h
+++ b/src-qt5/core/libLumina/LuminaRandR.h
@@ -17,17 +17,34 @@
#include <QRect>
#include <QList>
+// XCB
+#include "xcb/randr.h"
+#include "xcb/xcb_atom.h"
+
+struct 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;
+ }*/
+
+};
class OutputDevice{
public:
- QString id; //output ID
- bool enabled;
- bool isPrimary;
- //Monitor Geometry
- QPoint geom; //geometry of monitor within session
- //Monitor Resolution
- QSize cRes; //current resolution of the monitor (could be different from geom.size() if panning is enabled)
- QList<QSize> availRes; //available resolutions supported by the monitor
+
+ // EXPANSIONS TO-DO
//Refresh Rate
//int cHz; //current refresh rate
//QList<int> availHz; //available refresh rates
@@ -39,19 +56,32 @@ public:
static QList<OutputDevice> availableMonitors();
//FUNCTIONS (do not use directly - use the static list function instead)
- OutputDevice();
+ OutputDevice(QString id);
~OutputDevice();
+ //Information
+ QString ID();
+
+ bool isEnabled();
+ bool isPrimary();
+ bool isAutomatic();
+ QList<QSize> availableResolutions();
+ QSize currentResolution(); //could be different from geometry.size() if things like panning/rotation are enabled
+ QRect currentGeometry();
+
//Modification
- bool setAsPrimary();
+ bool setAsPrimary(bool);
bool disable();
void enable(QRect geom = QRect()); //if no geom provided, will add as the right-most screen at optimal resolution
void changeResolution(QSize);
-
+ void changeGeometry(QRect); //move a currently-enabled screen to another place
+
+ void updateInfoCache(); //Run this after all modification functions to refresh the current info for this device
+
//Now define a simple public_objects class so that each implementation
- // has a storage container for placing private objects as needed
- class p_objects;
- p_objects* p_obj;
+ // has a storage container for placing semi-private objects as needed
+ //class p_objects; //forward declaration - defined in the .cpp file
+ p_objects p_obj;
};
class OutputDeviceList : public QList<OutputDevice>{
@@ -64,7 +94,5 @@ public:
void disableMonitor(QString id);
//void enableMonitor(QString id,
-private:
-
};
#endif
diff --git a/src-qt5/core/libLumina/test/main.cpp b/src-qt5/core/libLumina/test/main.cpp
index 309fb938..b2ec9e41 100644
--- a/src-qt5/core/libLumina/test/main.cpp
+++ b/src-qt5/core/libLumina/test/main.cpp
@@ -5,9 +5,16 @@
int main(int argc, char** argv){
QApplication A(argc, argv);
- qDebug() << "Starting monitor scan...";
- QList<OutputDevice> outputs = OutputDevice::availableMonitors();
- qDebug() << "Finished monitor Scan";
- OutputDeviceList();
+ qDebug() << "Load Monitor Device Information";
+ OutputDeviceList devList;
+ qDebug() << "Detected Information:";
+ for(int i=0; i<devList.length(); i++){
+ qDebug() << "["+devList[i].ID()+"]";
+ qDebug() << " - isEnabled:" << devList[i].isEnabled();
+ qDebug() << " - isPrimary:" << devList[i].isPrimary();
+ qDebug() << " - isAutomatic:" << devList[i].isAutomatic();
+ qDebug() << " - Current Geometry:" << devList[i].currentGeometry();
+ qDebug() << " - Available Resolutions:" << devList[i].availableResolutions();
+ }
return 0;
}
bgstack15