diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f83404d..01289c67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,8 +24,8 @@ jobs: include: # The windows build is currently broken # See #135 - #- os: windows-latest - # ghc-version: '9.10' + - os: windows-latest + ghc-version: '9.10' - os: macos-latest ghc-version: '9.10' # gtk2hs is broken under apline @@ -48,28 +48,41 @@ jobs: zlib-dev zlib-static binutils curl \ gcc g++ gmp-dev libc-dev libffi-dev make \ musl-dev ncurses-dev perl tar xz \ - gtk+2.0-dev + gtk+3.0-dev - name: Install system dependencies (Ubuntu) if: runner.os == 'Linux' && !startsWith(matrix.container, 'alpine') - run: sudo apt-get update && sudo apt-get install libgtk2.0-dev + run: sudo apt-get update && sudo apt-get install libgtk-3-dev - name: Install system dependencies (macOS) if: runner.os == 'macOS' - run: brew install cairo gtk+ pkg-config + run: brew install cairo gtk+3 pkg-config - name: Set extra cabal build options (macOS) if: runner.os == 'macOS' run: | printf 'package gtk\n flags: +have-quartz-gtk' >>cabal.project - - name: Set up GHC ${{ matrix.ghc-version }} uses: haskell-actions/setup@v2 id: setup with: ghc-version: ${{ matrix.ghc-version }} + # Taken from https://github.com/agda/agda/blob/8210048a50c35d8d6fd0ae7e5edd1699592fda6f/src/github/workflows/cabal.yml#L113C1-L124C85 + # See: https://github.com/haskell/text-icu/pull/86 + # pacman needs MSYS /usr/bin in PATH, but this breaks the latest cache action. + # - https://github.com/actions/cache/issues/1073 + # MSYS' pkg-config needs MSYS /mingw64/bin which we can safely add to the PATH + # + - name: Install system dependencies (Windows) + if: ${{ startsWith(matrix.os, 'windows') }} + shell: pwsh + run: | + $env:PATH = "C:\msys64\usr\bin;$env:PATH" + pacman --noconfirm -S msys2-keyring mingw-w64-x86_64-pkgconf mingw-w64-x86_64-gtk3 + echo "C:\msys64\mingw64\bin" | Out-File -FilePath "$env:GITHUB_PATH" -Append + - name: Enable static build (only on alpine) if: ${{ startsWith(matrix.container, 'alpine') }} run: | @@ -106,15 +119,6 @@ jobs: path: ${{ steps.setup.outputs.cabal-store }} key: ${{ steps.cache.outputs.cache-primary-key }} - - name: Install system dependencies (Windows) - if: ${{ startsWith(matrix.os, 'windows') }} - uses: msys2/setup-msys2@v2 - with: - path-type: inherit - install: >- - mingw-w64-x86_64-pkg-config - mingw-w64-x86_64-gtk2 - - name: Build run: cabal build all diff --git a/GUI/BookmarkView.hs b/GUI/BookmarkView.hs index 6e21e5e7..42d36431 100644 --- a/GUI/BookmarkView.hs +++ b/GUI/BookmarkView.hs @@ -117,7 +117,7 @@ bookmarkViewNew builder BookmarkViewActions{..} = do (ts,_) <- listStoreGetValue bookmarkStore pos bookmarkViewGotoBookmark ts - onRowActivated bookmarkTreeView $ \[pos] _ -> do + bookmarkTreeView `on` rowActivated $ \[pos] _ -> do (ts, _) <- listStoreGetValue bookmarkStore pos bookmarkViewGotoBookmark ts diff --git a/GUI/Dialogs.hs b/GUI/Dialogs.hs index 395bc735..7043f7ce 100644 --- a/GUI/Dialogs.hs +++ b/GUI/Dialogs.hs @@ -8,6 +8,7 @@ import Graphics.UI.Gtk import Data.Version (showVersion) import System.FilePath +import Control.Monad.Trans ------------------------------------------------------------------------------- @@ -32,7 +33,7 @@ aboutDialog parent aboutDialogWebsite := "http://www.haskell.org/haskellwiki/ThreadScope", windowTransientFor := toWindow parent ] - onResponse dialog $ \_ -> widgetDestroy dialog + dialog `on` response $ \_ -> widgetDestroy dialog widgetShow dialog ------------------------------------------------------------------------------- @@ -59,7 +60,7 @@ openFileDialog parent open fileFilterAddPattern allfiles "*" fileChooserAddFilter dialog allfiles - onResponse dialog $ \response -> do + dialog `on` response $ \response -> do case response of ResponseAccept -> do mfile <- fileChooserGetFilename dialog @@ -105,7 +106,7 @@ exportFileDialog parent oldfile save = do fileFilterAddPattern pdfFiles "*.pdf" fileChooserAddFilter dialog pdfFiles - onResponse dialog $ \response -> + dialog `on` response $ \response -> case response of ResponseAccept -> do mfile <- fileChooserGetFilename dialog @@ -158,5 +159,5 @@ errorMessageDialog parent headline explanation = do dialogAddButton dialog "Close" ResponseClose dialogSetDefaultResponse dialog ResponseClose - onResponse dialog $ \_-> widgetDestroy dialog + dialog `on` response $ \_-> widgetDestroy dialog widgetShowAll dialog diff --git a/GUI/EventsView.hs b/GUI/EventsView.hs index 74d56d9e..c01236c5 100644 --- a/GUI/EventsView.hs +++ b/GUI/EventsView.hs @@ -13,8 +13,10 @@ module GUI.EventsView ( ) where import GHC.RTS.Events +import Debug.Trace -import Graphics.UI.Gtk +import Graphics.UI.Gtk hiding (rectangle) +import Graphics.Rendering.Cairo import qualified GUI.GtkExtras as GtkExt import Control.Monad @@ -100,9 +102,9 @@ eventsViewNew builder EventsViewActions{..} = do ----------------------------------------------------------------------------- -- Drawing - on drawArea exposeEvent $ liftIO $ do + on drawArea draw $ liftIO $ do drawEvents eventsView =<< readIORef stateRef - return True + return () ----------------------------------------------------------------------------- -- Key navigation @@ -122,7 +124,7 @@ eventsViewNew builder EventsViewActions{..} = do return True key <- eventKeyName -#if MIN_VERSION_gtk(0,13,0) +#if MIN_VERSION_gtk3(0,13,0) case T.unpack key of #else case key of @@ -239,7 +241,7 @@ updateScrollAdjustment :: EventsView -> ViewState -> IO () updateScrollAdjustment EventsView{drawArea, adj} ViewState{lineHeight, eventsState} = do - (_,windowHeight) <- widgetGetSize drawArea + Rectangle _ _ _ windowHeight <- widgetGetAllocation drawArea let numLines = case eventsState of EventsEmpty -> 0 EventsLoaded{eventsArr} -> snd (bounds eventsArr) + 1 @@ -276,9 +278,10 @@ drawEvents EventsView{drawArea, adj} begin = lower end = min upper (snd (bounds eventsArr)) - win <- widgetGetDrawWindow drawArea - style <- get drawArea widgetStyle - focused <- get drawArea widgetIsFocus + -- TODO: don't use Just here + Just win <- widgetGetWindow drawArea + style <- widgetGetStyle drawArea + focused <- widgetGetIsFocus drawArea let state | focused = StateSelected | otherwise = StateActive @@ -286,8 +289,9 @@ drawEvents EventsView{drawArea, adj} layout <- layoutEmpty pangoCtx layoutSetEllipsize layout EllipsizeEnd - (width,clipHeight) <- widgetGetSize drawArea - let clipRect = Rectangle 0 0 width clipHeight + + (Rectangle _ _ width _) <- widgetGetAllocation drawArea + let clipRect = Rectangle 0 0 0 0 let -- With average char width, timeWidth is enough for 24 hours of logs -- (way more than TS can handle, currently). Aligns nicely with @@ -301,36 +305,27 @@ drawEvents EventsView{drawArea, adj} sequence_ [ do when (inside || selected) $ - GtkExt.stylePaintFlatBox - style win - state1 ShadowNone - clipRect - drawArea "" - 0 (round y) width (round lineHeight) + renderWithDrawWindow win $ do + -- TODO: figure out how I can grab the correct color from GTK's style + setSourceRGBA 0.2 1 1 0.2 + rectangle 0 y (fromIntegral width) lineHeight + fill -- The event time layoutSetText layout (showEventTime event) layoutSetAlignment layout AlignRight layoutSetWidth layout (Just (fromIntegral timeWidth)) - GtkExt.stylePaintLayout - style win - state2 True - clipRect - drawArea "" - 0 (round y) - layout + renderWithDrawWindow win $ do + moveTo 0 y + showLayout layout -- The event description text layoutSetText layout (showEventDescr event) layoutSetAlignment layout AlignLeft layoutSetWidth layout (Just (fromIntegral descrWidth)) - GtkExt.stylePaintLayout - style win - state2 True - clipRect - drawArea "" - (timeWidth + columnGap) (round y) - layout + renderWithDrawWindow win $ do + moveTo (fromIntegral $ timeWidth + columnGap) y + showLayout layout | n <- [begin..end] , let y = fromIntegral n * lineHeight - yOffset diff --git a/GUI/GtkExtras.hs b/GUI/GtkExtras.hs index 880df46e..a18169f1 100644 --- a/GUI/GtkExtras.hs +++ b/GUI/GtkExtras.hs @@ -30,58 +30,6 @@ waitGUI = do ------------------------------------------------------------------------------- -stylePaintFlatBox :: WidgetClass widget - => Style - -> DrawWindow - -> StateType - -> ShadowType - -> Rectangle - -> widget - -> String - -> Int -> Int -> Int -> Int - -> IO () -stylePaintFlatBox style window stateType shadowType - clipRect widget detail x y width height = - with clipRect $ \rectPtr -> - withCString detail $ \detailPtr -> - (\(Style arg1) (DrawWindow arg2) arg3 arg4 arg5 (Widget arg6) arg7 arg8 arg9 arg10 arg11 -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->withForeignPtr arg6 $ \argPtr6 -> gtk_paint_flat_box argPtr1 argPtr2 arg3 arg4 arg5 argPtr6 arg7 arg8 arg9 arg10 arg11) - style - window - ((fromIntegral.fromEnum) stateType) - ((fromIntegral.fromEnum) shadowType) - (castPtr rectPtr) - (toWidget widget) - detailPtr - (fromIntegral x) (fromIntegral y) - (fromIntegral width) (fromIntegral height) - -stylePaintLayout :: WidgetClass widget - => Style - -> DrawWindow - -> StateType - -> Bool - -> Rectangle - -> widget - -> String - -> Int -> Int - -> PangoLayout - -> IO () -stylePaintLayout style window stateType useText - clipRect widget detail x y (PangoLayout _ layout) = - with clipRect $ \rectPtr -> - withCString detail $ \detailPtr -> - (\(Style arg1) (DrawWindow arg2) arg3 arg4 arg5 (Widget arg6) arg7 arg8 arg9 (PangoLayoutRaw arg10) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->withForeignPtr arg6 $ \argPtr6 ->withForeignPtr arg10 $ \argPtr10 -> gtk_paint_layout argPtr1 argPtr2 arg3 arg4 arg5 argPtr6 arg7 arg8 arg9 argPtr10) - style - window - ((fromIntegral.fromEnum) stateType) - (fromBool useText) - (castPtr rectPtr) - (toWidget widget) - detailPtr - (fromIntegral x) (fromIntegral y) - layout - - launchProgramForURI :: String -> IO Bool #if mingw32_HOST_OS || mingw32_TARGET_OS launchProgramForURI uri = do @@ -115,12 +63,6 @@ launchProgramForURI uri = ------------------------------------------------------------------------------- -foreign import ccall safe "gtk_paint_flat_box" - gtk_paint_flat_box :: Ptr Style -> Ptr DrawWindow -> CInt -> CInt -> Ptr () -> Ptr Widget -> Ptr CChar -> CInt -> CInt -> CInt -> CInt -> IO () - -foreign import ccall safe "gtk_paint_layout" - gtk_paint_layout :: Ptr Style -> Ptr DrawWindow -> CInt -> CInt -> Ptr () -> Ptr Widget -> Ptr CChar -> CInt -> CInt -> Ptr PangoLayoutRaw -> IO () - foreign import ccall safe "gtk_show_uri" gtk_show_uri :: Ptr Screen -> Ptr CChar -> CUInt -> Ptr (Ptr ()) -> IO CInt diff --git a/GUI/Histogram.hs b/GUI/Histogram.hs index 6aaaa6c8..73d983ef 100644 --- a/GUI/Histogram.hs +++ b/GUI/Histogram.hs @@ -16,6 +16,7 @@ import Graphics.UI.Gtk import qualified GUI.GtkExtras as GtkExt import Data.IORef +import Control.Monad.Trans data HistogramView = HistogramView @@ -51,7 +52,7 @@ histogramViewNew builder = do fontDescriptionSetFamily fd "sans serif" widgetModifyFont histogramYScaleArea (Just fd) - (_, xh) <- widgetGetSize timelineXScaleArea + Rectangle _ _ _ xh <- widgetGetAllocation timelineXScaleArea let xScaleAreaHeight = fromIntegral xh traces = [TraceHistogram] paramsHist (w, h) minterval = ViewParameters @@ -80,53 +81,51 @@ histogramViewNew builder = do ++ "Re-run with +RTS -lf to generate them." -- Program the callback for the capability drawingArea - on histogramDrawingArea exposeEvent $ + on histogramDrawingArea draw $ C.liftIO $ do maybeEventArray <- readIORef hecsIORef - win <- widgetGetDrawWindow histogramDrawingArea - (w, windowHeight) <- widgetGetSize histogramDrawingArea + -- TODO: get rid of Just + Just win <- widgetGetWindow histogramDrawingArea + Rectangle _ _ w windowHeight <- widgetGetAllocation histogramDrawingArea case maybeEventArray of - Nothing -> return False + Nothing -> return () Just hecs | null (durHistogram hecs) -> do - GtkExt.stylePaintLayout - style win - StateNormal True - (Rectangle 0 0 w windowHeight) - histogramDrawingArea "" - 4 20 - layout - return True + renderWithDrawWindow win $ do + C.moveTo 4 20 + showLayout layout + return () | otherwise -> do minterval <- readIORef mintervalIORef if windowHeight < 80 - then return False + then return () else do let size = (w, windowHeight - firstTraceY) params = paramsHist size minterval rect = Rectangle 0 0 w (snd size) - renderWithDrawable win $ + renderWithDrawWindow win $ renderTraces params hecs rect - return True + return () -- Redrawing histogramYScaleArea - histogramYScaleArea `onExpose` \_ -> do + histogramYScaleArea `on` draw $ liftIO $ do maybeEventArray <- readIORef hecsIORef case maybeEventArray of - Nothing -> return False + Nothing -> return () Just hecs - | null (durHistogram hecs) -> return False + | null (durHistogram hecs) -> return () | otherwise -> do - win <- widgetGetDrawWindow histogramYScaleArea + -- TODO: get rid of Just + Just win <- widgetGetWindow histogramYScaleArea minterval <- readIORef mintervalIORef - (_, windowHeight) <- widgetGetSize histogramYScaleArea + Rectangle _ _ _ windowHeight <- widgetGetAllocation histogramYScaleArea if windowHeight < 80 - then return False + then return () else do let size = (undefined, windowHeight - firstTraceY) params = paramsHist size minterval - renderWithDrawable win $ + renderWithDrawWindow win $ renderYScaleArea params hecs histogramYScaleArea - return True + return () return HistogramView{..} diff --git a/GUI/KeyView.hs b/GUI/KeyView.hs index a64063ef..1c365630 100644 --- a/GUI/KeyView.hs +++ b/GUI/KeyView.hs @@ -24,7 +24,8 @@ keyViewNew builder = do keyTreeView <- builderGetObject builder castToTreeView "key_list" - dw <- widgetGetDrawWindow keyTreeView + -- TODO: get rid of this Just + Just dw <- widgetGetWindow keyTreeView keyEntries <- createKeyEntries dw keyData keyStore <- listStoreNew keyEntries @@ -113,7 +114,7 @@ keyData = ] -createKeyEntries :: DrawableClass dw +createKeyEntries :: DrawWindowClass dw => dw -> [(String, KeyStyle, Color,String)] -> IO [(String, String, Pixbuf)] @@ -165,12 +166,11 @@ renderKEvent keyColour = do C.relLineTo 0 25 C.stroke -renderToPixbuf :: DrawableClass dw => dw -> (Int, Int) -> C.Render () +renderToPixbuf :: DrawWindowClass dw => dw -> (Int, Int) -> C.Render () -> IO Pixbuf renderToPixbuf similar (w, h) draw = do - pixmap <- pixmapNew (Just similar) w h Nothing - renderWithDrawable pixmap draw - Just pixbuf <- pixbufGetFromDrawable pixmap (Rectangle 0 0 w h) + renderWithDrawWindow similar draw + pixbuf <- pixbufNewFromWindow similar 0 0 w h return pixbuf ------------------------------------------------------------------------------- diff --git a/GUI/MainWindow.hs b/GUI/MainWindow.hs index 19122c38..7c9c6983 100644 --- a/GUI/MainWindow.hs +++ b/GUI/MainWindow.hs @@ -32,7 +32,6 @@ instance Glib.GObjectClass MainWindow where toGObject = toGObject . mainWindow unsafeCastGObject = error "cannot downcast to MainView type" -instance Gtk.ObjectClass MainWindow instance Gtk.WidgetClass MainWindow instance Gtk.ContainerClass MainWindow instance Gtk.BinClass MainWindow diff --git a/GUI/ProgressView.hs b/GUI/ProgressView.hs index a83a27b0..db9dda8f 100644 --- a/GUI/ProgressView.hs +++ b/GUI/ProgressView.hs @@ -16,6 +16,7 @@ import GUI.GtkExtras import qualified Control.Concurrent as Concurrent import Control.Exception import Data.Typeable +import Control.Monad.Trans data ProgressView = ProgressView { progressWindow :: Gtk.Window, @@ -95,8 +96,8 @@ new parent cancelAction = do progress <- progressBarNew cancel <- buttonNewFromStock stockCancel - onClicked cancel (widgetDestroy win >> cancelAction) - onDelete win (\_ -> cancelAction >> return True) + cancel `on` buttonActivated $ (widgetDestroy win >> cancelAction) + win `on` destroyEvent $ lift cancelAction >> return True on win keyPressEvent $ do keyVal <- eventKeyVal case keyVal of diff --git a/GUI/SaveAs.hs b/GUI/SaveAs.hs index a576b5d7..112f01f6 100644 --- a/GUI/SaveAs.hs +++ b/GUI/SaveAs.hs @@ -62,14 +62,14 @@ saveAs hecs params'@ViewParameters{xScaleAreaHeight, width, saveAsPDF :: FilePath -> HECs -> ViewParameters -> DrawingArea -> IO () saveAsPDF filename hecs params yScaleArea = do - (xoffset, _) <- liftIO $ widgetGetSize yScaleArea + Rectangle _ _ xoffset _ <- liftIO $ widgetGetAllocation yScaleArea let (w', h', drawAll) = saveAs hecs params (fromIntegral xoffset) yScaleArea withPDFSurface filename (fromIntegral w') (fromIntegral h') $ \surface -> renderWith surface drawAll saveAsPNG :: FilePath -> HECs -> ViewParameters -> DrawingArea -> IO () saveAsPNG filename hecs params yScaleArea = do - (xoffset, _) <- liftIO $ widgetGetSize yScaleArea + Rectangle _ _ xoffset _ <- liftIO $ widgetGetAllocation yScaleArea let (w', h', drawAll) = saveAs hecs params (fromIntegral xoffset) yScaleArea withImageSurface FormatARGB32 w' h' $ \surface -> do renderWith surface drawAll diff --git a/GUI/Timeline.hs b/GUI/Timeline.hs index 24302f73..d449977f 100644 --- a/GUI/Timeline.hs +++ b/GUI/Timeline.hs @@ -38,6 +38,7 @@ import Graphics.Rendering.Cairo ( liftIO ) import Data.IORef import Control.Monad +import Control.Monad.Trans import qualified Data.Text as T ----------------------------------------------------------------------------- @@ -78,7 +79,7 @@ timelineGetViewParameters :: TimelineView -> IO ViewParameters timelineGetViewParameters TimelineView{tracesIORef, bwmodeIORef, labelsModeIORef, timelineState=TimelineState{..}} = do - (w, _) <- widgetGetSize timelineDrawingArea + Rectangle _ _ w _ <- widgetGetAllocation timelineDrawingArea scaleValue <- readIORef scaleIORef maxSpkValue <- readIORef maxSpkIORef @@ -90,7 +91,7 @@ timelineGetViewParameters TimelineView{tracesIORef, bwmodeIORef, labelsModeIORef bwmode <- readIORef bwmodeIORef labelsMode <- readIORef labelsModeIORef - (_, xScaleAreaHeight) <- widgetGetSize timelineXScaleArea + Rectangle _ _ _ xScaleAreaHeight <- widgetGetAllocation timelineXScaleArea let histTotalHeight = stdHistogramHeight + histXScaleHeight timelineHeight = calculateTotalTimelineHeight labelsMode histTotalHeight traces @@ -169,32 +170,32 @@ timelineViewNew builder actions = do ------------------------------------------------------------------------ -- Redrawing labelDrawingArea - timelineYScaleArea `onExpose` \_ -> do + timelineYScaleArea `on` draw $ liftIO $ do maybeEventArray <- readIORef hecsIORef -- Check to see if an event trace has been loaded case maybeEventArray of - Nothing -> return False + Nothing -> return () Just hecs -> do traces <- readIORef tracesIORef labelsMode <- readIORef labelsModeIORef let maxP = maxSparkPool hecs maxH = fromIntegral (maxYHistogram hecs) updateYScaleArea timelineState maxP maxH Nothing labelsMode traces - return True + return () ------------------------------------------------------------------------ -- Redrawing XScaleArea - timelineXScaleArea `onExpose` \_ -> do + timelineXScaleArea `on` draw $ liftIO $ do maybeEventArray <- readIORef hecsIORef -- Check to see if an event trace has been loaded case maybeEventArray of - Nothing -> return False + Nothing -> return () Just hecs -> do let lastTx = hecLastEventTime hecs updateXScaleArea timelineState lastTx - return True + return () ------------------------------------------------------------------------ -- Allow mouse wheel to be used for zoom in/out @@ -253,7 +254,7 @@ timelineViewNew builder actions = do in withMouseState whenNoMouse >> return True keyName <- eventKeyName keyVal <- eventKeyVal -#if MIN_VERSION_gtk(0,13,0) +#if MIN_VERSION_gtk3(0,13,0) case (T.unpack keyName, keyToChar keyVal, keyVal) of #else case (keyName, keyToChar keyVal, keyVal) of @@ -277,8 +278,7 @@ timelineViewNew builder actions = do ------------------------------------------------------------------------ -- Redrawing - on timelineDrawingArea exposeEvent $ do - exposeRegion <- eventRegion + on timelineDrawingArea draw $ do liftIO $ do maybeEventArray <- readIORef hecsIORef @@ -290,14 +290,14 @@ timelineViewNew builder actions = do -- render either the whole height of the timeline, or the window, whichever -- is larger (this just ensure we fill the background if the timeline is -- smaller than the window). - (_, h) <- widgetGetSize timelineDrawingArea + (Rectangle _ _ w h)<- widgetGetAllocation timelineDrawingArea let params' = params { height = max (height params) h } selection <- readIORef selectionRef bookmarks <- readIORef bookmarkIORef - renderView timelineState params' hecs selection bookmarks exposeRegion + renderView timelineState params' hecs selection bookmarks (Rectangle 0 0 w h) - return True + return () on timelineDrawingArea configureEvent $ do liftIO $ configureTimelineDrawingArea timelineWin @@ -357,7 +357,7 @@ updateTimelineVScroll TimelineView{tracesIORef, labelsModeIORef, timelineState=T labelsMode <- readIORef labelsModeIORef let histTotalHeight = stdHistogramHeight + histXScaleHeight h = calculateTotalTimelineHeight labelsMode histTotalHeight traces - (_,winh) <- widgetGetSize timelineDrawingArea + Rectangle _ _ _ winh <- widgetGetAllocation timelineDrawingArea let winh' = fromIntegral winh; h' = fromIntegral h adjustmentSetLower timelineVAdj 0 @@ -377,7 +377,7 @@ updateTimelineVScroll TimelineView{tracesIORef, labelsModeIORef, timelineState=T -- the view at all. updateTimelineHPageSize :: TimelineState -> IO () updateTimelineHPageSize TimelineState{..} = do - (winw,_) <- widgetGetSize timelineDrawingArea + Rectangle _ _ winw _ <- widgetGetAllocation timelineDrawingArea scaleValue <- readIORef scaleIORef adjustmentSetPageSize timelineAdj (fromIntegral winw * scaleValue) @@ -467,8 +467,9 @@ mouseRelease view@TimelineView{..} TimelineViewActions{..} state button x = widgetSetCursor :: WidgetClass widget => widget -> Maybe Cursor -> IO () widgetSetCursor widget cursor = do -#if MIN_VERSION_gtk(0,12,1) - dw <- widgetGetDrawWindow widget +#if MIN_VERSION_gtk3(0,12,1) + -- TODO: get rid of this Just + Just dw <- widgetGetWindow widget drawWindowSetCursor dw cursor #endif return () diff --git a/GUI/Timeline/Motion.hs b/GUI/Timeline/Motion.hs index 4aafb37c..ce90e1ec 100644 --- a/GUI/Timeline/Motion.hs +++ b/GUI/Timeline/Motion.hs @@ -68,7 +68,7 @@ zoomToFit TimelineState{scaleIORef, maxSpkIORef,timelineAdj, let lastTx = hecLastEventTime hecs upper = fromIntegral lastTx lower = 0 - (w, _) <- widgetGetSize timelineDrawingArea + Rectangle _ _ w _ <- widgetGetAllocation timelineDrawingArea let newScaleValue = upper / fromIntegral w (sliceAll, profAll) = treesProfile newScaleValue 0 lastTx hecs -- TODO: verify that no empty lists possible below diff --git a/GUI/Timeline/Render.hs b/GUI/Timeline/Render.hs index 546b93f3..6edde7aa 100644 --- a/GUI/Timeline/Render.hs +++ b/GUI/Timeline/Render.hs @@ -53,6 +53,8 @@ import Data.IORef import Control.Monad import qualified Data.Text as T +import qualified Graphics.UI.Gtk.Cairo as C + ------------------------------------------------------------------------------- -- | This function redraws the currently visible part of the @@ -61,20 +63,19 @@ import qualified Data.Text as T renderView :: TimelineState -> ViewParameters -> HECs -> TimeSelection -> [Timestamp] - -> Region -> IO () + -> Rectangle -> IO () renderView TimelineState{timelineDrawingArea, timelineVAdj, timelinePrevView} - params hecs selection bookmarks exposeRegion = do + params hecs selection bookmarks rect = do -- Get state information from user-interface components - (w, _) <- widgetGetSize timelineDrawingArea + Rectangle _ _ w _ <- widgetGetAllocation timelineDrawingArea vadj_value <- adjustmentGetValue timelineVAdj prev_view <- readIORef timelinePrevView - rect <- regionGetClipbox exposeRegion - - win <- widgetGetDrawWindow timelineDrawingArea - renderWithDrawable win $ do + -- TODO: get rid of this Just + Just win <- widgetGetWindow timelineDrawingArea + renderWithDrawWindow win $ do let renderToNewSurface = do new_surface <- withTargetSurface $ \surface -> @@ -113,7 +114,7 @@ renderView TimelineState{timelineDrawingArea, timelineVAdj, timelinePrevView} liftIO $ writeIORef timelinePrevView (Just (params, surface)) - region exposeRegion + C.rectangle rect clip setSourceSurface surface 0 (-vadj_value) -- ^^ this is where we adjust for the vertical scrollbar @@ -319,15 +320,16 @@ scrollView surface old new hecs = do -- and not only the newly exposed area. This is comparatively very cheap. updateXScaleArea :: TimelineState -> Timestamp -> IO () updateXScaleArea TimelineState{..} lastTx = do - win <- widgetGetDrawWindow timelineXScaleArea - (width, _) <- widgetGetSize timelineDrawingArea - (_, xScaleAreaHeight) <- widgetGetSize timelineXScaleArea + -- TODO: get rid of this Just + Just win <- widgetGetWindow timelineXScaleArea + Rectangle _ _ width _ <- widgetGetAllocation timelineDrawingArea + Rectangle _ _ _ xScaleAreaHeight <- widgetGetAllocation timelineXScaleArea scaleValue <- readIORef scaleIORef -- Snap the view to whole pixels, to avoid blurring. hadjValue0 <- adjustmentGetValue timelineAdj let hadjValue = toWholePixels scaleValue hadjValue0 off y = y + xScaleAreaHeight - 17 - renderWithDrawable win $ + renderWithDrawWindow win $ renderXScale scaleValue hadjValue lastTx width off XScaleTime return () @@ -341,7 +343,7 @@ renderYScaleArea ViewParameters{maxSpkValue, labelsMode, viewTraces, hecs yScaleArea = do let maxP = maxSparkPool hecs maxH = fromIntegral $ maxYHistogram hecs - (xoffset, _) <- liftIO $ widgetGetSize yScaleArea + Rectangle _ _ xoffset _ <- liftIO $ widgetGetAllocation yScaleArea drawYScaleArea maxSpkValue maxP maxH minterval (fromIntegral xoffset) 0 labelsMode histogramHeight viewTraces yScaleArea @@ -352,11 +354,12 @@ updateYScaleArea :: TimelineState -> Double -> Double -> Maybe Interval -> Bool -> [Trace] -> IO () updateYScaleArea TimelineState{..} maxSparkPool maxYHistogram minterval labelsMode traces = do - win <- widgetGetDrawWindow timelineYScaleArea + -- TODO: get rid of this Just + Just win <- widgetGetWindow timelineYScaleArea maxSpkValue <- readIORef maxSpkIORef vadj_value <- adjustmentGetValue timelineVAdj - (xoffset, _) <- widgetGetSize timelineYScaleArea - renderWithDrawable win $ + Rectangle _ _ xoffset _ <- widgetGetAllocation timelineYScaleArea + renderWithDrawWindow win $ drawYScaleArea maxSpkValue maxSparkPool maxYHistogram minterval (fromIntegral xoffset) vadj_value labelsMode stdHistogramHeight traces timelineYScaleArea @@ -393,7 +396,7 @@ drawSingleYScale maxSpkValue maxSparkPool maxYHistogram minterval xoffset -- Note: the following does not always work, see the HACK in Timeline.hs layoutSetAttributes layout [AttrSize minBound maxBound 8, AttrFamily minBound maxBound -#if MIN_VERSION_gtk(0,13,0) +#if MIN_VERSION_gtk3(0,13,0) (T.pack "sans serif")] #else "sans serif"] diff --git a/Graphics/UI/Gtk/ModelView/TreeView/Compat.hs b/Graphics/UI/Gtk/ModelView/TreeView/Compat.hs index b697ded7..a24124d5 100644 --- a/Graphics/UI/Gtk/ModelView/TreeView/Compat.hs +++ b/Graphics/UI/Gtk/ModelView/TreeView/Compat.hs @@ -4,7 +4,7 @@ module Graphics.UI.Gtk.ModelView.TreeView.Compat ) where import Graphics.UI.Gtk hiding (treeViewSetModel) import qualified Graphics.UI.Gtk.ModelView.TreeView as Gtk -#if !MIN_VERSION_gtk(0, 14, 9) +#if !MIN_VERSION_gtk3(0, 14, 9) import qualified System.Glib.FFI as Glib import qualified Graphics.UI.GtkInternals as Gtk #endif @@ -14,7 +14,7 @@ treeViewSetModel => self -> Maybe model -> IO () -#if MIN_VERSION_gtk(0, 14, 9) +#if MIN_VERSION_gtk3(0, 14, 9) treeViewSetModel = Gtk.treeViewSetModel #else treeViewSetModel self model = Gtk.treeViewSetModel self diff --git a/threadscope.cabal b/threadscope.cabal index e2471e13..80da4dec 100644 --- a/threadscope.cabal +++ b/threadscope.cabal @@ -34,6 +34,7 @@ Bug-reports: https://github.com/haskell/ThreadScope/issues Build-Type: Simple Data-files: threadscope.ui, threadscope.png Extra-source-files: include/windows_cconv.h + threadscope.ui README.md CHANGELOG.md Tested-with: GHC == 8.8.4 @@ -53,7 +54,7 @@ source-repository head Executable threadscope Main-is: Main.hs Build-Depends: base >= 4.10 && < 5, - gtk >= 0.12 && < 0.16, + gtk3 >= 0.12 && < 0.16, cairo < 0.14, glib < 0.14, pango < 0.14, @@ -69,10 +70,12 @@ Executable threadscope bytestring < 0.13, file-embed < 0.1, template-haskell < 2.24, - temporary >= 1.1 && < 1.4 + temporary >= 1.1 && < 1.4, + transformers <0.6.3 include-dirs: include default-extensions: RecordWildCards, NamedFieldPuns, BangPatterns, PatternGuards + other-extensions: TemplateHaskell Other-Modules: Events.HECs, Events.EventDuration, Events.EventTree,