PageInput.cpp (ssr-0.4.0) | : | PageInput.cpp (ssr-0.4.1) | ||
---|---|---|---|---|
skipping to change at line 74 | skipping to change at line 74 | |||
static QRect CombineScreenGeometries(const std::vector<QRect>& screen_geometries ) { | static QRect CombineScreenGeometries(const std::vector<QRect>& screen_geometries ) { | |||
QRect combined_geometry; | QRect combined_geometry; | |||
for(const QRect &geometry : screen_geometries) { | for(const QRect &geometry : screen_geometries) { | |||
combined_geometry |= geometry; | combined_geometry |= geometry; | |||
} | } | |||
return combined_geometry; | return combined_geometry; | |||
} | } | |||
static QPoint GetMousePhysicalCoordinates() { | static QPoint GetMousePhysicalCoordinates() { | |||
Window root, child; | if(IsPlatformX11()) { | |||
int root_x, root_y; | Window root, child; | |||
int win_x, win_y; | int root_x, root_y; | |||
unsigned int mask_return; | int win_x, win_y; | |||
XQueryPointer(QX11Info::display(), QX11Info::appRootWindow(), &root, &chi | unsigned int mask_return; | |||
ld, &root_x, &root_y, &win_x, &win_y, &mask_return); | XQueryPointer(QX11Info::display(), QX11Info::appRootWindow(), &ro | |||
return QPoint(root_x, root_y); | ot, &child, &root_x, &root_y, &win_x, &win_y, &mask_return); | |||
return QPoint(root_x, root_y); | ||||
} else { | ||||
return QPoint(0, 0); // TODO: implement for wayland | ||||
} | ||||
} | } | |||
static QRect MapToLogicalCoordinates(const QRect& rect) { | static QRect MapToLogicalCoordinates(const QRect& rect) { | |||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | |||
for(QScreen *screen : QApplication::screens()) { | for(QScreen *screen : QApplication::screens()) { | |||
QRect geometry = screen->geometry(); | QRect geometry = screen->geometry(); | |||
qreal ratio = screen->devicePixelRatio(); | qreal ratio = screen->devicePixelRatio(); | |||
QRect physical_geometry(geometry.x(), geometry.y(), lrint((qreal) geometry.width() * ratio), lrint((qreal) geometry.height() * ratio)); | QRect physical_geometry(geometry.x(), geometry.y(), lrint((qreal) geometry.width() * ratio), lrint((qreal) geometry.height() * ratio)); | |||
if(physical_geometry.contains(rect.center())) { | if(physical_geometry.contains(rect.center())) { | |||
return QRect( | return QRect( | |||
skipping to change at line 152 | skipping to change at line 156 | |||
#else | #else | |||
#define TRANSPARENT_WINDOW_FLAGS (Qt::Window | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | \ | #define TRANSPARENT_WINDOW_FLAGS (Qt::Window | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | \ | |||
Qt::WindowStaysOnTopHint) | Qt::WindowStaysOnTopHint) | |||
// Replacement for Qt::WindowTransparentForInput based on X11 'shape' extension as described here: | // Replacement for Qt::WindowTransparentForInput based on X11 'shape' extension as described here: | |||
// http://shallowsky.com/blog/programming/translucent-window-click-thru.html | // http://shallowsky.com/blog/programming/translucent-window-click-thru.html | |||
#define TRANSPARENT_WINDOW_ATTRIBUTES() {\ | #define TRANSPARENT_WINDOW_ATTRIBUTES() {\ | |||
setAttribute(Qt::WA_X11DoNotAcceptFocus); \ | setAttribute(Qt::WA_X11DoNotAcceptFocus); \ | |||
int shape_event_base, shape_error_base; \ | int shape_event_base, shape_error_base; \ | |||
if(XShapeQueryExtension(QX11Info::display(), &shape_event_base, &shape_er | if(IsPlatformX11()) { \ | |||
ror_base)) { \ | if(XShapeQueryExtension(QX11Info::display(), &shape_event_base, & | |||
Region region = XCreateRegion(); \ | shape_error_base)) { \ | |||
XShapeCombineRegion(QX11Info::display(), winId(), ShapeInput, 0, | Region region = XCreateRegion(); \ | |||
0, region, ShapeSet); \ | XShapeCombineRegion(QX11Info::display(), winId(), ShapeIn | |||
XDestroyRegion(region); \ | put, 0, 0, region, ShapeSet); \ | |||
XDestroyRegion(region); \ | ||||
} \ | ||||
} \ | } \ | |||
} | } | |||
#endif | #endif | |||
ScreenLabelWindow::ScreenLabelWindow(QWidget* parent, const QString &text) | ScreenLabelWindow::ScreenLabelWindow(QWidget* parent, const QString &text) | |||
: QWidget(parent, TRANSPARENT_WINDOW_FLAGS) { | : QWidget(parent, TRANSPARENT_WINDOW_FLAGS) { | |||
TRANSPARENT_WINDOW_ATTRIBUTES(); | TRANSPARENT_WINDOW_ATTRIBUTES(); | |||
m_text = text; | m_text = text; | |||
m_font = QFont("Sans", 18, QFont::Bold); | m_font = QFont("Sans", 18, QFont::Bold); | |||
skipping to change at line 653 | skipping to change at line 659 | |||
settings->setValue("input/glinject_channel", GetGLInjectChannel()); | settings->setValue("input/glinject_channel", GetGLInjectChannel()); | |||
settings->setValue("input/glinject_relax_permissions", GetGLInjectRelaxPe rmissions()); | settings->setValue("input/glinject_relax_permissions", GetGLInjectRelaxPe rmissions()); | |||
settings->setValue("input/glinject_command", GetGLInjectCommand()); | settings->setValue("input/glinject_command", GetGLInjectCommand()); | |||
settings->setValue("input/glinject_working_directory", GetGLInjectWorking Directory()); | settings->setValue("input/glinject_working_directory", GetGLInjectWorking Directory()); | |||
settings->setValue("input/glinject_auto_launch", GetGLInjectAutoLaunch()) ; | settings->setValue("input/glinject_auto_launch", GetGLInjectAutoLaunch()) ; | |||
settings->setValue("input/glinject_limit_fps", GetGLInjectLimitFPS()); | settings->setValue("input/glinject_limit_fps", GetGLInjectLimitFPS()); | |||
#endif | #endif | |||
} | } | |||
bool PageInput::Validate() { | bool PageInput::Validate() { | |||
if(m_grabbing || m_selecting_window) | if(m_grabbing) | |||
return false; | return false; | |||
return true; | return true; | |||
} | } | |||
#if SSR_USE_ALSA | #if SSR_USE_ALSA | |||
QString PageInput::GetALSASourceName() { | QString PageInput::GetALSASourceName() { | |||
return QString::fromStdString(m_alsa_sources[GetALSASource()].m_name); | return QString::fromStdString(m_alsa_sources[GetALSASource()].m_name); | |||
} | } | |||
#endif | #endif | |||
skipping to change at line 736 | skipping to change at line 742 | |||
if(childs != NULL) | if(childs != NULL) | |||
XFree(childs); | XFree(childs); | |||
return real_window; | return real_window; | |||
} | } | |||
void PageInput::mousePressEvent(QMouseEvent* event) { | void PageInput::mousePressEvent(QMouseEvent* event) { | |||
if(m_grabbing) { | if(m_grabbing) { | |||
if(event->button() == Qt::LeftButton) { | if(event->button() == Qt::LeftButton) { | |||
QPoint mouse_physical = GetMousePhysicalCoordinates(); | if(IsPlatformX11()) { | |||
if(m_selecting_window) { | QPoint mouse_physical = GetMousePhysicalCoordinat | |||
// As expected, Qt does not provide any functions | es(); | |||
to find the window at a specific position, so I have to use Xlib directly. | if(m_selecting_window) { | |||
// I'm not completely sure whether this is the be | // As expected, Qt does not provide any f | |||
st way to do this, but it appears to work. XQueryPointer returns the window | unctions to find the window at a specific position, so I have to use Xlib direct | |||
// currently below the mouse along with the mouse | ly. | |||
position, but apparently this may not work correctly when the mouse pointer | // I'm not completely sure whether this i | |||
// is also grabbed (even though it works fine in | s the best way to do this, but it appears to work. XQueryPointer returns the win | |||
my test), so I use XTranslateCoordinates instead. Originally I wanted to | dow | |||
// show the rubber band when the mouse hovers ove | // currently below the mouse along with t | |||
r a window (instead of having to click it), but this doesn't work correctly | he mouse position, but apparently this may not work correctly when the mouse poi | |||
// since X will simply return a handle the rubber | nter | |||
band itself (even though it should be transparent to mouse events). | // is also grabbed (even though it works | |||
Window selected_window; | fine in my test), so I use XTranslateCoordinates instead. Originally I wanted to | |||
int x, y; | // show the rubber band when the mouse ho | |||
if(XTranslateCoordinates(QX11Info::display(), QX1 | vers over a window (instead of having to click it), but this doesn't work correc | |||
1Info::appRootWindow(), QX11Info::appRootWindow(), mouse_physical.x(), mouse_phy | tly | |||
sical.y(), &x, &y, &selected_window)) { | // since X will simply return a handle th | |||
XWindowAttributes attributes; | e rubber band itself (even though it should be transparent to mouse events). | |||
if(selected_window != None && XGetWindowA | Window selected_window; | |||
ttributes(QX11Info::display(), selected_window, &attributes)) { | int x, y; | |||
if(XTranslateCoordinates(QX11Info::displa | ||||
// naive outer/inner rectangle, t | y(), QX11Info::appRootWindow(), QX11Info::appRootWindow(), mouse_physical.x(), m | |||
his won't work for window decorations | ouse_physical.y(), &x, &y, &selected_window)) { | |||
m_select_window_outer_rect = QRec | XWindowAttributes attributes; | |||
t(attributes.x, attributes.y, attributes.width + 2 * attributes.border_width, at | if(selected_window != None && XGe | |||
tributes.height + 2 * attributes.border_width); | tWindowAttributes(QX11Info::display(), selected_window, &attributes)) { | |||
m_select_window_inner_rect = QRec | ||||
t(attributes.x + attributes.border_width, attributes.y + attributes.border_width | // naive outer/inner rect | |||
, attributes.width, attributes.height); | angle, this won't work for window decorations | |||
m_select_window_outer_rec | ||||
// try to find the real window (r | t = QRect(attributes.x, attributes.y, attributes.width + 2 * attributes.border_w | |||
ather than the decorations added by the window manager) | idth, attributes.height + 2 * attributes.border_width); | |||
Window real_window = X11FindRealW | m_select_window_inner_rec | |||
indow(QX11Info::display(), selected_window); | t = QRect(attributes.x + attributes.border_width, attributes.y + attributes.bord | |||
if(real_window != None) { | er_width, attributes.width, attributes.height); | |||
Atom actual_type; | ||||
int actual_format; | // try to find the real w | |||
unsigned long items, byte | indow (rather than the decorations added by the window manager) | |||
s_left; | Window real_window = X11F | |||
long *data = NULL; | indRealWindow(QX11Info::display(), selected_window); | |||
int result = XGetWindowPr | if(real_window != None) { | |||
operty(QX11Info::display(), real_window, XInternAtom(QX11Info::display(), "_NET_ | Atom actual_type; | |||
FRAME_EXTENTS", true), | int actual_format | |||
; | ||||
0, 4, false, AnyPropertyType, &actual_typ | unsigned long ite | |||
e, &actual_format, &items, &bytes_left, (unsigned char**) &data); | ms, bytes_left; | |||
if(result == Success) { | long *data = NULL | |||
if(items == 4 && | ; | |||
bytes_left == 0 && actual_format == 32) { // format 32 means 'long', even if lon | int result = XGet | |||
g is 64-bit ... | WindowProperty(QX11Info::display(), real_window, XInternAtom(QX11Info::display() | |||
Window ch | , "_NET_FRAME_EXTENTS", true), | |||
ild; | ||||
// the at | 0, 4, false, AnyPropertyType, &ac | |||
tributes of the real window only store the *relative* position which is not what | tual_type, &actual_format, &items, &bytes_left, (unsigned char**) &data); | |||
we need, so use XTranslateCoordinates again | if(result == Succ | |||
if(XTrans | ess) { | |||
lateCoordinates(QX11Info::display(), real_window, QX11Info::appRootWindow(), 0, | if(items | |||
0, &x, &y, &child) | == 4 && bytes_left == 0 && actual_format == 32) { // format 32 means 'long', eve | |||
n if long is 64-bit ... | ||||
&& XGetWindowAttributes(QX11Info::display(), real_window, &attributes)) | W | |||
{ | indow child; | |||
/ | ||||
/ | / the attributes of the real window only store the *relative* position which is | |||
/ finally! | not what we need, so use XTranslateCoordinates again | |||
m | i | |||
_select_window_inner_rect = QRect(x, y, attributes.width, attributes.height); | f(XTranslateCoordinates(QX11Info::display(), real_window, QX11Info::appRootWindo | |||
m | w(), 0, 0, &x, &y, &child) | |||
_select_window_outer_rect = m_select_window_inner_rect.adjusted(-data[0], -data[ | ||||
2], data[1], data[3]); | && XGetWindowAttributes(QX11Info::display(), real_window, &attri | |||
butes)) { | ||||
// finally! | ||||
m_select_window_inner_rect = QRect(x, y, attributes.width, attributes.hei | ||||
ght); | ||||
m_select_window_outer_rect = m_select_window_inner_rect.adjusted(-data[0] | ||||
, -data[2], data[1], data[3]); | ||||
} else { | } else { | |||
/ | ||||
/ I doubt this will ever be needed, but do it anyway | // I doubt this will ever be needed, but do it anyway | |||
m | ||||
_select_window_inner_rect = m_select_window_outer_rect.adjusted(data[0], data[2] | m_select_window_inner_rect = m_select_window_outer_rect.adjusted(data[0], | |||
, -data[1], -data[3]); | data[2], -data[1], -data[3]); | |||
} | ||||
} | } | |||
} | } | |||
if(data != NULL) | ||||
XFree(dat | ||||
a); | ||||
} | } | |||
if(data != NULL) | ||||
XFree(data); | ||||
} | ||||
// pick the inner rectangle if th | // pick the inner rectang | |||
e users clicks inside the window, or the outer rectangle otherwise | le if the users clicks inside the window, or the outer rectangle otherwise | |||
m_rubber_band_rect = (m_select_wi | m_rubber_band_rect = (m_s | |||
ndow_inner_rect.contains(mouse_physical))? m_select_window_inner_rect : m_select | elect_window_inner_rect.contains(mouse_physical))? m_select_window_inner_rect : | |||
_window_outer_rect; | m_select_window_outer_rect; | |||
UpdateRubberBand(); | UpdateRubberBand(); | |||
} | ||||
} | } | |||
} else { | ||||
m_rubber_band_rect = QRect(mouse_physical | ||||
, mouse_physical); | ||||
UpdateRubberBand(); | ||||
} | } | |||
} else { | ||||
m_rubber_band_rect = QRect(mouse_physical, mouse_ | ||||
physical); | ||||
UpdateRubberBand(); | ||||
} | } | |||
} else { | } else { | |||
StopGrabbing(); | StopGrabbing(); | |||
} | } | |||
event->accept(); | event->accept(); | |||
return; | return; | |||
} | } | |||
event->ignore(); | event->ignore(); | |||
} | } | |||
skipping to change at line 821 | skipping to change at line 829 | |||
} | } | |||
StopGrabbing(); | StopGrabbing(); | |||
event->accept(); | event->accept(); | |||
return; | return; | |||
} | } | |||
event->ignore(); | event->ignore(); | |||
} | } | |||
void PageInput::mouseMoveEvent(QMouseEvent* event) { | void PageInput::mouseMoveEvent(QMouseEvent* event) { | |||
if(m_grabbing) { | if(m_grabbing) { | |||
if(m_rubber_band != NULL) { | if(m_rubber_band != NULL && IsPlatformX11()) { | |||
QPoint mouse_physical = GetMousePhysicalCoordinates(); | QPoint mouse_physical = GetMousePhysicalCoordinates(); | |||
if(m_selecting_window) { | if(m_selecting_window) { | |||
// pick the inner rectangle if the user clicks in side the window, or the outer rectangle otherwise | // pick the inner rectangle if the user clicks in side the window, or the outer rectangle otherwise | |||
m_rubber_band_rect = (m_select_window_inner_rect. contains(mouse_physical))? m_select_window_inner_rect : m_select_window_outer_re ct; | m_rubber_band_rect = (m_select_window_inner_rect. contains(mouse_physical))? m_select_window_inner_rect : m_select_window_outer_re ct; | |||
} else { | } else { | |||
m_rubber_band_rect.setBottomRight(mouse_physical) ; | m_rubber_band_rect.setBottomRight(mouse_physical) ; | |||
} | } | |||
UpdateRubberBand(); | UpdateRubberBand(); | |||
} | } | |||
event->accept(); | event->accept(); | |||
End of changes. 14 change blocks. | ||||
105 lines changed or deleted | 123 lines changed or added |