Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmake/compiler_gnu_gcc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ else()
if(C0XFLAG)
message(STATUS "Using -std=c++0x")
add_definitions(-std=c++0x)
# Abuse the preprocessor to remove the
# override keyword on this old compiler.
add_definitions(-Doverride= )
else()
message(FATAL_ERROR "Compiler does not support -std=c++0x either. "
"Please upgrade your compiler."
Expand Down
11 changes: 11 additions & 0 deletions cmake/filelists.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,19 @@ list(APPEND libdspdfviewer_SRCS
pdfviewerwindow.cpp
dspdfviewer.cpp
windowrole.cpp
desktopsupport.cpp
desktopsupportfactory.cpp
desktopsupportexceptions.cpp
desktopsupport/generic.cpp
desktopsupport/i3.cpp
)

if(UseQtFive)
list(APPEND libdspdfviewer_SRCS
desktopsupport/win32.cpp
)
endif()

list(APPEND dspdfviewer_SRCS
main.cpp
)
Expand Down
File renamed without changes.
80 changes: 80 additions & 0 deletions desktopsupport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "desktopsupport.h"
#include "desktopsupportexceptions.h"

namespace {
bool isPrimary(const OutputPtr& p) {
return p->isPrimary();
}
}

OutputPtr DesktopSupport::getPrimary(const DesktopSupportErrorHandling& err) const {
OutputList vec=getOutputs();

if ( vec.empty () ) {
throw NoOutputsFound();
}

/** Return (first) primary screen */
for( OutputPtr& p: vec )
{
if ( p->isPrimary() ) {
return move(p);
}
}

/** No primary screen found!
*
* If there is not exactly one output left,
* we don't know 100% what to do.
*/

if ( vec.size() != 1 ) {
if ( err == DesktopSupportErrorHandling::ThrowOnError )
throw CannotDeterminePrimaryOutput(vec);
}

/** Errors ignored or exactly one screen left. Output it */
return move( vec.at(0) );
}

OutputPtr DesktopSupport::getSecondary(const DesktopSupportErrorHandling& err) const {
OutputList vec = getOutputs();
if ( vec.empty() ) {
throw NoOutputsFound();
}

/** Remove primary outputs from the set */
vec.erase(
remove_if( vec.begin(), vec.end(), isPrimary ),
vec.end()
);

/** If there is not exactly one output left,
* we have a problem.
*/
if ( vec.size() > 1 ) {
if ( err == DesktopSupportErrorHandling::ThrowOnError )
{
throw TooManyScreens(vec);
}
}

/** Return the first non-primary output */
return move( vec.at(0) );
}

void DesktopSupport::makeFullscreen( QWidget& window ) const {
if ( isFullscreen(window) )
return;
window.showFullScreen();
}

void DesktopSupport::removeFullscreen( QWidget& window ) const {
if ( ! isFullscreen(window) )
return;
window.showNormal();
}

bool DesktopSupport::isFullscreen( QWidget& window ) const {
return window.isFullScreen();
}
155 changes: 155 additions & 0 deletions desktopsupport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#pragma once

#include <memory>
#include <vector>
#include <string>
#include <QWidget>

#include "windowrole.h"

enum class DesktopEnvironmentHandlerQuality {
NotMyEnvironment = 0,
GenericHandler,
OperatingSystemSpecificHandler,
DesktopEnvironmentSpecificHandler
};

/** Represents one "output",
* meaning a physical screen connected to the machine
*
* Exact type will be dependent on the handler that created it.
*/
struct OutputHandle {
/** Get a human-readable name of the output */
virtual std::string const name() const =0;

/** Is this output marked as "primary" ? */
virtual bool isPrimary() const =0;

/** Polymorphic class */
virtual ~OutputHandle() { }
};
typedef std::unique_ptr<OutputHandle> OutputPtr;
typedef std::vector<OutputPtr> OutputList;

enum class DesktopSupportErrorHandling {
ThrowOnError,
TryToIgnoreError
};

/** Abstract base class for desktop support */
class DesktopSupport {
public:
/** Check handler quality
*
* This either outputs NotMyEnvironment,
* or the quality of the handler
*
* High quality means it is perfectly suited
* for the current execution environment.
*
*/
virtual DesktopEnvironmentHandlerQuality quality() const =0;

/** Output the DesktopSupport's name
*
* Human-readable, but must be unique across implementations.
* */
virtual std::string const name() const =0;

/** Get all outputs on the machine
*
* This needs to be implemented by inheriting classes
* */
virtual OutputList getOutputs() const =0;

/** Get Primary output
*
* can throw CannotDeterminePrimaryOutput
* if there is more than one screen and
* none of them is marked primary
*
* If there is more than one "primary" screen,
* it will output the numerically first of them.
*
* If errors are ignored, will pick the numerically
* first screen returned from the environment.
*/
OutputPtr getPrimary(
const DesktopSupportErrorHandling& errorMode=
DesktopSupportErrorHandling::ThrowOnError
)
const;

/** Get secondary screen
*
* can throw OnlyOneOutput if there is only
* one output
*
* can throw CannotDeterminePrimaryOutput
* if no screeen is marked Primary
*
* can throw TooManyScreens if there is three
* or more screens
*
* If errors are ignored, will pick the numerically
* second one when there is no primary.
*
* If there is a primary, will pick the numerically
* first non-primary.
*
* The exact screen chosen depends on the environment
* and is probably random.
*/
OutputPtr getSecondary(
const DesktopSupportErrorHandling& errorMode=
DesktopSupportErrorHandling::ThrowOnError
)
const;

/** Move a window to a specified output
*
* Can throw FailedToMoveToOutput if the desktop environment
* signaled an error (this is likely fatal)
*/
virtual void moveWindow(QWidget& window, OutputHandle& to)
const =0;

/** Get target output for a specific window role */
OutputPtr getTargetOutput(
const WindowRole& windowRole,
const DesktopSupportErrorHandling& errorMode=
DesktopSupportErrorHandling::ThrowOnError
) const;

/** Make the window fullscreen.
*
* Must not make an already-fullscreened window
* "normal" again.
*
* If the desktop does not allow detection of fullscreen
* state, unconditional un-full-screening and re-full-screening
* is acceptable as a last resort.
*
* The default implementation simply calls QWidget::showFullscreen()
*/
virtual void makeFullscreen(QWidget& window) const;

/** Make the window non-fullscreen.
*
* Must not make an already normal window fullscreen.
*
* The default implementation simply calls QWidget::showNormal().
*/
virtual void removeFullscreen(QWidget& window) const;

/** Can this desktop environment move fullscreen windows?
*/
virtual bool canMoveWindowWhileFullscreen() const =0;

/* Is this window fullscreen? */
virtual bool isFullscreen(QWidget& window) const;

/** This is a base class, make destructor virtual */
virtual ~DesktopSupport() { }
};
39 changes: 39 additions & 0 deletions desktopsupport/generic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "generic.h"

#include <QDesktopWidget>
#include <sstream>

using namespace std;

namespace {
ostream& operator << (ostream& o, const QRect& rect) {
return o << rect.width() << "x" << rect.height() <<
"@" << rect.left() << "," << rect.top();
}
}

string const GenericOutputHandle::name() const {
ostringstream os;
os << "GenericOutputHandle - rect " << screenRect;
return os.str();
}


OutputList GenericDesktopSupport::getOutputs() const {
OutputList vec;
QDesktopWidget* desk = QApplication::desktop();
for( int i=0 ; i < desk->screenCount() ; ++i ) {
OutputPtr p{ new GenericOutputHandle{
desk->screenGeometry( i ),
i == desk->primaryScreen()
}};
vec.push_back( move(p) );
}
return vec;
}

void GenericDesktopSupport::moveWindow(QWidget& window, OutputHandle& outhand) const {
GenericOutputHandle& out = dynamic_cast<GenericOutputHandle&>(outhand);
window.move( out.screenRect.topLeft() );
window.resize( out.screenRect.size() );
}
43 changes: 43 additions & 0 deletions desktopsupport/generic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include "../desktopsupport.h"

#include <QApplication>
#include <QRect>

/** On the Generic Handler, an "output handle"
* is just a rectangular place on the output
*/
struct GenericOutputHandle: public OutputHandle {
QRect screenRect;
bool primary;

inline bool isPrimary() const override{
return primary;
}

GenericOutputHandle(const QRect& rect, bool b):
screenRect(rect), primary(b) {
}

const std::string name() const override;
};

class GenericDesktopSupport: public DesktopSupport {

DesktopEnvironmentHandlerQuality quality() const override {
return DesktopEnvironmentHandlerQuality::GenericHandler;
}

std::string const name() const override {
return "Generic Qt4/5 desktop support handler";
}

OutputList getOutputs() const override;

void moveWindow(QWidget&, OutputHandle&) const override;

bool canMoveWindowWhileFullscreen() const override {
return true;
}
};
Loading