aboutsummaryrefslogtreecommitdiff
path: root/libLumina/LuminaX11.cpp
diff options
context:
space:
mode:
authorKen Moore <moorekou@gmail.com>2015-09-15 19:02:00 -0400
committerKen Moore <moorekou@gmail.com>2015-09-15 19:02:00 -0400
commit043cb2ef441b4ee46961ed837fedab082db14ceb (patch)
tree8f070d92e9b589d2cce1b1f522dfaac0d4ca6631 /libLumina/LuminaX11.cpp
parentAdjust the theming of the calendar widgets so that the day/week are a bit mor... (diff)
downloadlumina-043cb2ef441b4ee46961ed837fedab082db14ceb.tar.gz
lumina-043cb2ef441b4ee46961ed837fedab082db14ceb.tar.bz2
lumina-043cb2ef441b4ee46961ed837fedab082db14ceb.zip
Finally fix up the system tray updates:
Found out that (at least on FreeBSD 10.2 right now), the xcb_damage_create() routine does absolutely nothing (no damage events ever sent out when the window changes). Switching this back to the Xlib XDamageCreate() routine makes it work perfectly again. Need to ask about this upstream and see if this is a known bug/regression in the XCB libraries.
Diffstat (limited to 'libLumina/LuminaX11.cpp')
-rw-r--r--libLumina/LuminaX11.cpp125
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
+
bgstack15