From 9804217b51b058fed43a060a746f543da044b2a5 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 5 May 2013 03:46:01 -0500 Subject: Fix OpenGL screensaver background when ARGB mode is enabled --- kdesktop/lock/lockprocess.cc | 32 ++++++---- kdesktop/lock/lockprocess.h | 1 + twin/kompmgr/kompmgr.c | 137 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 143 insertions(+), 27 deletions(-) diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc index 33fd374aa..30c9e4dee 100644 --- a/kdesktop/lock/lockprocess.cc +++ b/kdesktop/lock/lockprocess.cc @@ -137,6 +137,10 @@ static Window gVRootData = 0; static Atom gXA_VROOT; static Atom gXA_SCREENSAVER_VERSION; +Atom kde_wm_system_modal_notification = 0; +Atom kde_wm_transparent_to_desktop = 0; +Atom kde_wm_transparent_to_black = 0; + void print_trace() { #ifdef WITH_KDESKTOP_LOCK_BACKTRACE @@ -234,7 +238,8 @@ LockProcess::LockProcess() m_mousePrevY(0), m_dialogPrevX(0), m_dialogPrevY(0), - m_maskWidget(NULL) + m_maskWidget(NULL), + m_saverRootWindow(0) { #ifdef KEEP_MOUSE_UNGRABBED setNFlags(WX11DisableMove|WX11DisableClose|WX11DisableShade|WX11DisableMinimize|WX11DisableMaximize); @@ -242,10 +247,10 @@ LockProcess::LockProcess() setupSignals(); - // Signal that we want to be transparent to the desktop, not to windows behind us... - Atom kde_wm_transparent_to_desktop; + // Set up atoms + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False); kde_wm_transparent_to_desktop = XInternAtom(tqt_xdisplay(), "_KDE_TRANSPARENT_TO_DESKTOP", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_transparent_to_desktop, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + kde_wm_transparent_to_black = XInternAtom(tqt_xdisplay(), "_KDE_TRANSPARENT_TO_BLACK", False); kapp->installX11EventFilter(this); @@ -923,8 +928,8 @@ void LockProcess::createSaverWindow() XFree( info ); } - Window w = XCreateWindow( x11Display(), RootWindow( x11Display(), x11Screen()), x(), y(), width(), height(), 0, x11Depth(), InputOutput, visual, flags, &attrs ); - create( w ); + m_saverRootWindow = XCreateWindow( x11Display(), RootWindow( x11Display(), x11Screen()), x(), y(), width(), height(), 0, x11Depth(), InputOutput, visual, flags, &attrs ); + create( m_saverRootWindow ); // Some xscreensaver hacks check for this property const char *version = "KDE 2.0"; @@ -937,9 +942,7 @@ void LockProcess::createSaverWindow() XChangeWindowAttributes(tqt_xdisplay(), winId(), CWEventMask, &attr); // Signal that we want to be transparent to the desktop, not to windows behind us... - Atom kde_wm_transparent_to_desktop; - kde_wm_transparent_to_desktop = XInternAtom(tqt_xdisplay(), "_KDE_TRANSPARENT_TO_DESKTOP", False); - XChangeProperty(tqt_xdisplay(), w, kde_wm_transparent_to_desktop, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_desktop, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); // erase(); @@ -1598,6 +1601,11 @@ bool LockProcess::startHack() if (trinity_desktop_lock_use_system_modal_dialogs) { // Make sure we have a nice clean display to start with! if (argb_visual) { + // Signal that we want to be transparent to a black background... + if (m_saverRootWindow) { + XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); + } setTransparentBackgroundARGB(); } else { @@ -1712,6 +1720,10 @@ void LockProcess::hackExited(TDEProcess *) } } if (argb_visual) { + if (m_saverRootWindow) { + XDeleteProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black); + XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); + } setTransparentBackgroundARGB(); } else { @@ -2346,8 +2358,6 @@ void LockProcess::msgBox( TQMessageBox::Icon type, const TQString &txt ) TQDialog box( 0, "messagebox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); if (trinity_desktop_lock_use_system_modal_dialogs) { // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False); XChangeProperty(tqt_xdisplay(), box.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); } box.setCaption(i18n("Authentication Subsystem Notice")); diff --git a/kdesktop/lock/lockprocess.h b/kdesktop/lock/lockprocess.h index 5b9649893..23fe9912a 100644 --- a/kdesktop/lock/lockprocess.h +++ b/kdesktop/lock/lockprocess.h @@ -238,6 +238,7 @@ private: int m_dialogPrevY; TQWidget* m_maskWidget; + Window m_saverRootWindow; ControlPipeHandlerObject* mControlPipeHandler; TQEventLoopThread* mControlPipeHandlerThread; diff --git a/twin/kompmgr/kompmgr.c b/twin/kompmgr/kompmgr.c index 34ebb86e1..55c1bebd1 100644 --- a/twin/kompmgr/kompmgr.c +++ b/twin/kompmgr/kompmgr.c @@ -163,6 +163,9 @@ typedef struct _win { /* setting whether a window will be transparent to the desktop or the windows below it */ Bool show_root_tile; + + /* setting whether a window will be transparent to a black background or something else */ + Bool show_black_background; } win; typedef struct _conv { @@ -228,6 +231,7 @@ Atom dimAtom; Atom deskChangeAtom; Atom winTypeAtom; Atom winTDETTDAtom; +Atom winTDETTBAtom; Atom winType[NUM_WINTYPES]; double winTypeOpacity[NUM_WINTYPES]; Bool winTypeShadow[NUM_WINTYPES]; @@ -1081,6 +1085,12 @@ static char *backgroundProps[] = { 0, }; +static Bool +determine_window_transparent_to_black(Display *dpy, Window w); + +static Bool +determine_window_transparent_to_desktop(Display *dpy, Window w); + static Picture root_tile (Display *dpy) { @@ -1596,7 +1606,18 @@ paint_all (Display *dpy, XserverRegion region) background pixmap entirely here is the place to do it; simply draw the new background onto rootBuffer before continuing! */ if (w->isInFade == False) { - if (w->show_root_tile == True) { + // HACK + // For an unknown reason the PropertyNotify event handler is not + // fired when either the show_black_background or show_root_tile + // control atoms are changed. This works around the problem but + // causes an unquantified, likely relatively low, performance loss. + w->show_black_background = determine_window_transparent_to_black(dpy, w->id); + if (w->show_black_background == True) { + XRenderComposite (dpy, PictOpSrc, blackPicture, None, rootBuffer, + x, y, x, y, + x, y, wid, hei); + } + else if (w->show_root_tile == True) { XRenderComposite (dpy, PictOpSrc, rootTile, None, rootBuffer, x, y, x, y, x, y, wid, hei); @@ -1807,8 +1828,9 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade) win *w = find_win (dpy, id); Drawable back; - if (!w) + if (!w) { return; + } w->a.map_state = IsViewable; @@ -1817,6 +1839,8 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade) /* This needs to be here since we don't get PropertyNotify when unmapped */ w->opacity = get_opacity_prop (dpy, w, OPAQUE); + w->show_root_tile = determine_window_transparent_to_desktop(dpy, id); + w->show_black_background = determine_window_transparent_to_black(dpy, id); determine_mode (dpy, w); w->windowType = determine_wintype (dpy, w->id, w->id); @@ -1846,8 +1870,9 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade) #endif w->a_prev = w->a; - if (fade && winTypeFade[w->windowType]) + if (fade && winTypeFade[w->windowType]) { set_fade (dpy, w, 0, get_opacity_prop(dpy, w, OPAQUE)*1.0/OPAQUE, fade_in_step, 0, False, True, True, True); + } } static void @@ -2175,6 +2200,28 @@ get_window_transparent_to_desktop(Display * dpy, Window w) return False; } +static Bool +get_window_transparent_to_black(Display * dpy, Window w) +{ + Atom actual; + int format; + unsigned long n, left; + + unsigned char *data; + int result = XGetWindowProperty (dpy, w, winTDETTBAtom, 0L, 1L, False, + XA_ATOM, &actual, &format, + &n, &left, &data); + + if (result == Success && data != None && format == 32 ) + { + Atom a; + a = *(long*)data; + XFree ( (void *) data); + return True; + } + return False; +} + static void determine_mode(Display *dpy, win *w) { @@ -2235,8 +2282,9 @@ determine_window_transparent_to_desktop (Display *dpy, Window w) Bool type; type = get_window_transparent_to_desktop (dpy, w); - if (type == True) + if (type == True) { return True; + } if (!XQueryTree (dpy, w, &root_return, &parent_return, &children, &nchildren)) @@ -2260,6 +2308,41 @@ determine_window_transparent_to_desktop (Display *dpy, Window w) return False; } +static Bool +determine_window_transparent_to_black (Display *dpy, Window w) +{ + Window root_return, parent_return; + Window *children = NULL; + unsigned int nchildren, i; + Bool type; + + type = get_window_transparent_to_black (dpy, w); + if (type == True) { + return True; + } + + if (!XQueryTree (dpy, w, &root_return, &parent_return, &children, + &nchildren)) + { + /* XQueryTree failed. */ + if (children) + XFree ((void *)children); + return False; + } + + for (i = 0;i < nchildren;i++) + { + type = determine_window_transparent_to_black (dpy, children[i]); + if (type == True) + return True; + } + + if (children) + XFree ((void *)children); + + return False; +} + static void add_win (Display *dpy, Window id, Window prev) { @@ -2330,6 +2413,7 @@ add_win (Display *dpy, Window id, Window prev) new->shadowSize = 100; new->decoHash = 0; new->show_root_tile = determine_window_transparent_to_desktop(dpy, id); + new->show_black_background = determine_window_transparent_to_black(dpy, id); new->windowType = determine_wintype (dpy, new->id, new->id); if ((new->windowType < 0) || (new->windowType > NUM_WINTYPES)) new->windowType = WINTYPE_NORMAL; @@ -3400,6 +3484,7 @@ main (int argc, char **argv) deskChangeAtom = XInternAtom (dpy, DESKCHANGE_PROP, False); winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False); winTDETTDAtom = XInternAtom (dpy, "_KDE_TRANSPARENT_TO_DESKTOP", False); + winTDETTBAtom = XInternAtom (dpy, "_KDE_TRANSPARENT_TO_BLACK", False); winType[WINTYPE_DESKTOP] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False); winType[WINTYPE_DOCK] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); winType[WINTYPE_TOOLBAR] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False); @@ -3464,8 +3549,9 @@ main (int argc, char **argv) allDamage = None; clipChanged = True; XGrabServer (dpy); - if (autoRedirect) + if (autoRedirect) { XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic); + } else { int dummy; @@ -3489,8 +3575,9 @@ main (int argc, char **argv) XUngrabServer (dpy); ufd.fd = ConnectionNumber (dpy); ufd.events = POLLIN; - if (!autoRedirect) + if (!autoRedirect) { paint_all (dpy, None); + } /* Under no circumstances should these two lines EVER be moved earlier in main() than this point */ atexit(delete_pid_file); @@ -3500,8 +3587,9 @@ main (int argc, char **argv) { /* dump_wins (); */ do { - if (autoRedirect) + if (autoRedirect) { XFlush (dpy); + } if (!QLength (dpy)) { if (poll (&ufd, 1, fade_timeout()) == 0) @@ -3512,8 +3600,9 @@ main (int argc, char **argv) } XNextEvent (dpy, &ev); - if ((ev.type & 0x7f) != KeymapNotify) + if ((ev.type & 0x7f) != KeymapNotify) { discard_ignore (dpy, ev.xany.serial); + } #if DEBUG_EVENTS printf ("event %10.10s serial 0x%08x window 0x%08x\n", ev_name(&ev), ev_serial (&ev), ev_window (&ev)); @@ -3711,14 +3800,30 @@ main (int argc, char **argv) w->extents = win_extents (dpy, w); } } - } - else if (ev.xproperty.atom == deskChangeAtom) - { - /*just set global variable*/ - unsigned int tmp = get_deskchange_prop(dpy, ev.xproperty.window); - printf("desk change, state:%d\n",tmp); - } - break; + } + else if (ev.xproperty.atom == deskChangeAtom) + { + /*just set global variable*/ + unsigned int tmp = get_deskchange_prop(dpy, ev.xproperty.window); + printf("desk change, state:%d\n",tmp); + } + else if (ev.xproperty.atom == winTDETTDAtom) + { + win * w = find_win(dpy, ev.xproperty.window); + if (w) + { + w->show_root_tile = determine_window_transparent_to_desktop(dpy, ev.xproperty.window); + } + } + else if (ev.xproperty.atom == winTDETTBAtom) + { + win * w = find_win(dpy, ev.xproperty.window); + if (w) + { + w->show_black_background = determine_window_transparent_to_black(dpy, ev.xproperty.window); + } + } + break; default: if (ev.type == damage_event + XDamageNotify) { -- cgit v1.2.1