summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2011-07-18 02:20:04 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2011-07-18 02:20:04 +0800
commit94ccc08c57b113c64370b5a9091fbc405ef1c562 (patch)
treec8f05d1061d459e3fae9318c75fed7f62eb440de
parent4fcd9c9ba61e8a37ee395813dd41a3a82f701cd7 (diff)
downloadx11locker-94ccc08c57b113c64370b5a9091fbc405ef1c562.tar.gz
x11locker-94ccc08c57b113c64370b5a9091fbc405ef1c562.tar.bz2
X11 Locker is an extension to the locker plugin and allows for X11 windows to be
the lock dialog
-rw-r--r--CMakeLists.txt5
-rw-r--r--VERSION1
-rw-r--r--src/xlocker.cpp355
-rw-r--r--src/xlocker.h139
-rw-r--r--xlocker.xml.in10
5 files changed, 510 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..7012075
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,5 @@
+find_package (Compiz REQUIRED)
+
+include (CompizPlugin)
+
+compiz_plugin (xlocker PLUGINDEPS composite opengl locker)
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..719a233
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.9.5.0
diff --git a/src/xlocker.cpp b/src/xlocker.cpp
new file mode 100644
index 0000000..620e81d
--- /dev/null
+++ b/src/xlocker.cpp
@@ -0,0 +1,355 @@
+/*
+ * Compiz x11 locker plugin
+ *
+ * xlocker.cpp
+ *
+ * Copyright (c) 2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "xlocker.h"
+#include <poll.h>
+
+COMPIZ_PLUGIN_20090315 (xlocker, X11LockerPluginVTable);
+
+namespace LockerAtoms
+{
+ Atom lockerStatus;
+ Atom lockerBgStatus;
+ Atom lockerUnlock;
+}
+
+/* Create a backing window */
+X11LockWindow::X11LockWindow (Window child) :
+ mCBackingWindow (NULL),
+ mBackingWindow (0),
+ mChild (child),
+ mMapped (false)
+{
+ unsigned char *propData;
+ long *data;
+ Atom retType;
+ int retFmt;
+ unsigned long retItems, retLeft;
+ XSetWindowAttributes attr;
+
+ attr.override_redirect = true;
+
+ /* Read the _COMPIZ_NET_LOCKER_STATUS property on this window
+ * and then reparent this window into a window that we own and
+ * control */
+
+ if (XGetWindowProperty (screen->dpy (), child, LockerAtoms::lockerStatus, 0L,
+ 4096L, false, XA_CARDINAL, &retType,
+ &retFmt, &retItems, &retLeft, &propData) == Success &&
+ retItems == 6 &&
+ retLeft == 0 &&
+ retFmt == 32)
+ {
+ data = (long *) propData;
+
+ mBackingWindow = XCreateWindow (screen->dpy (), screen->root (),
+ screen->outputDevs ().front ().centerX () - data[4] / 2,
+ screen->outputDevs ().front ().centerY () - data[5] / 2,
+ data[4], data[5], 0, CopyFromParent, InputOutput,
+ DefaultVisual (screen->dpy (), screen->screenNum ()),
+ CWOverrideRedirect, &attr);
+
+ XAddToSaveSet (screen->dpy (), child);
+ XReparentWindow (screen->dpy (), child, mBackingWindow, 0, 0);
+
+ mGeometry = CompRect (data[2], data[3], data[4], data[5]);
+ }
+}
+
+X11LockWindow::~X11LockWindow ()
+{
+ XDestroyWindow (screen->dpy (), mBackingWindow);
+}
+
+void
+X11LockWindow::hide ()
+{
+ XUnmapWindow (screen->dpy (), mBackingWindow);
+ mMapped = false;
+}
+
+void
+X11LockWindow::show ()
+{
+ XMapRaised (screen->dpy (), mBackingWindow);
+
+ mMapped = true;
+}
+
+bool
+X11LockWindow::visible ()
+{
+ return mMapped;
+}
+
+
+
+void
+X11LockWindow::completeBackingWindow (CompWindow *w)
+{
+ mCBackingWindow = w;
+
+ XSelectInput (screen->dpy (), mChild, PropertyChangeMask);
+}
+
+bool
+X11LockWindow::attemptUnlock (long *data)
+{
+ Lockable *lockable = Lockable::Default ();
+
+ if (data[1] == mChild)
+ {
+ lockable->unlock ();
+ return true;
+ }
+
+ return false;
+}
+
+void
+X11LockWindow::setGeometry (int x, int y, unsigned int width, unsigned int height)
+{
+ XWindowChanges xwc;
+ unsigned int mask = 0;
+
+ if (x != mGeometry.x ())
+ mask |= CWX;
+
+ if (y != mGeometry.y ())
+ mask |= CWY;
+
+ if (width != mGeometry.width ())
+ mask |= CWWidth;
+
+ if (height != CWHeight)
+ mask |= CWHeight;
+
+ /* Always position in the middle of the screen */
+ xwc.x = screen->outputDevs ().front ().centerX () - width / 2;
+ xwc.y = screen->outputDevs ().front ().centerY () - height / 2;
+ xwc.width = width;
+ xwc.height = height;
+
+ if (mCBackingWindow)
+ mCBackingWindow->configureXWindow (mask, &xwc);
+ else
+ XConfigureWindow (screen->dpy (), mBackingWindow, mask, &xwc);
+
+ mGeometry = CompRect (x, y, width, height);
+}
+
+void
+X11LockWindow::stackOffendingWindow (Window offender, XWindowChanges *xwc, unsigned int mask)
+{
+ CompWindow *p = mCBackingWindow->prev;
+
+ for (; p; p = p->prev)
+ {
+ mask |= (CWSibling | CWStackMode);
+ xwc->stack_mode = Above;
+ xwc->sibling = ROOTPARENT (p);
+
+ XConfigureWindow (screen->dpy (), offender, mask, xwc);
+ return;
+ }
+
+ /* Couldn't stack this window below anything ..
+ * stack the locker above instead then */
+
+ unsigned int vm;
+ XWindowChanges xlwc;
+
+ vm = CWStackMode | CWSibling;
+ xlwc.sibling = offender;
+ xlwc.stack_mode = Above;
+
+ XConfigureWindow (screen->dpy (), mBackingWindow, mask, &xlwc);
+}
+
+void
+X11LockWindow::paint (const GLMatrix &transform)
+{
+ GLFragment::Attrib a (GLWindow::get (mCBackingWindow)->lastPaintAttrib ());
+ a.setBrightness (BRIGHT);
+ a.setOpacity (OPAQUE);
+ a.setSaturation (COLOR);
+ if (!mCBackingWindow)
+ return;
+
+ glPushMatrix ();
+ glLoadMatrixf (transform.getMatrix ());
+
+ GLWindow::get (mCBackingWindow)->glDraw (transform, a,
+ infiniteRegion,
+ GLWindow::get (mCBackingWindow)->lastMask ());
+}
+
+void
+X11LockerScreen::handleEvent (XEvent *event)
+{
+ switch (event->type)
+ {
+ case PropertyNotify:
+ if (event->xproperty.atom == LockerAtoms::lockerStatus)
+ {
+ X11LockWindow *xlw = dynamic_cast <X11LockWindow *> (LockerLockWindow::Default ());
+
+ if (!xlw)
+ {
+ xlw = new X11LockWindow (event->xproperty.window);
+ LockerLockWindow::SetDefault (xlw);
+ }
+ else
+ {
+ /* Either a new locker window was created or the old one needs to be resized */
+
+ if (!xlw->isChildWindow (event->xproperty.window))
+ LockerLockWindow::SetDefault (new X11LockWindow (event->xproperty.window));
+ else
+ {
+ unsigned char *propData;
+ long *data;
+ Atom retType;
+ int retFmt;
+ unsigned long retItems, retLeft;
+
+ if (XGetWindowProperty (screen->dpy (), event->xproperty.window,
+ LockerAtoms::lockerStatus, 0L,
+ 4096L, false, XA_CARDINAL, &retType,
+ &retFmt, &retItems, &retLeft, &propData) == Success &&
+ retItems == 6 &&
+ retLeft == 0 &&
+ retFmt == 32)
+ {
+ xlw->setGeometry (data[2], data[3], data[4], data[5]);
+ }
+ }
+ }
+ }
+ break;
+ case ClientMessage:
+ if (event->xclient.message_type == LockerAtoms::lockerUnlock)
+ {
+ X11LockWindow *xlw = dynamic_cast <X11LockWindow *> (LockerLockWindow::Default ());
+
+ if (xlw)
+ xlw->attemptUnlock (event->xclient.data.l);
+ }
+ case ConfigureRequest:
+ if (event->xconfigurerequest.value_mask & (CWSibling | CWStackMode))
+ {
+ X11LockWindow *xlw = dynamic_cast <X11LockWindow *> (LockerLockWindow::Default ());
+
+ if (xlw)
+ {
+ if (xlw->isBackingWindow (event->xconfigurerequest.above))
+ {
+ XWindowChanges xwc;
+
+ xwc.x = event->xconfigurerequest.x;
+ xwc.y = event->xconfigurerequest.y;
+ xwc.width = event->xconfigurerequest.width;
+ xwc.height = event->xconfigurerequest.height;
+ xwc.stack_mode = event->xconfigurerequest.detail;
+ xwc.sibling = event->xconfigurerequest.above;
+
+ /* Do not allow other windows to go above this one,
+ * find the next window below this one and go above
+ * that instead */
+ xlw->stackOffendingWindow (event->xconfigurerequest.window, &xwc, event->xconfigurerequest.value_mask);
+ }
+ }
+ }
+ }
+
+ screen->handleEvent (event);
+}
+
+X11LockerScreen::~X11LockerScreen ()
+{
+ LockerLockWindow::SetDefault (NULL);
+}
+
+X11LockerScreen::X11LockerScreen (CompScreen *s) :
+ PluginClassHandler <X11LockerScreen, CompScreen> (s)
+{
+ ScreenInterface::setHandler (s);
+
+ LockerAtoms::lockerStatus = XInternAtom (screen->dpy (),
+ X_LOCKER_PROPERTY_NAME, 0);
+ LockerAtoms::lockerBgStatus = XInternAtom (screen->dpy (),
+ X_LOCKER_BG_PROPERTY_NAME, 0);
+ LockerAtoms::lockerUnlock = XInternAtom (screen->dpy (),
+ X_LOCKER_UNLOCK_PROPERTY_NAME, 0);
+}
+
+X11LockerWindow::X11LockerWindow (CompWindow *w) :
+ PluginClassHandler <X11LockerWindow, CompWindow> (w),
+ window (w),
+ gWindow (GLWindow::get (w))
+{
+ X11LockWindow *xlw = dynamic_cast <X11LockWindow *> (LockerLockWindow::Default ());
+
+ if (xlw)
+ {
+ if (xlw->isBackingWindow (w->id ()))
+ xlw->completeBackingWindow (w);
+ }
+ else
+ {
+ /* No locker defined, maybe check to see if this is the one */
+ unsigned char *propData;
+ long *data;
+ Atom retType;
+ int retFmt;
+ unsigned long retItems, retLeft;
+
+ /* Read the _COMPIZ_NET_LOCKER_STATUS property on this window
+ * and then reparent this window into a window that we own and
+ * control */
+
+ int status = XGetWindowProperty (screen->dpy (), window->id (), XInternAtom (screen->dpy (), "_COMPIZ_NET_LOCKER_STATUS", 0), 0L, 4096L,
+ false, XA_CARDINAL, &retType,
+ &retFmt, &retItems, &retLeft, &propData);
+
+ if (status == Success)
+ {
+
+ if (retItems == 6 && retFmt == 32 && retLeft == 0)
+ {
+ xlw = new X11LockWindow (window->id ());
+ LockerLockWindow::SetDefault (xlw);
+ }
+ }
+ }
+}
+
+bool
+X11LockerPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI) ||
+ !CompPlugin::checkPluginABI ("locker", COMPIZ_LOCKER_ABI))
+ return false;
+
+ return true;
+}
+
+
diff --git a/src/xlocker.h b/src/xlocker.h
new file mode 100644
index 0000000..c810e1c
--- /dev/null
+++ b/src/xlocker.h
@@ -0,0 +1,139 @@
+/*
+ * Compiz x11 locker plugin
+ *
+ * xlocker.cpp
+ *
+ * Copyright (c) 2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <core/core.h>
+#include <locker/locker.h>
+
+#include <X11/Xatom.h>
+
+#include "xlocker_options.h"
+
+/*
+ * Definition of the _COMPIZ_NET_LOCKER_STATUS property:
+ *
+ * data[0] = API Version
+ * data[1] = Window ID of the locker window
+ * data[2] = X position of the locker window
+ * data[3] = Y position of the locker window
+ * data[4] = Width of the locker window
+ * data[5] = Height of the locker window
+ */
+
+#define X_LOCKER_PROPERTY_NAME "_COMPIZ_NET_LOCKER_STATUS"
+
+/*
+ * Definition of the _COMPIZ_NET_LOCKER_BACKGROUND property:
+ *
+ * data[0] = API Version
+ * data[1] = Window ID of the background window
+ * data[2] = X position of the background window
+ * data[3] = Y position of the background window
+ * data[4] = Width of the background window
+ * data[5] = Height of the background window
+ */
+
+#define X_LOCKER_BG_PROPERTY_NAME "_COMPIZ_NET_LOCKER_BACKGROUND_STATUS"
+
+/*
+ * Definition of the _COMPIZ_NET_LOCKER_UNLOCK property:
+ *
+ * data[0] = API Version
+ * data[1] = Window ID
+ * data[2] = Unlock cookie (hash value generated by
+ * a random number seed *
+ * timestamp of sent unlocker
+ * window creation)
+ */
+
+#define X_LOCKER_UNLOCK_PROPERTY_NAME "_COMPIZ_NET_LOCKER_UNLOCK"
+
+class X11LockWindow :
+ public LockerLockWindow
+{
+public:
+ X11LockWindow (Window child);
+ ~X11LockWindow ();
+
+ void hide ();
+ void show ();
+ bool visible ();
+ void paint (const GLMatrix &transform);
+
+ bool needsGrab () { return false; }
+ bool matched (Window, int &);
+ bool isBackingWindow (Window w) { return mBackingWindow == w; }
+ void completeBackingWindow (CompWindow *w);
+
+ bool isChildWindow (Window w) { return mChild == w; }
+ bool attemptUnlock (long *data);
+
+ void setGeometry (int x, int y, unsigned int width, unsigned int height);
+ void stackOffendingWindow (Window offender, XWindowChanges *xwc, unsigned int mask);
+
+ static bool processEvent (short int, Display *dpy);
+
+ CompRegion & damage () { return mDamageRegion; }
+
+private:
+
+ CompWindow *mCBackingWindow;
+ Window mBackingWindow;
+ Window mChild;
+ bool mMapped;
+ CompRect mGeometry;
+ CompRegion mDamageRegion;
+};
+
+class X11LockerScreen :
+ public PluginClassHandler <X11LockerScreen, CompScreen>,
+ public ScreenInterface,
+ public XlockerOptions
+{
+public:
+ X11LockerScreen (CompScreen *);
+ ~X11LockerScreen ();
+
+ /* We need to communicate with the thing doing
+ * the locking */
+ void handleEvent (XEvent *);
+};
+
+class X11LockerWindow :
+ public PluginClassHandler <X11LockerWindow, CompWindow>,
+ public WindowInterface,
+ public GLWindowInterface
+{
+public:
+ X11LockerWindow (CompWindow *w);
+
+ CompWindow *window;
+ GLWindow *gWindow;
+
+private:
+
+ bool mExternalPaint;
+};
+
+class X11LockerPluginVTable :
+ public CompPlugin::VTableForScreenAndWindow <X11LockerScreen, X11LockerWindow>
+{
+public:
+
+ bool init ();
+};
diff --git a/xlocker.xml.in b/xlocker.xml.in
new file mode 100644
index 0000000..cf6bd15
--- /dev/null
+++ b/xlocker.xml.in
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<compiz>
+ <plugin name="xlocker" useBcop="true">
+ <_short>X11 Locker</_short>
+ <_long>X11 Window Based Locker</_long>
+ <category>Utility</category>
+ <options>
+ </options>
+ </plugin>
+</compiz>