aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--dev-tools/systray-tester/Trayapp.h2
-rw-r--r--libLumina/LuminaThemes.cpp14
-rw-r--r--libLumina/LuminaThemes.h6
-rw-r--r--libLumina/LuminaX11.cpp125
-rw-r--r--libLumina/LuminaX11.h3
-rw-r--r--libLumina/libLumina.pro2
-rw-r--r--lumina-desktop/LXcbEventFilter.cpp1
-rw-r--r--lumina-desktop/panel-plugins/systemtray/LSysTray.cpp5
-rw-r--r--lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp16
9 files changed, 138 insertions, 36 deletions
diff --git a/dev-tools/systray-tester/Trayapp.h b/dev-tools/systray-tester/Trayapp.h
index 54fa8a6b..a16e1127 100644
--- a/dev-tools/systray-tester/Trayapp.h
+++ b/dev-tools/systray-tester/Trayapp.h
@@ -3,6 +3,7 @@
#include <QSystemTrayIcon>
#include <QMenu>
#include <QTimer>
+#include <QDebug>
#include <LuminaXDG.h>
@@ -18,6 +19,7 @@ private slots:
this->setToolTip("Icon Number:"+QString::number(iconnum));
QString ico;
//Rotate the icon every time
+ qDebug() << "Changing Icon:" << iconnum;
if(iconnum <=0){ ico = "arrow-left"; iconnum=1; }
else if(iconnum==1){ ico = "arrow-up"; iconnum=2; }
else if(iconnum==2){ ico = "arrow-right"; iconnum=3; }
diff --git a/libLumina/LuminaThemes.cpp b/libLumina/LuminaThemes.cpp
index b64ace0f..7a4ce9ad 100644
--- a/libLumina/LuminaThemes.cpp
+++ b/libLumina/LuminaThemes.cpp
@@ -315,7 +315,7 @@ QString LTHEME::readCustomEnvSetting(QString var){
// =========================
// LuminaThemeStyle
// =========================
-LuminaThemeStyle::LuminaThemeStyle() : QProxyStyle(){
+/*LuminaThemeStyle::LuminaThemeStyle() : QProxyStyle(){
this->update();
}
@@ -326,10 +326,10 @@ LuminaThemeStyle::~LuminaThemeStyle(){
//Function to update the style (for use by the theme engine)
void LuminaThemeStyle::update(){
darkfont = true; //make this dynamic later
-}
+}*/
//Subclassed functions
-void LuminaThemeStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const{
+//void LuminaThemeStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const{
/*QFont cfont = painter->font();
cfont.setHintingPreference(QFont::PreferFullHinting);
QFont outfont = cfont;
@@ -348,7 +348,7 @@ void LuminaThemeStyle::drawItemText(QPainter *painter, const QRect &rect, int al
else{ painter->setPen(QPen(Qt::white)); }
painter->drawText(rect, text);*/
- QFont font = painter->font();
+ /*QFont font = painter->font();
QFont cfont = font; //save for later
if(font.pixelSize()>0){ font.setPixelSize( font.pixelSize()-4); }
else{ font.setPointSize(font.pointSize()-1); }
@@ -369,9 +369,9 @@ void LuminaThemeStyle::drawItemText(QPainter *painter, const QRect &rect, int al
}
painter->setPen(pen);
painter->drawPath(path);
- painter->setFont(cfont); //reset back to original font
+ painter->setFont(cfont); //reset back to original font*/
-}
+//}
//==================
@@ -439,7 +439,7 @@ void LuminaThemeEngine::reloadFiles(){
if(font!=current[3] || fontsize!=current[4]){
font=current[3]; fontsize=current[4];
QFont tmp = application->font();
- tmp.setStyleStrategy(QFont::PreferOutline);
+ tmp.setStyleStrategy(QFont::PreferAntialias);
tmp.setFamily(font);
if(fontsize.endsWith("pt")){ tmp.setPointSize(fontsize.section("pt",0,0).toInt()); }
else if(fontsize.endsWith("px")){ tmp.setPixelSize(fontsize.section("px",0,0).toInt()); }
diff --git a/libLumina/LuminaThemes.h b/libLumina/LuminaThemes.h
index 4ded0527..0ff15aa1 100644
--- a/libLumina/LuminaThemes.h
+++ b/libLumina/LuminaThemes.h
@@ -58,7 +58,7 @@ public:
};
// Qt Style override to allow custom themeing/colors
-class LuminaThemeStyle : public QProxyStyle{
+/*class LuminaThemeStyle : public QProxyStyle{
Q_OBJECT
private:
bool darkfont;
@@ -72,7 +72,7 @@ public:
//Subclassed functions
void drawItemText(QPainter*, const QRect&, int, const QPalette&, bool, const QString&, QPalette::ColorRole) const;
-};
+};*/
//Simple class to setup a utility to use the Lumina theme
//-----Example usage in "main.cpp" -------------------------------
@@ -98,7 +98,7 @@ private:
QString theme,colors,icons, font, fontsize, cursors; //current settings
QTimer *syncTimer;
QDateTime lastcheck;
- LuminaThemeStyle *style;
+ //LuminaThemeStyle *style;
private slots:
void watcherChange();
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
+
diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h
index 1732616f..8fe741f9 100644
--- a/libLumina/LuminaX11.h
+++ b/libLumina/LuminaX11.h
@@ -106,12 +106,15 @@ public:
void ReserveLocation(WId win, QRect geom, QString loc);
//Window Embedding/Detaching (for system tray)
+ //void SetWindowBackground(QWidget *parent, QRect area, WId client);
uint EmbedWindow(WId win, WId container); //returns the damage ID (or 0 for an error)
bool UnembedWindow(WId win);
+ QPixmap TrayImage(WId win);
//System Tray Management
WId startSystemTray(int screen = 0); //Startup the system tray (returns window ID for tray)
void closeSystemTray(WId); //Close the system tray
+
//============
// WM Functions (directly changing properties/settings)
diff --git a/libLumina/libLumina.pro b/libLumina/libLumina.pro
index c32a4cb5..ddd26056 100644
--- a/libLumina/libLumina.pro
+++ b/libLumina/libLumina.pro
@@ -59,7 +59,7 @@ equals(LINUX_DISTRIBUTION, "Debian"): {
INCLUDEPATH += $$PREFIX/include
-LIBS += -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util
+LIBS += -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lXdamage
include.path=$$PREFIX/include/
include.files=LuminaXDG.h \
diff --git a/lumina-desktop/LXcbEventFilter.cpp b/lumina-desktop/LXcbEventFilter.cpp
index a3a8147b..aa38002b 100644
--- a/lumina-desktop/LXcbEventFilter.cpp
+++ b/lumina-desktop/LXcbEventFilter.cpp
@@ -31,6 +31,7 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag
if(stopping){ return false; } //don't do any parsing
//qDebug() << "New Event";
if(eventType=="xcb_generic_event_t"){
+ //qDebug() << " - XCB event";
//Convert to known event type (for X11 systems)
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
//Now parse the event and emit signals as necessary
diff --git a/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp b/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp
index 220c7858..05c601e1 100644
--- a/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp
+++ b/lumina-desktop/panel-plugins/systemtray/LSysTray.cpp
@@ -150,8 +150,9 @@ void LSysTray::UpdateTrayWindow(WId win){
for(int i=0; i<trayIcons.length(); i++){
if(trayIcons[i]->appID()==win){
qDebug() << "System Tray: Update Window " << win;
- trayIcons[i]->update();
- QTimer::singleShot(1000, trayIcons[i], SLOT(update()) );
+ trayIcons[i]->repaint(); //don't use update() because we need an instant repaint (not a cached version)
+ //QTimer::singleShot(10, trayIcons[i], SLOT(repaint()) ); //re-paint in 10ms (give it a moment to settle)
+ //QTimer::singleShot(1000, trayIcons[i], SLOT(update()) );
return; //finished now
}
}
diff --git a/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp b/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp
index 3e26683f..01af6936 100644
--- a/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp
+++ b/lumina-desktop/panel-plugins/systemtray/TrayIcon.cpp
@@ -83,19 +83,29 @@ void TrayIcon::updateIcon(){
void TrayIcon::paintEvent(QPaintEvent *event){
QWidget::paintEvent(event); //make sure the background is already painted
if(AID!=0){
+ //Update the background on the tray app
+ //qDebug() << "Paint Tray Background";
+ //LSession::handle()->XCB->SetWindowBackground(this, this->geometry(), AID);
//qDebug() << "Paint Tray:" << AID;
QPainter painter(this);
//Now paint the tray app on top of the background
//qDebug() << " - Draw tray:" << AID << IID << this->winId();
//qDebug() << " - - " << event->rect().x() << event->rect().y() << event->rect().width() << event->rect().height();
//qDebug() << " - Get image:" << AID;
- QPixmap pix; //= WIN->icon().pixmap(this->size());
- //Try to grab the window directly with Qt
- QList<QScreen*> scrnlist = QApplication::screens();
+ QPixmap pix = LSession::handle()->XCB->TrayImage(AID); //= WIN->icon().pixmap(this->size());
+ //if(pix.isNull()){
+ //qDebug() << "Null Image - use Qt grab Window";
+ //Try to grab the window directly with Qt instead
+ /*QList<QScreen*> scrnlist = QApplication::screens();
for(int i=0; i<scrnlist.length(); i++){
pix = scrnlist[i]->grabWindow(AID);
break; //stop here
}
+ //}
+ if(pix.isNull()){
+ qDebug() << "Null Qt Pixmap - Use XCB grab image:";
+ pix = LSession::handle()->XCB->TrayImage(AID);
+ }*/
//qDebug() << " - Pix size:" << pix.size().width() << pix.size().height();
//qDebug() << " - Geom:" << this->geometry().x() << this->geometry().y() << this->geometry().width() << this->geometry().height();
if(!pix.isNull()){
bgstack15