summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2011-07-19 14:50:04 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2011-07-19 14:50:04 +0200
commit227cf56f443d1ce45fce2e13a4daf442a29bc862 (patch)
tree0d53ff45098d54e49099aa45afc992ffc4c0fd63
parentbc9f8e1fbc7e117ec5368d2d74742cdb2c5f22f7 (diff)
downloadphi-227cf56f443d1ce45fce2e13a4daf442a29bc862.tar
phi-227cf56f443d1ce45fce2e13a4daf442a29bc862.zip
Add native error handler for systray
-rw-r--r--csrc/SystrayErrorHandler.c27
-rw-r--r--include/SystrayErrorHandler.h11
-rw-r--r--lib/Phi/Bindings/SystrayErrorHandler.hsc17
-rw-r--r--lib/Phi/Widgets/Systray.hs38
-rw-r--r--lib/Phi/X11.hs2
-rw-r--r--phi.cabal4
6 files changed, 73 insertions, 26 deletions
diff --git a/csrc/SystrayErrorHandler.c b/csrc/SystrayErrorHandler.c
new file mode 100644
index 0000000..29e7fa1
--- /dev/null
+++ b/csrc/SystrayErrorHandler.c
@@ -0,0 +1,27 @@
+#include <SystrayErrorHandler.h>
+
+
+static Window lastErrorWindow = 0;
+
+
+static int systrayErrorHandler (Display *display, XErrorEvent *event)
+{
+ if (event->error_code == BadWindow) {
+ lastErrorWindow = event->resourceid;
+ }
+
+ return 0;
+}
+
+void setSystrayErrorHandler (void)
+{
+ lastErrorWindow = 0;
+ XSetErrorHandler(systrayErrorHandler);
+}
+
+Window getLastErrorWindow (void)
+{
+ Window ret = lastErrorWindow;
+ lastErrorWindow = 0;
+ return ret;
+}
diff --git a/include/SystrayErrorHandler.h b/include/SystrayErrorHandler.h
new file mode 100644
index 0000000..3850655
--- /dev/null
+++ b/include/SystrayErrorHandler.h
@@ -0,0 +1,11 @@
+#ifndef _PHI_SYSTRAYERRORHANDLER_H_
+#define _PHI_SYSTRAYERRORHANDLER_H_
+
+#include <X11/Xlib.h>
+
+
+void setSystrayErrorHandler (void);
+
+Window getLastErrorWindow (void);
+
+#endif /* _PHI_SYSTRAYERRORHANDLER_H_ */
diff --git a/lib/Phi/Bindings/SystrayErrorHandler.hsc b/lib/Phi/Bindings/SystrayErrorHandler.hsc
new file mode 100644
index 0000000..73fedbb
--- /dev/null
+++ b/lib/Phi/Bindings/SystrayErrorHandler.hsc
@@ -0,0 +1,17 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Phi.Bindings.SystrayErrorHandler ( setSystrayErrorHandler
+ , getLastErrorWindow
+ ) where
+
+#include <SystrayErrorHandler.h>
+
+
+import Graphics.X11.Xlib
+
+
+foreign import ccall unsafe "SystrayErrorHandler.h setSystrayErrorHandler"
+ setSystrayErrorHandler :: IO ()
+
+foreign import ccall unsafe "SystrayErrorHandler.h getLastErrorWindow"
+ getLastErrorWindow :: IO Window
diff --git a/lib/Phi/Widgets/Systray.hs b/lib/Phi/Widgets/Systray.hs
index 0d14f0e..2f8de56 100644
--- a/lib/Phi/Widgets/Systray.hs
+++ b/lib/Phi/Widgets/Systray.hs
@@ -24,6 +24,7 @@ import qualified Graphics.X11.Xlib as Xlib
import Graphics.X11.Xlib.Extras
import Phi.Bindings.Util
+import Phi.Bindings.SystrayErrorHandler
import Phi.Phi
import Phi.Types
@@ -103,16 +104,10 @@ systrayRunner phi dispvar = do
_ ->
case (fromMessage m) of
Just (RenderIcon midParent window x y w h reset) -> do
- errorWindowRef <- liftIO $ newIORef []
-
withDisplay dispvar $ \disp -> do
liftIO $ flip catch (\_ -> return ()) $ do
sync disp False
- setErrorHandler $ \disp eventptr -> do
- event <- getErrorEvent eventptr
- when (ev_error_code event == fromIntegral badWindow) $ do
- errorWindows <- readIORef errorWindowRef
- writeIORef errorWindowRef (ev_resourceid event:errorWindows)
+ setSystrayErrorHandler
(_, x', y', w', h', _, _) <- getGeometry disp midParent
(_, _, _, w'', h'', _, _) <- getGeometry disp window
@@ -124,14 +119,15 @@ systrayRunner phi dispvar = do
resizeWindow disp window (fromIntegral w) (fromIntegral h)
sync disp False
- when (resize || reset) $ do
- clearArea disp window 0 0 (fromIntegral w) (fromIntegral h) True
- sync disp False
-
+ clearArea disp window 0 0 (fromIntegral w) (fromIntegral h) True
+
+ sync disp False
xSetErrorHandler
- errorWindows <- liftIO $ readIORef errorWindowRef
- mapM_ (removeIcon phi disp) errorWindows
+ lastErrorWindow <- liftIO $ getLastErrorWindow
+ when (lastErrorWindow == window) $ do
+ liftIO $ print window
+ removeIcon phi disp window
_ ->
case (fromMessage m) of
Just Shutdown -> do
@@ -234,24 +230,18 @@ addIcon :: Phi -> Xlib.Display -> Atoms -> Window -> Window -> StateT (M.Map Win
addIcon phi disp atoms panelWindow window = do
liftIO $ selectInput disp window $ structureNotifyMask .|. propertyChangeMask
- errorRef <- liftIO $ newIORef False
midParent <- liftIO $ createSimpleWindow disp panelWindow (-16) (-16) 16 16 0 0 0
liftIO $ do
setWindowBackgroundPixmap disp midParent 1 -- ParentRelative
sync disp False
- setErrorHandler $ \disp eventptr -> do
- event <- getErrorEvent eventptr
- when (ev_error_code event == fromIntegral badWindow && ev_resourceid event == window) $
- writeIORef errorRef True
+ setSystrayErrorHandler
reparentWindow disp window midParent 0 0
- sync disp False
mapRaised disp midParent
mapWindow disp window
- sync disp False
allocaXEvent $ \event -> do
putClientMessage event window (atom_XEMBED atoms) [fromIntegral currentTime, fromIntegral xEMBED_EMBEDDED_NOTIFY, 0, fromIntegral midParent, 0]
@@ -260,13 +250,13 @@ addIcon phi disp atoms panelWindow window = do
sync disp False
xSetErrorHandler
- error <- liftIO $ readIORef errorRef
- case error of
- False -> do
+ errorWindow <- liftIO $ getLastErrorWindow
+ case True of
+ _ | errorWindow /= window -> do
sendMessage phi $ AddIcon midParent window
sendMessage phi Repaint
modify $ M.insert window midParent
- True ->
+ | otherwise ->
liftIO $ destroyWindow disp midParent
diff --git a/lib/Phi/X11.hs b/lib/Phi/X11.hs
index 9bd5cd4..f0cf62c 100644
--- a/lib/Phi/X11.hs
+++ b/lib/Phi/X11.hs
@@ -223,7 +223,6 @@ updatePanels dispvar = do
-- copy buffer to window
liftIO $ do
- setWindowBackgroundPixmap disp (panelWindow panel') pixmap
(withDimension area $ clearArea disp (panelWindow panel') 0 0) True
sync disp False
@@ -282,6 +281,7 @@ createPanel disp win widgets screenRect = do
depth = defaultDepth disp screen
pixmap <- liftIO $ (withDimension rect $ createPixmap disp win) depth
+ liftIO $ setWindowBackgroundPixmap disp win pixmap
return PanelState { panelWindow = win
, panelPixmap = pixmap
diff --git a/phi.cabal b/phi.cabal
index d5b59c8..98da9e3 100644
--- a/phi.cabal
+++ b/phi.cabal
@@ -14,7 +14,9 @@ library
build-depends: base >= 4, template-haskell, stm, array, containers, transformers, mtl, utf8-string, time, old-locale, X11, cairo, pango, unix
exposed-modules: Phi.Types, Phi.Phi, Phi.Panel, Phi.Widget, Phi.Border, Phi.X11,
Phi.Widgets.AlphaBox, Phi.Widgets.Clock, Phi.Widgets.Taskbar, Phi.Widgets.Systray
- other-modules: Phi.X11.Atoms, Phi.X11.AtomList, Phi.Bindings.Util
+ other-modules: Phi.X11.Atoms, Phi.X11.AtomList, Phi.Bindings.Util, Phi.Bindings.SystrayErrorHandler
+ c-sources: csrc/SystrayErrorHandler.c
+ include-dirs: include
hs-source-dirs: lib
extra-libraries: X11
pkgconfig-depends: cairo >= 1.2.0, cairo-xlib