diff options
Diffstat (limited to 'src-qt5/src-cpp/obsolete')
-rw-r--r-- | src-qt5/src-cpp/obsolete/NativeEmbedWidget.cpp | 423 | ||||
-rw-r--r-- | src-qt5/src-cpp/obsolete/NativeEmbedWidget.h | 74 | ||||
-rw-r--r-- | src-qt5/src-cpp/obsolete/NativeWindow.cpp | 123 | ||||
-rw-r--r-- | src-qt5/src-cpp/obsolete/NativeWindow.h | 118 | ||||
-rw-r--r-- | src-qt5/src-cpp/obsolete/NativeWindow.pri | 13 |
5 files changed, 751 insertions, 0 deletions
diff --git a/src-qt5/src-cpp/obsolete/NativeEmbedWidget.cpp b/src-qt5/src-cpp/obsolete/NativeEmbedWidget.cpp new file mode 100644 index 00000000..57b6edde --- /dev/null +++ b/src-qt5/src-cpp/obsolete/NativeEmbedWidget.cpp @@ -0,0 +1,423 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "NativeEmbedWidget.h" + +#include <QPainter> +#include <QX11Info> +#include <QApplication> +#include <QScreen> +#include <QDebug> + +#include <xcb/xproto.h> +#include <xcb/xcb_aux.h> +#include <xcb/xcb_event.h> +#include <xcb/xcb_image.h> +//#include <xcb/render.h> +//#include <xcb/xcb_renderutil.h> +#include <xcb/composite.h> +#include <X11/extensions/Xdamage.h> + +#define DISABLE_COMPOSITING true + +/*inline xcb_render_pictformat_t get_pictformat(){ + static xcb_render_pictformat_t format = 0; + if(format==0){ + xcb_render_query_pict_formats_reply_t *reply = xcb_render_query_pict_formats_reply( QX11Info::connection(), xcb_render_query_pict_formats(QX11Info::connection()), NULL); + format = xcb_render_util_find_standard_format(reply, XCB_PICT_STANDARD_ARGB_32)->id; + free(reply); + } + return format; +} + + +inline void renderWindowToWidget(WId id, QWidget *widget, bool hastransparency = true){ + //window and widget are assumed to be the same size + //Pull the XCB pixmap out of the compositing layer + xcb_pixmap_t pix = xcb_generate_id(QX11Info::connection()); + xcb_composite_name_window_pixmap(QX11Info::connection(), WIN->id(), pix); + if(pix==0){ qDebug() << "Got blank pixmap!"; return; } + + xcb_render_picture_t pic_id = xcb_generate_id(QX11Info::connection()); + xcb_render_create_picture_aux(QX11Info::connection(), pic_id, pix, get_pictformat() , 0, NULL); + // + xcb_render_composite(QX11Info::connection(), hastransparency ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC, pic_id, XCB_RENDER_PICTURE_NONE, widget->x11RenderHandle(), + 0, 0, 0, 0, 0, 0, (uint16_t) widget->width(), (uint16_t) widget->height() ); +}*/ + +#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_FOCUS_CHANGE | \ + XCB_EVENT_MASK_POINTER_MOTION) + +#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_BUTTON_RELEASE | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_EXPOSURE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_ENTER_WINDOW) + +inline void registerClientEvents(WId id, bool client = true){ + uint32_t values[] = {XCB_NONE}; + values[0] = client ? CLIENT_EVENT_MASK : FRAME_EVENT_MASK ; + /*{ (XCB_EVENT_MASK_PROPERTY_CHANGE + | XCB_EVENT_MASK_BUTTON_PRESS + | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_POINTER_MOTION + | XCB_EVENT_MASK_BUTTON_MOTION + | XCB_EVENT_MASK_EXPOSURE + | XCB_EVENT_MASK_STRUCTURE_NOTIFY + | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT + | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY + | XCB_EVENT_MASK_ENTER_WINDOW) + };*/ + xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, values); +} + +// ============ +// PRIVATE +// ============ +//Simplification functions for the XCB/XLib interactions +void NativeEmbedWidget::syncWinSize(QSize sz){ + if(WIN==0){ return; } + else if(!sz.isValid()){ sz = this->size(); } //use the current widget size + //qDebug() << "Sync Window Size:" << sz; + //if(sz == winSize){ return; } //no change + QPoint pt(0,0); + if(!DISABLE_COMPOSITING){ pt = this->mapToGlobal(QPoint(0,0)); } + const uint32_t valList[4] = {(uint32_t) pt.x(), (uint32_t) pt.y(), (uint32_t) sz.width(), (uint32_t) sz.height()}; + const uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; + xcb_configure_window(QX11Info::connection(), WIN->id(), mask, valList); + winSize = sz; //save this for checking later +} + +void NativeEmbedWidget::syncWidgetSize(QSize sz){ + //qDebug() << "Sync Widget Size:" << sz; + this->resize(sz); +} + +void NativeEmbedWidget::hideWindow(){ + //qDebug() << "Hide Embed Window"; + xcb_unmap_window(QX11Info::connection(), WIN->id()); +} + +void NativeEmbedWidget::showWindow(){ + //qDebug() << "Show Embed Window"; + xcb_map_window(QX11Info::connection(), WIN->id()); + reregisterEvents(); + if(!DISABLE_COMPOSITING){ + QTimer::singleShot(0,this, SLOT(repaintWindow())); + } +} + +QImage NativeEmbedWidget::windowImage(QRect geom){ + //if(DISABLE_COMPOSITING){ + if(!this->isVisible()){ return QImage(); } //nothing to grab yet + QList<QScreen*> screens = static_cast<QApplication*>( QApplication::instance() )->screens(); + //for(int i=0; i<screens.length(); i++){ + //if(screens[i]->contains(this)){ + if(!screens.isEmpty()){ + return screens[0]->grabWindow(WIN->id(), geom.x(), geom.y(), geom.width(), geom.height()).toImage(); + } + //} + //} + return QImage(); + /*}else{ + //Pull the XCB pixmap out of the compositing layer + xcb_pixmap_t pix = xcb_generate_id(QX11Info::connection()); + xcb_composite_name_window_pixmap(QX11Info::connection(), WIN->id(), pix); + if(pix==0){ qDebug() << "Got blank pixmap!"; return QImage(); } + + //Convert this pixmap into a QImage + //xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, 0, 0, this->width(), this->height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP); + xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, geom.x(), geom.y(), geom.width(), geom.height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP); + if(ximg == 0){ qDebug() << "Got blank image!"; return QImage(); } + QImage img(ximg->data, ximg->width, ximg->height, ximg->stride, QImage::Format_ARGB32_Premultiplied); + img = img.copy(); //detach this image from the XCB data structures before we clean them up, otherwise the QImage will try to clean it up a second time on window close and crash + xcb_image_destroy(ximg); + + //Cleanup the XCB data structures + xcb_free_pixmap(QX11Info::connection(), pix); + + return img; + }*/ +} +void NativeEmbedWidget::setWinUnpaused(){ + paused = false; + winImage = QImage(); + if(!DISABLE_COMPOSITING){ + repaintWindow(); //update the cached image right away + }else if(this->isVisible()){ + showWindow(); + } + resyncWindow(); //make sure the window knows about the new location +} +// ============ +// PUBLIC +// ============ +NativeEmbedWidget::NativeEmbedWidget(QWidget *parent) : QWidget(parent){ + WIN = 0; //nothing embedded yet + paused = false; + this->setMouseTracking(true); + //this->setSizeIncrement(2,2); +} + +bool NativeEmbedWidget::embedWindow(NativeWindow *window){ + WIN = window; + + //Now send the embed event to the app + //qDebug() << " - send _XEMBED event"; + /*xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = WIN->id(); + event.type = obj->ATOMS["_XEMBED"]; //_XEMBED + event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY + event.data.data32[2] = 0; + event.data.data32[3] = this->winId(); //WID of the container + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + */ + //Now setup any redirects and return + if(!DISABLE_COMPOSITING){ + xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); + xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //AUTOMATIC); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); + + //Now create/register the damage handler + // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore) + // -- Retested 6/29/17 (no change) Ken Moore + //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer + //xcb_damage_create(QX11Info::connection(), dmgID, WIN->id(), XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); + // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself). + Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); + + WIN->addDamageID( (uint) dmgID); //save this for later + connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change + }else{ + xcb_reparent_window(QX11Info::connection(), WIN->id(), this->winId(), 0, 0); + registerClientEvents(this->winId()); //child events get forwarded through the frame - watch this for changes too + //Also use a partial-composite here - make sure the window pixmap is available even when the window is obscured + xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_AUTOMATIC); + //xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); + //Also alert us when the window visual changes + Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); + + WIN->addDamageID( (uint) dmgID); //save this for later + connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change + } + WIN->addFrameWinID(this->winId()); + registerClientEvents(WIN->id()); + //qDebug() << "Events Registered:" << WIN->id() << this->winId(); + return true; +} + +bool NativeEmbedWidget::detachWindow(){ + xcb_reparent_window(QX11Info::connection(), WIN->id(), QX11Info::appRootWindow(), -1, -1); + //WIN = 0; + return true; +} + +bool NativeEmbedWidget::isEmbedded(){ + return (WIN!=0); +} + +void NativeEmbedWidget::raiseWindow(){ + if(DISABLE_COMPOSITING){ return; } + uint32_t val = XCB_STACK_MODE_ABOVE; + xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); +} + +void NativeEmbedWidget::lowerWindow(){ + if(DISABLE_COMPOSITING){ return; } + uint32_t val = XCB_STACK_MODE_BELOW; + xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); +} + +// ============== +// PUBLIC SLOTS +// ============== +//Pause/resume +void NativeEmbedWidget::pause(){ + if(DISABLE_COMPOSITING){ + winImage = windowImage(QRect(QPoint(0,0), this->size())); + hideWindow(); + }else{ + if(winImage.isNull()){ repaintWindow(); } //make sure we have one image already cached first + } + paused = true; +} + +void NativeEmbedWidget::resume(){ + //paused = false; + syncWinSize(); + if(DISABLE_COMPOSITING){ + //showWindow(); + }else{ + repaintWindow(); //update the cached image right away + } + QTimer::singleShot(10, this, SLOT(setWinUnpaused()) ); +} + +void NativeEmbedWidget::resyncWindow(){ + if(WIN==0){ return; } + //syncWinSize(); + //if(DISABLE_COMPOSITING){ + // Specs say to send an artificial configure event to the window if the window was reparented into the frame + QPoint loc = this->mapToGlobal( QPoint(0,0) ); + //Send an artificial configureNotify event to the window with the global position/size included + xcb_configure_notify_event_t *event = (xcb_configure_notify_event_t*) calloc(32,1); //always 32-byes long, even if we don't need all of it + event->x = loc.x(); + event->y = loc.y(); + event->width = this->width(); + event->height = this->height(); + event->border_width = 0; + event->above_sibling = XCB_NONE; + event->override_redirect = false; + event->window = WIN->id(); + event->event = WIN->id(); + event->response_type = XCB_CONFIGURE_NOTIFY; + xcb_send_event(QX11Info::connection(), false, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, (char *) event); + xcb_flush(QX11Info::connection()); + free(event); + /*}else{ + //Window is floating invisibly - make sure it is in the right place + //Make sure the window size is syncronized and visual up to date + //syncWinSize(); + QTimer::singleShot(10, this, SLOT(repaintWindow()) ); + }*/ + +} + +void NativeEmbedWidget::repaintWindow(){ + //if(DISABLE_COMPOSITING){ return; } + //qDebug() << "Update Window Image:" << !paused; + if(paused){ return; } + /*QImage tmp = windowImage( QRect(QPoint(0,0), this->size()) ); + if(!tmp.isNull()){ + winImage = tmp; + }else{ qDebug() << "Got Null Image!!"; }*/ + this->parentWidget()->update(); //visual changed - need to update the image on the widget +} + +void NativeEmbedWidget::reregisterEvents(){ + if(WIN!=0){ registerClientEvents(WIN->id()); } +} + +// ============== +// PROTECTED +// ============== +void NativeEmbedWidget::resizeEvent(QResizeEvent *ev){ + QWidget::resizeEvent(ev); + if(WIN!=0 && !paused){ + syncWinSize(ev->size()); + } //syncronize the window with the new widget size +} + +void NativeEmbedWidget::showEvent(QShowEvent *ev){ + if(WIN!=0){ showWindow(); } + QWidget::showEvent(ev); +} + +void NativeEmbedWidget::hideEvent(QHideEvent *ev){ + if(WIN!=0){ hideWindow(); } + QWidget::hideEvent(ev); +} + +void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ + QPainter P(this); + P.setClipping(true); + P.setClipRect(0,0,this->width(), this->height()); + P.fillRect(ev->rect(), Qt::transparent); + if(WIN==0){ return; } + QRect geom = ev->rect(); //atomic updates + //qDebug() << "Paint Rect:" << geom; + QImage img; + if(!paused){ img = windowImage(geom); } + else if(!winImage.isNull()){ + if(winImage.size() == this->size()){ img = winImage.copy(geom); } + else{ img = winImage.scaled(geom.size()); } //this is a fast transformation - might be slightly distorted + } + //Need to paint the image from the window onto the widget as an overlay + P.drawImage( geom , img, QRect(QPoint(0,0), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping + + +} + +void NativeEmbedWidget::enterEvent(QEvent *ev){ + QWidget::enterEvent(ev); + //qDebug() << "Enter Embed Widget"; + //raiseWindow(); //this->grabMouse(); +} + +void NativeEmbedWidget::leaveEvent(QEvent *ev){ + QWidget::leaveEvent(ev); + /*qDebug() << "Leave Embed Widget"; + QPoint pt = QCursor::pos(); + QPoint relpt = this->parentWidget()->mapFromGlobal(pt); + qDebug() << " - Geom:" << this->geometry() << "Global pt:" << pt << "Relative pt:" << relpt; + if(!this->geometry().contains(relpt) ){ lowerWindow(); }*/ +} + +void NativeEmbedWidget::mouseMoveEvent(QMouseEvent *ev){ + QWidget::mouseMoveEvent(ev); + //Forward this event on to the window +} + +void NativeEmbedWidget::mousePressEvent(QMouseEvent *ev){ + QWidget::mousePressEvent(ev); + //Forward this event on to the window +} + +void NativeEmbedWidget::mouseReleaseEvent(QMouseEvent *ev){ + QWidget::mouseReleaseEvent(ev); + //Forward this event on to the window +} + +/*bool NativeEmbedWidget::nativeEvent(const QByteArray &eventType, void *message, long *result){ + if(eventType=="xcb_generic_event_t" && WIN!=0){ + //Convert to known event type (for X11 systems) + xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message); + //qDebug() << "Got Embed Window Event:" << xcb_event_get_label(ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) << xcb_event_get_request_label(ev->response_type); + uint32_t mask = 0; + switch( ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK){ + case XCB_BUTTON_PRESS: + //This is a mouse button press + mask = XCB_EVENT_MASK_BUTTON_PRESS; + break; + case XCB_BUTTON_RELEASE: + //This is a mouse button release + //qDebug() << "Button Release Event"; + mask = XCB_EVENT_MASK_BUTTON_RELEASE; + break; + case XCB_MOTION_NOTIFY: + //This is a mouse movement event + mask = XCB_EVENT_MASK_POINTER_MOTION; + break; + case XCB_ENTER_NOTIFY: + //This is a mouse movement event when mouse goes over a new window + mask = XCB_EVENT_MASK_ENTER_WINDOW; + break; + case XCB_LEAVE_NOTIFY: + //This is a mouse movement event when mouse goes leaves a window + mask = XCB_EVENT_MASK_LEAVE_WINDOW; + break; + default: + mask = 0; + } + + //Now forward this event on to the embedded window + if(mask!=0){ + qDebug() << " - Got a mouse event"; + xcb_send_event(QX11Info::connection(), true, WIN->id(),mask, (char*) ev); + return true; + } + } + return false; +}*/ diff --git a/src-qt5/src-cpp/obsolete/NativeEmbedWidget.h b/src-qt5/src-cpp/obsolete/NativeEmbedWidget.h new file mode 100644 index 00000000..16bb46dc --- /dev/null +++ b/src-qt5/src-cpp/obsolete/NativeEmbedWidget.h @@ -0,0 +1,74 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a container object for embedding a native window into a QWidget +// and maintaining a 1-to-1 mapping of sizing and other properties +// while also providing compositing effects between the two windows +//=========================================== +#ifndef _LUMINA_NATIVE_EMBED_WIDGET_H +#define _LUMINA_NATIVE_EMBED_WIDGET_H + +#include "NativeWindow.h" +#include <QWidget> +#include <QTimer> +#include <QResizeEvent> +#include <QShowEvent> +#include <QHideEvent> +#include <QPaintEvent> +#include <QMouseEvent> + +class NativeEmbedWidget : public QWidget{ + Q_OBJECT +private: + NativeWindow *WIN; + QSize winSize; + QImage winImage; + bool paused, hasAlphaChannel; + +private slots: + //Simplification functions + void syncWinSize(QSize sz = QSize()); + void syncWidgetSize(QSize sz); + void hideWindow(); + void showWindow(); + QImage windowImage(QRect geom); + + void setWinUnpaused(); + +public: + NativeEmbedWidget(QWidget *parent); + + bool embedWindow(NativeWindow *window); + bool detachWindow(); + bool isEmbedded(); //status of the embed + bool isPaused(){ return paused; } + +public slots: + void raiseWindow(); + void lowerWindow(); + + //Pause/resume + void pause(); + void resume(); + + void resyncWindow(); + void repaintWindow(); + void reregisterEvents(); + +protected: + void resizeEvent(QResizeEvent *ev); + void showEvent(QShowEvent *ev); + void hideEvent(QHideEvent *ev); + void paintEvent(QPaintEvent *ev); + void enterEvent(QEvent *ev); + void leaveEvent(QEvent *ev); + void mouseMoveEvent(QMouseEvent *ev); + void mousePressEvent(QMouseEvent *ev); + void mouseReleaseEvent(QMouseEvent *ev); + //bool nativeEvent(const QByteArray &eventType, void *message, long *result); +}; + +#endif diff --git a/src-qt5/src-cpp/obsolete/NativeWindow.cpp b/src-qt5/src-cpp/obsolete/NativeWindow.cpp new file mode 100644 index 00000000..02cc001e --- /dev/null +++ b/src-qt5/src-cpp/obsolete/NativeWindow.cpp @@ -0,0 +1,123 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "NativeWindow.h" + +#include <QDebug> + +// === PUBLIC === +NativeWindow::NativeWindow(WId id) : QObject(){ + winid = id; + frameid = 0; + dmgID = 0; +} + +NativeWindow::~NativeWindow(){ + hash.clear(); +} + +void NativeWindow::addFrameWinID(WId fid){ + frameid = fid; +} + +void NativeWindow::addDamageID(unsigned int dmg){ + dmgID = dmg; +} + +bool NativeWindow::isRelatedTo(WId tmp){ + return (relatedTo.contains(tmp) || winid == tmp || frameid == tmp); +} + +WId NativeWindow::id(){ + return winid; +} + +WId NativeWindow::frameId(){ + return frameid; +} + +unsigned int NativeWindow::damageId(){ + return dmgID; +} + +QVariant NativeWindow::property(NativeWindow::Property prop){ + if(hash.contains(prop)){ return hash.value(prop); } + else if(prop == NativeWindow::RelatedWindows){ return QVariant::fromValue(relatedTo); } + return QVariant(); //null variant +} + +void NativeWindow::setProperty(NativeWindow::Property prop, QVariant val, bool force){ + if(prop == NativeWindow::RelatedWindows){ relatedTo = val.value< QList<WId> >(); } + else if(prop == NativeWindow::None || (!force && hash.value(prop)==val)){ return; } + else{ hash.insert(prop, val); } + emit PropertiesChanged(QList<NativeWindow::Property>() << prop, QList<QVariant>() << val); +} + +void NativeWindow::setProperties(QList<NativeWindow::Property> props, QList<QVariant> vals, bool force){ + for(int i=0; i<props.length(); i++){ + if(i>=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property + if(props[i] == NativeWindow::None || (!force && (hash.value(props[i]) == vals[i])) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value + hash.insert(props[i], vals[i]); + } + emit PropertiesChanged(props, vals); +} + +void NativeWindow::requestProperty(NativeWindow::Property prop, QVariant val, bool force){ + if(prop == NativeWindow::None || prop == NativeWindow::RelatedWindows || (!force && hash.value(prop)==val) ){ return; } + emit RequestPropertiesChange(winid, QList<NativeWindow::Property>() << prop, QList<QVariant>() << val); +} + +void NativeWindow::requestProperties(QList<NativeWindow::Property> props, QList<QVariant> vals, bool force){ + //Verify/adjust inputs as needed + for(int i=0; i<props.length(); i++){ + if(i>=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property + if(props[i] == NativeWindow::None || props[i] == NativeWindow::RelatedWindows || (!force && hash.value(props[i])==vals[i]) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value + /*if( (props[i] == NativeWindow::Visible || props[i] == NativeWindow::Active) && frameid !=0){ + //These particular properties needs to change the frame - not the window itself + emit RequestPropertiesChange(frameid, QList<NativeWindow::Property>() << props[i], QList<QVariant>() << vals[i]); + props.removeAt(i); vals.removeAt(i); i--; + }*/ + } + emit RequestPropertiesChange(winid, props, vals); +} + +QRect NativeWindow::geometry(){ + //Calculate the "full" geometry of the window + frame (if any) + //Check that the size is between the min/max limitations + QSize size = hash.value(NativeWindow::Size).toSize(); + QSize min = hash.value(NativeWindow::MinSize).toSize(); + QSize max = hash.value(NativeWindow::MaxSize).toSize(); + if(min.isValid() && min.width() > size.width() ){ size.setWidth(min.width()); } + if(min.isValid() && min.height() > size.height()){ size.setHeight(min.height()); } + if(max.isValid() && max.width() < size.width() && max.width()>min.width()){ size.setWidth(max.width()); } + if(max.isValid() && max.height() < size.height() && max.height()>min.height()){ size.setHeight(max.height()); } + //Assemble the full geometry + QRect geom( hash.value(NativeWindow::GlobalPos).toPoint(), size ); + //Now adjust the window geom by the frame margins + QList<int> frame = hash.value(NativeWindow::FrameExtents).value< QList<int> >(); //Left,Right,Top,Bottom + //qDebug() << "Calculate Geometry:" << geom << frame; + if(frame.length()==4){ + geom = geom.adjusted( -frame[0], -frame[2], frame[1], frame[3] ); + } + //qDebug() << " - Total:" << geom; + return geom; +} +// ==== PUBLIC SLOTS === +void NativeWindow::toggleVisibility(){ + setProperty(NativeWindow::Visible, !property(NativeWindow::Visible).toBool() ); +} + +void NativeWindow::requestClose(){ + emit RequestClose(winid); +} + +void NativeWindow::requestKill(){ + emit RequestKill(winid); +} + +void NativeWindow::requestPing(){ + emit RequestPing(winid); +} diff --git a/src-qt5/src-cpp/obsolete/NativeWindow.h b/src-qt5/src-cpp/obsolete/NativeWindow.h new file mode 100644 index 00000000..67436259 --- /dev/null +++ b/src-qt5/src-cpp/obsolete/NativeWindow.h @@ -0,0 +1,118 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a container object for setting/announcing changes +// in a native window's properties. +// The WM will usually run the "setProperty" function on this object, +// and any other classes/widgets which watch this window can act appropriatly after-the-fact +// Non-WM classes should use the "Request" signals to ask the WM to do something, and listen for changes later +//=========================================== +#ifndef _LUMINA_DESKTOP_NATIVE_WINDOW_H +#define _LUMINA_DESKTOP_NATIVE_WINDOW_H + +#include <QString> +#include <QRect> +#include <QSize> +#include <QObject> +#include <QWindow> +#include <QHash> +#include <QVariant> + +class NativeWindow : public QObject{ + Q_OBJECT +public: + enum State{ S_MODAL, S_STICKY, S_MAX_VERT, S_MAX_HORZ, S_SHADED, S_SKIP_TASKBAR, S_SKIP_PAGER, S_HIDDEN, S_FULLSCREEN, S_ABOVE, S_BELOW, S_ATTENTION }; + enum Type{T_DESKTOP, T_DOCK, T_TOOLBAR, T_MENU, T_UTILITY, T_SPLASH, T_DIALOG, T_DROPDOWN_MENU, T_POPUP_MENU, T_TOOLTIP, T_NOTIFICATION, T_COMBO, T_DND, T_NORMAL }; + enum Action {A_MOVE, A_RESIZE, A_MINIMIZE, A_SHADE, A_STICK, A_MAX_VERT, A_MAX_HORZ, A_FULLSCREEN, A_CHANGE_DESKTOP, A_CLOSE, A_ABOVE, A_BELOW}; + + enum Property{ /*QVariant Type*/ + None=0, /*null*/ + MinSize=1, /*QSize*/ + MaxSize=2, /*QSize*/ + Size=3, /*QSize*/ + GlobalPos=4, /*QPoint*/ + Title=5, /*QString*/ + ShortTitle=6, /*QString*/ + Icon=7, /*QIcon*/ + Name=8, /*QString*/ + Workspace=9, /*int*/ + States=10, /*QList<NativeWindow::State> : Current state of the window */ + WinTypes=11, /*QList<NativeWindow::Type> : Current type of window (typically does not change)*/ + WinActions=12, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/ + FrameExtents=13, /*QList<int> : [Left, Right, Top, Bottom] in pixels */ + RelatedWindows=14, /* QList<WId> - better to use the "isRelatedTo(WId)" function instead of reading this directly*/ + Active=15, /*bool*/ + Visible=16 /*bool*/ + }; + + static QList<NativeWindow::Property> allProperties(){ + //Return all the available properties (excluding "None" and "FrameExtents" (WM control only) ) + QList<NativeWindow::Property> props; + props << MinSize << MaxSize << Size << GlobalPos << Title << ShortTitle << Icon << Name << Workspace \ + << States << WinTypes << WinActions << RelatedWindows << Active << Visible; + return props; + }; + + NativeWindow(WId id); + ~NativeWindow(); + + void addFrameWinID(WId); + void addDamageID(unsigned int); + bool isRelatedTo(WId); + + WId id(); + WId frameId(); + unsigned int damageId(); + + //QWindow* window(); + + QVariant property(NativeWindow::Property); + void setProperty(NativeWindow::Property, QVariant, bool force = false); + void setProperties(QList<NativeWindow::Property>, QList<QVariant>, bool force = false); + void requestProperty(NativeWindow::Property, QVariant, bool force = false); + void requestProperties(QList<NativeWindow::Property>, QList<QVariant>, bool force = false); + + QRect geometry(); //this returns the "full" geometry of the window (window + frame) + +public slots: + void toggleVisibility(); + void requestClose(); //ask the app to close the window (may/not depending on activity) + void requestKill(); //ask the WM to kill the app associated with this window (harsh - only use if not responding) + void requestPing(); //ask the app if it is still active (a WindowNotResponding signal will get sent out if there is no reply); + +private: + QHash <NativeWindow::Property, QVariant> hash; + //QWindow *WIN; + WId winid, frameid; + QList<WId> relatedTo; + unsigned int dmgID; + +signals: + //General Notifications + void PropertiesChanged(QList<NativeWindow::Property>, QList<QVariant>); + void RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>); + void WindowClosed(WId); + void WindowNotResponding(WId); //will be sent out if a window does not respond to a ping request + void VisualChanged(); + + //Action Requests (not automatically emitted - typically used to ask the WM to do something) + //Note: "WId" should be the NativeWindow id() + void RequestClose(WId); //Close the window + void RequestKill(WId); //Kill the window/app (usually from being unresponsive) + void RequestPing(WId); //Verify that the window is still active (such as not closing after a request + void RequestReparent(WId, WId, QPoint); //client window, frame window, relative origin point in frame + // System Tray Icon Embed/Unembed Requests + //void RequestEmbed(WId, QWidget*); + //void RequestUnEmbed(WId, QWidget*); +}; + +// Declare the enumerations as Qt MetaTypes +Q_DECLARE_METATYPE(NativeWindow::Type); +Q_DECLARE_METATYPE(NativeWindow::Action); +Q_DECLARE_METATYPE(NativeWindow::State); +Q_DECLARE_METATYPE(NativeWindow::Property); + +#endif diff --git a/src-qt5/src-cpp/obsolete/NativeWindow.pri b/src-qt5/src-cpp/obsolete/NativeWindow.pri new file mode 100644 index 00000000..12eb27fe --- /dev/null +++ b/src-qt5/src-cpp/obsolete/NativeWindow.pri @@ -0,0 +1,13 @@ + +# Files +QT *= x11extras +LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lxcb-keysyms -lXdamage + +SOURCES *= $${PWD}/NativeWindowSystem.cpp \ + $${PWD}/NativeKeyToQt.cpp \ + $${PWD}/NativeEventFilter.cpp + +HEADERS *= $${PWD}/NativeWindowSystem.h \ + $${PWD}/NativeEventFilter.h + +INCLUDEPATH *= $${PWD} |