diff options
Diffstat (limited to 'libLumina/LuminaX11.cpp')
-rw-r--r-- | libLumina/LuminaX11.cpp | 125 |
1 files changed, 105 insertions, 20 deletions
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp index 5f4afab4..4780f8e0 100644 --- a/libLumina/LuminaX11.cpp +++ b/libLumina/LuminaX11.cpp @@ -13,13 +13,9 @@ #include <QImage> #include <QApplication> #include <QDesktopWidget> +#include <QScreen> + -//X includes (these need to be last due to Qt compile issues) -/*#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xrender.h> -#include <X11/extensions/Xcomposite.h>*/ //XCB Library includes #include <xcb/xcb.h> @@ -31,7 +27,9 @@ #include <xcb/xcb_aux.h> #include <xcb/composite.h> #include <xcb/damage.h> -//#include <xcb/render.h> + +//XLib includes +#include <X11/extensions/Xdamage.h> #define DEBUG 0 @@ -478,7 +476,7 @@ QIcon LXCB::WindowIcon(WId win){ // === SelectInput() === void LXCB::SelectInput(WId win){ - uint32_t mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; + uint32_t mask = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_change_window_attributes(QX11Info::connection(), win, XCB_CW_EVENT_MASK, &mask ); } @@ -778,6 +776,30 @@ void LXCB::ReserveLocation(WId win, QRect geom, QString loc){ xcb_ewmh_set_wm_strut(&EWMH, win, LOC.left, LOC.right, LOC.top, LOC.bottom); //_NET_WM_STRUT } +/*void LXCB::SetWindowBackground(QWidget *parent, QRect area, WId client){ + //Copy the image from the parent onto the client (parent/child - for system tray apps) + //First create the background graphics context + //qDebug() << "Create graphics context"; + //xcb_screen_t *root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen()); + uint32_t val = XCB_GX_CLEAR; + xcb_gcontext_t graphic_context = xcb_generate_id(QX11Info::connection()); + xcb_create_gc(QX11Info::connection(), graphic_context, client, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, &val); + //qDebug() << "Copy Background Area"; + //Now copy the image onto the client background + xcb_copy_area(QX11Info::connection(), + parent->winId(), + client, + graphic_context, + area.x(), area.y(), + 0, 0, + area.width(), area.height()); + //Now re-map the client so it paints on top of the new background + //qDebug() << "Map Window"; + //xcb_map_window(QX11Info::connection(), client); + //Clean up variables + xcb_free_gc(QX11Info::connection(), graphic_context); +}*/ + // === EmbedWindow() === uint LXCB::EmbedWindow(WId win, WId container){ if(DEBUG){ qDebug() << "XCB: EmbedWindow()"; } @@ -813,20 +835,18 @@ uint LXCB::EmbedWindow(WId win, WId container){ xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); //Now setup any redirects and return - //qDebug() << " - select Input"; - //XSelectInput(disp, win, StructureNotifyMask); //Notify of structure changes - //uint32_t val[] = {XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY}; - //xcb_change_window_attributes(QX11Info::connection(), win, XCB_CW_EVENT_MASK, val); - this->SelectInput(win); - //qDebug() << " - Composite Redirect"; - xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); + this->SelectInput(win); //Notify of structure changes + xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); //Now map the window (will be a transparent child of the container) xcb_map_window(QX11Info::connection(), win); //Now create/register the damage handler - 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, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); + // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, 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, 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, XDamageReportRawRectangles); //qDebug() << " - Done"; return ( (uint) dmgID ); @@ -836,9 +856,7 @@ uint LXCB::EmbedWindow(WId win, WId container){ bool LXCB::UnembedWindow(WId win){ if(DEBUG){ qDebug() << "XCB: UnembedWindow()"; } if(win==0){ return false; } - //Display *disp = QX11Info::display(); //Remove redirects - //XSelectInput(disp, win, NoEventMask); uint32_t val[] = {XCB_EVENT_MASK_NO_EVENT}; xcb_change_window_attributes(QX11Info::connection(), win, XCB_CW_EVENT_MASK, val); //Make sure it is invisible @@ -848,6 +866,73 @@ bool LXCB::UnembedWindow(WId win){ return true; } +// === TrayImage() === +QPixmap LXCB::TrayImage(WId win){ + QPixmap pix; + + //Get the current QScreen (for XCB->Qt conversion) + QList<QScreen*> scrnlist = QApplication::screens(); + if(scrnlist.isEmpty()){ return pix; } + + //Try to grab the given window directly with Qt + if(pix.isNull()){ + pix = scrnlist[0]->grabWindow(win); + } + return pix; + + //NOTE: Code below here saved for reference later (as necessary) + // ------------------------------- + /*//First get the pixmap from the XCB compositing layer (since the tray images are redirected there) + xcb_pixmap_t pixmap = xcb_generate_id(QX11Info::connection()); + xcb_composite_name_window_pixmap(QX11Info::connection(), win, pixmap); + //Get the sizing information about the pixmap + xcb_get_geometry_cookie_t Gcookie = xcb_get_geometry_unchecked(QX11Info::connection(), pixmap); + xcb_get_geometry_reply_t *Greply = xcb_get_geometry_reply(QX11Info::connection(), Gcookie, NULL); + if(Greply==0){ qDebug() << "[Tray Image] - Geom Fetch Error:"; return QPixmap(); } //Error in geometry detection + + //Now convert the XCB pixmap into an XCB image + xcb_get_image_cookie_t GIcookie = xcb_get_image_unchecked(QX11Info::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, 0, 0, Greply->width, Greply->height, 0xffffffff); + xcb_get_image_reply_t *GIreply = xcb_get_image_reply(QX11Info::connection(), GIcookie, NULL); + if(GIreply==0){ qDebug() << "[Tray Image] - Image Convert Error:"; return QPixmap(); } //Error in conversion + uint8_t *GIdata = xcb_get_image_data(GIreply); + uint32_t BPL = xcb_get_image_data_length(GIreply) / Greply->height; //bytes per line + //Now convert the XCB image into a Qt Image + QImage image(const_cast<uint8_t *>(GIdata), Greply->width, Greply->height, BPL, QImage::Format_ARGB32_Premultiplied); + //Free the various data structures + free(GIreply); //done with get image reply + xcb_free_pixmap(QX11Info::connection(), pixmap); //done with the raw pixmap + free(Greply); //done with geom reply*/ + + /* NOTE: Found these little bit in the Qt sources - not sure if it is needed, but keep it here for reference + // we may have to swap the byte order based on system type + uint8_t image_byte_order = connection->setup()->image_byte_order; + if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST) + || (QSysInfo::ByteOrder == QSysInfo::BigEndian && image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)) + { + for (int i=0; i < image.height(); i++) { + uint *p = (uint*)image.scanLine(i); + uint *end = p + image.width(); + while (p < end) { + *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) + | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); + p++; + } + } + }*/ + + // fix-up alpha channel + /*if (image.format() == QImage::Format_RGB32) { + QRgb *p = (QRgb *)image.bits(); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) + p[x] |= 0xff000000; + p += bytes_per_line / 4; + }*/ + + //Convert the QImage into a QPixmap and return it + //return QPixmap::fromImage(image.copy()); +} + // ===== startSystemTray() ===== WId LXCB::startSystemTray(int screen){ qDebug() << "Starting System Tray:" << screen; @@ -987,4 +1072,4 @@ void LXCB::closeSystemTray(WId trayID){ void LXCB::WM_CloseWindow(WId win){ xcb_destroy_window(QX11Info::connection(), win); } -
\ No newline at end of file + |