diff options
author | Simon Rettberg | 2021-04-07 13:46:15 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-04-07 13:46:15 +0200 |
commit | b0683d83a9a1778c3dd991541ef0a3d82c62ad0e (patch) | |
tree | 0011c32ce218758c122e053c877432a295948f91 /driver | |
parent | xscreensaver 6.00 (diff) | |
download | xscreensaver-b0683d83a9a1778c3dd991541ef0a3d82c62ad0e.tar.gz xscreensaver-b0683d83a9a1778c3dd991541ef0a3d82c62ad0e.tar.xz xscreensaver-b0683d83a9a1778c3dd991541ef0a3d82c62ad0e.zip |
Delete pre-6.00 files
Diffstat (limited to 'driver')
-rw-r--r-- | driver/XScreenSaver_Xm_ad.h | 108 | ||||
-rw-r--r-- | driver/XScreenSaver_ad.h | 534 | ||||
-rw-r--r-- | driver/splash.c | 917 | ||||
-rw-r--r-- | driver/test-apm.c | 101 | ||||
-rw-r--r-- | driver/test-mlstring.c | 312 | ||||
-rw-r--r-- | driver/timers.c | 1794 | ||||
-rw-r--r-- | driver/vms-getpwnam.c | 129 | ||||
-rw-r--r-- | driver/vms-hpwd.c | 75 | ||||
-rw-r--r-- | driver/vms-pwd.h | 48 | ||||
-rw-r--r-- | driver/vms-validate.c | 75 | ||||
-rw-r--r-- | driver/xscreensaver-getimage.c | 2000 | ||||
-rw-r--r-- | driver/xset.c | 389 |
12 files changed, 0 insertions, 6482 deletions
diff --git a/driver/XScreenSaver_Xm_ad.h b/driver/XScreenSaver_Xm_ad.h deleted file mode 100644 index 371e0a2..0000000 --- a/driver/XScreenSaver_Xm_ad.h +++ /dev/null @@ -1,108 +0,0 @@ -"*fontList: *-helvetica-medium-r-*-*-*-120-*-*-*-iso8859-1", -"*demoDialog*label1.fontList: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1", -"*cmdText.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1", -"*label0.fontList: *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1", -"XScreenSaver*doc.fontList: *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1", -"*foreground: #000000", -"*background: #C0C0C0", -"*XmTextField.foreground: #000000", -"*XmTextField.background: #FFFFFF", -"*list.foreground: #000000", -"*list.background: #FFFFFF", -"*ApplicationShell.title: XScreenSaver", -"*warning.title: XScreenSaver", -"*warning_popup.title: XScreenSaver", -"*allowShellResize: True", -"*autoUnmanage: False", -"*menubar*file.labelString: File", -"*menubar*file.mnemonic: F", -"*file.blank.labelString: Blank Screen Now", -"*file.blank.mnemonic: B", -"*file.lock.labelString: Lock Screen Now", -"*file.lock.mnemonic: L", -"*file.kill.labelString: Kill Daemon", -"*file.kill.mnemonic: K", -"*file.restart.labelString: Restart Daemon", -"*file.restart.mnemonic: R", -"*file.exit.labelString: Exit", -"*file.exit.mnemonic: E", -"*menubar*edit.labelString: Edit", -"*menubar*edit.mnemonic: E", -"*edit.cut.labelString: Cut", -"*edit.cut.mnemonic: u", -"*edit.copy.labelString: Copy", -"*edit.copy.mnemonic: C", -"*edit.paste.labelString: Paste", -"*edit.paste.mnemonic: P", -"*menubar*help.labelString: Help", -"*menubar*help.mnemonic: H", -"*help.about.labelString: About...", -"*help.about.mnemonic: A", -"*help.docMenu.labelString: Documentation...", -"*help.docMenu.mnemonic: D", -"*demoTab.marginWidth: 10", -"*optionsTab.marginWidth: 10", -"*XmScrolledWindow.topOffset: 10", -"*XmScrolledWindow.leftOffset: 10", -"*demoTab.topOffset: 4", -"*form1.bottomOffset: 10", -"*form3.leftOffset: 10", -"*form3.rightOffset: 10", -"*frame.topOffset: 10", -"*frame.bottomOffset: 10", -"*enabled.topOffset: 10", -"*visLabel.topOffset: 10", -"*combo.topOffset: 10", -"*form4.bottomOffset: 4", -"*hr.bottomOffset: 4", -"*XmComboBox.marginWidth: 0", -"*XmComboBox.marginHeight: 0", -"*demo.marginWidth: 30", -"*demo.marginHeight: 4", -"*man.marginWidth: 10", -"*man.marginHeight: 4", -"*down.leftOffset: 40", -"*down.marginWidth: 4", -"*down.marginHeight: 4", -"*up.marginWidth: 4", -"*up.marginHeight: 4", -"*frame.traversalOn: False", -"*list.automaticSelection: True", -"*list.visibleItemCount: 20", -"*doc.columns: 60", -"*combo.columns: 11", -"*demoTab.labelString: Graphics Demos", -"*optionsTab.labelString: Screensaver Options", -"*down.labelString: \\\\/ ", -"*up.labelString: /\\\\ ", -"*frameLabel.labelString: ", -"*cmdLabel.labelString: Command Line:", -"*cmdLabel.alignment: ALIGNMENT_BEGINNING", -"*enabled.labelString: Enabled", -"*visLabel.labelString: Visual:", -"*visLabel.alignment: ALIGNMENT_END", -"*visLabel.leftOffset: 20", -"*demo.labelString: Demo", -"*man.labelString: Documentation...", -"*done.labelString: Quit", -"*preferencesLabel.labelString: XScreenSaver Parameters", -"*timeoutLabel.labelString: Saver Timeout", -"*cycleLabel.labelString: Cycle Timeout", -"*fadeSecondsLabel.labelString: Fade Duration", -"*fadeTicksLabel.labelString: Fade Ticks", -"*lockLabel.labelString: Lock Timeout", -"*passwdLabel.labelString: Password Timeout", -"*preferencesForm*XmTextField.columns: 8", -"*verboseToggle.labelString: Verbose", -"*cmapToggle.labelString: Install Colormap", -"*fadeToggle.labelString: Fade Colormap", -"*unfadeToggle.labelString: Unfade Colormap", -"*lockToggle.labelString: Require Password", -"*OK.marginWidth: 30", -"*OK.marginHeight: 4", -"*OK.leftOffset: 10", -"*OK.bottomOffset: 10", -"*Cancel.marginWidth: 30", -"*Cancel.marginHeight: 4", -"*Cancel.rightOffset: 10", -"*Cancel.bottomOffset: 10", diff --git a/driver/XScreenSaver_ad.h b/driver/XScreenSaver_ad.h deleted file mode 100644 index 22e213a..0000000 --- a/driver/XScreenSaver_ad.h +++ /dev/null @@ -1,534 +0,0 @@ -"#error Do not run app-defaults files through xrdb!", -"#error That does not do what you might expect.", -"#error Put this file in /usr/lib/X11/app-defaults/XScreenSaver instead.", -"*mode: random", -"*timeout: 0:10:00", -"*cycle: 0:10:00", -"*lockTimeout: 0:00:00", -"*passwdTimeout: 0:00:30", -"*dpmsEnabled: False", -"*dpmsQuickoffEnabled: False", -"*dpmsStandby: 2:00:00", -"*dpmsSuspend: 2:00:00", -"*dpmsOff: 4:00:00", -"*grabDesktopImages: True", -"*grabVideoFrames: False", -"*chooseRandomImages: True", -"*imageDirectory: /Library/Desktop Pictures/", -"*nice: 10", -"*memoryLimit: 0", -"*lock: False", -"*verbose: False", -"*fade: True", -"*unfade: True", -"*fadeSeconds: 0:00:03", -"*fadeTicks: 20", -"*splash: True", -"*splashDuration: 0:00:05", -"*visualID: default", -"*installColormap: True", -"*ignoreUninstalledPrograms: False", -"*authWarningSlack: 20", -"*textMode: file", -"*textLiteral: XScreenSaver", -"*textFile: ", -"*textProgram: fortune", -"*textURL: https://en.wikipedia.org/w/index.php?title=Special:NewPages&feed=rss", -"*demoCommand: xscreensaver-settings", -"*helpURL: https://www.jwz.org/xscreensaver/man.html", -"*loadURL: gnome-open '%s'", -"*manualCommand: yelp man:%s || \ - x-terminal-emulator -t '%s manual' \ - -e /bin/sh -c \"man %s; read foo\"", -"*dateFormat: %I:%M %p, %a %b %e", -"*newLoginCommand: no-such-login-manager", -"XScreenSaver.pointerHysteresis: 10", -"XScreenSaver.bourneShell: /bin/sh", -"*dialogTheme: default", -"*themeNames: Default, Borderless, Dark Gray, Borderless Black, \ - Green Black, White, Blue, Aqua Black, Wine", -"*Dialog.headingFont: sans-serif bold 16", -"*Dialog.bodyFont: sans-serif 14", -"*Dialog.errorFont: sans-serif bold 14", -"*Dialog.labelFont: sans-serif bold 14", -"*Dialog.unameFont: sans-serif 12", -"*Dialog.buttonFont: sans-serif bold 14", -"*Dialog.dateFont: sans-serif 9", -"*passwd.uname: True", -"*passwd.asterisks: True", -"*default.Dialog.foreground: #000000", -"*default.Dialog.background: #E6E6E6", -"*default.Dialog.button.foreground: #000000", -"*default.Dialog.button.background: #F5F5F5", -"*default.Dialog.logo.background: #BBBBBB", -"*default.Dialog.text.foreground: #000000", -"*default.Dialog.error.foreground: #FF0000", -"*default.Dialog.text.background: #FFFFFF", -"*default.Dialog.topShadowColor: #FFFFFF", -"*default.Dialog.bottomShadowColor: #CECECE", -"*default.Dialog.shadowWidth: 2", -"*default.Dialog.logo.width: 210", -"*default.Dialog.logo.height: 210", -"*default.Dialog.thermometer.foreground: #4464AC", -"*default.Dialog.thermometer.background: #FFFFFF", -"*default.Dialog.thermometer.width: 8", -"*default.Dialog.borderColor: #CECECE", -"*default.Dialog.borderWidth: 0", -"*default.Dialog.internalPadding: 24", -"*borderless.Dialog.topShadowColor: #E6E6E6", -"*borderless.Dialog.button.background: #FFFFFF", -"*borderless.Dialog.bottomShadowColor: #E6E6E6", -"*borderless.Dialog.logo.background: #E6E6E6", -"*borderless.Dialog.borderColor: #888888", -"*borderless.Dialog.thermometer.width: 6", -"*borderless.Dialog.borderWidth: 1", -"*darkgray.Dialog.foreground: #CCCCCC", -"*darkgray.Dialog.background: #333333", -"*darkgray.Dialog.topShadowColor: #444444", -"*darkgray.Dialog.bottomShadowColor: #111111", -"*darkgray.Dialog.borderColor: #111111", -"*darkgray.Dialog.text.foreground: #DDDDDD", -"*darkgray.Dialog.text.background: #666666", -"*darkgray.Dialog.button.foreground: #CCCCCC", -"*darkgray.Dialog.button.background: #666666", -"*darkgray.Dialog.logo.background: #444444", -"*darkgray.Dialog.thermometer.foreground: #4464AC", -"*darkgray.Dialog.thermometer.background: #666666", -"*darkgray.Dialog.borderWidth: 0", -"*borderlessblack.Dialog.foreground: #CCCCCC", -"*borderlessblack.Dialog.background: #000000", -"*borderlessblack.Dialog.topShadowColor: #000000", -"*borderlessblack.Dialog.bottomShadowColor: #000000", -"*borderlessblack.Dialog.text.foreground: #CCCCCC", -"*borderlessblack.Dialog.text.background: #000000", -"*borderlessblack.Dialog.button.foreground: #CCCCCC", -"*borderlessblack.Dialog.button.background: #333333", -"*borderlessblack.Dialog.logo.background: #000000", -"*borderlessblack.Dialog.thermometer.foreground: #CCCCCC", -"*borderlessblack.Dialog.thermometer.background: #333333", -"*borderlessblack.Dialog.thermometer.width: 3", -"*borderlessblack.Dialog.borderColor: #333333", -"*borderlessblack.Dialog.borderWidth: 1", -"*greenblack.Dialog.foreground: #00FF00", -"*greenblack.Dialog.background: #000000", -"*greenblack.Dialog.topShadowColor: #000000", -"*greenblack.Dialog.bottomShadowColor: #000000", -"*greenblack.Dialog.shadowWidth: 1", -"*greenblack.Dialog.text.foreground: #00FF00", -"*greenblack.Dialog.text.background: #006600", -"*greenblack.Dialog.button.foreground: #00FF00", -"*greenblack.Dialog.button.background: #006600", -"*greenblack.Dialog.logo.background: #000000", -"*greenblack.Dialog.thermometer.foreground: #00CC00", -"*greenblack.Dialog.thermometer.background: #006600", -"*greenblack.Dialog.borderColor: #006600", -"*greenblack.Dialog.borderWidth: 1", -"*white.Dialog.foreground: #000000", -"*white.Dialog.background: #FFFFFF", -"*white.Dialog.topShadowColor: #CCCCCC", -"*white.Dialog.bottomShadowColor: #CCCCCC", -"*white.Dialog.shadowWidth: 1", -"*white.Dialog.borderColor: #CCCCCC", -"*white.Dialog.text.foreground: #000000", -"*white.Dialog.text.background: #FFFFFF", -"*white.Dialog.button.foreground: #000000", -"*white.Dialog.button.background: #FFFFFF", -"*white.Dialog.logo.background: #FFFFFF", -"*white.Dialog.borderWidth: 0", -"*blue.Dialog.foreground: #000000", -"*blue.Dialog.background: #BBCCDD", -"*blue.Dialog.topShadowColor: #CCDDEE", -"*blue.Dialog.bottomShadowColor: #AABBCC", -"*blue.Dialog.borderColor: #AABBCC", -"*blue.Dialog.text.foreground: #000000", -"*blue.Dialog.text.background: #DDEEFF", -"*blue.Dialog.button.foreground: #000000", -"*blue.Dialog.button.background: #DDEEFF", -"*blue.Dialog.logo.background: #BBCCDD", -"*blue.Dialog.thermometer.foreground: #5566AA", -"*blue.Dialog.thermometer.background: #BBCCDD", -"*blue.Dialog.borderWidth: 0", -"*aquablack.Dialog.foreground: #00EFEF", -"*aquablack.Dialog.background: #000000", -"*aquablack.Dialog.topShadowColor: #000000", -"*aquablack.Dialog.bottomShadowColor: #000000", -"*aquablack.Dialog.shadowWidth: 2", -"*aquablack.Dialog.button.foreground: #000000", -"*aquablack.Dialog.button.background: #2244EE", -"*aquablack.Dialog.logo.background: #000000", -"*aquablack.Dialog.text.foreground: #2244EE", -"*aquablack.Dialog.text.background: #EEEEEE", -"*aquablack.Dialog.thermometer.foreground: #2244EE", -"*aquablack.Dialog.thermometer.background: #000088", -"*aquablack.Dialog.borderColor: #000066", -"*aquablack.Dialog.borderWidth: 1", -"*aquablack.Dialog.internalPadding: 36", -"*wine.Dialog.foreground: #AD8FA6", -"*wine.Dialog.background: #2C041E", -"*wine.Dialog.topShadowColor: #2C041E", -"*wine.Dialog.bottomShadowColor: #2C041E", -"*wine.Dialog.text.foreground: #706B70", -"*wine.Dialog.text.background: #F9F9F8", -"*wine.Dialog.button.foreground: #5F585B", -"*wine.Dialog.logo.background: #2C041E", -"*wine.Dialog.thermometer.foreground: #AD8FA6", -"*wine.Dialog.thermometer.background: #4D2946", -"*wine.Dialog.borderColor: #4D2946", -"*wine.Dialog.thermometer.width: 6", -"*wine.Dialog.borderWidth: 1", -"*errorFont: sans-serif bold 18", -"*errorColor: #FF0000", -"*programs: \ - maze -root \\n\ - GL: superquadrics -root \\n\ - attraction -root \\n\ - blitspin -root \\n\ - greynetic -root \\n\ - helix -root \\n\ - hopalong -root \\n\ - imsmap -root \\n\ -- noseguy -root \\n\ -- pyro -root \\n\ - qix -root \\n\ -- rocks -root \\n\ - rorschach -root \\n\ - decayscreen -root \\n\ - flame -root \\n\ - halo -root \\n\ - slidescreen -root \\n\ - pedal -root \\n\ - bouboule -root \\n\ -- braid -root \\n\ - coral -root \\n\ - deco -root \\n\ - drift -root \\n\ -- fadeplot -root \\n\ - galaxy -root \\n\ - goop -root \\n\ - grav -root \\n\ - ifs -root \\n\ - GL: jigsaw -root \\n\ - julia -root \\n\ -- kaleidescope -root \\n\ - GL: moebius -root \\n\ - moire -root \\n\ - GL: morph3d -root \\n\ - mountain -root \\n\ - munch -root \\n\ - penrose -root \\n\ - GL: pipes -root \\n\ - rd-bomb -root \\n\ - GL: rubik -root \\n\ -- sierpinski -root \\n\ - slip -root \\n\ - GL: sproingies -root \\n\ - starfish -root \\n\ - strange -root \\n\ - swirl -root \\n\ - triangle -root \\n\ - xjack -root \\n\ - xlyap -root \\n\ - GL: atlantis -root \\n\ - bsod -root \\n\ - GL: bubble3d -root \\n\ - GL: cage -root \\n\ -- crystal -root \\n\ - cynosure -root \\n\ - discrete -root \\n\ - distort -root \\n\ - epicycle -root \\n\ - flow -root \\n\ - GL: glplanet -root \\n\ - interference -root \\n\ - kumppa -root \\n\ - GL: lament -root \\n\ - moire2 -root \\n\ - GL: sonar -root \\n\ - GL: stairs -root \\n\ - truchet -root \\n\ -- vidwhacker -root \\n\ - blaster -root \\n\ - bumps -root \\n\ - ccurve -root \\n\ - compass -root \\n\ - deluxe -root \\n\ -- demon -root \\n\ - GL: extrusion -root \\n\ -- loop -root \\n\ - penetrate -root \\n\ - petri -root \\n\ - phosphor -root \\n\ - GL: pulsar -root \\n\ - ripples -root \\n\ - shadebobs -root \\n\ - GL: sierpinski3d -root \\n\ - spotlight -root \\n\ - squiral -root \\n\ - wander -root \\n\ -- webcollage -root \\n\ - xflame -root \\n\ - xmatrix -root \\n\ - GL: gflux -root \\n\ -- nerverot -root \\n\ - xrayswarm -root \\n\ - xspirograph -root \\n\ - GL: circuit -root \\n\ - GL: dangerball -root \\n\ -- GL: dnalogo -root \\n\ - GL: engine -root \\n\ - GL: flipscreen3d -root \\n\ - GL: gltext -root \\n\ - GL: menger -root \\n\ - GL: molecule -root \\n\ - rotzoomer -root \\n\ - scooter -root \\n\ - speedmine -root \\n\ - GL: starwars -root \\n\ - GL: stonerview -root \\n\ - vermiculate -root \\n\ - whirlwindwarp -root \\n\ - zoom -root \\n\ - anemone -root \\n\ - apollonian -root \\n\ - GL: boxed -root \\n\ - GL: cubenetic -root \\n\ - GL: endgame -root \\n\ - euler2d -root \\n\ - fluidballs -root \\n\ - GL: flurry -root \\n\ -- GL: glblur -root \\n\ - GL: glsnake -root \\n\ - halftone -root \\n\ - GL: juggler3d -root \\n\ - GL: lavalite -root \\n\ -- polyominoes -root \\n\ - GL: queens -root \\n\ -- GL: sballs -root \\n\ - GL: spheremonics -root \\n\ -- thornbird -root \\n\ - twang -root \\n\ -- GL: antspotlight -root \\n\ - apple2 -root \\n\ - GL: atunnel -root \\n\ - barcode -root \\n\ - GL: blinkbox -root \\n\ - GL: blocktube -root \\n\ - GL: bouncingcow -root \\n\ - cloudlife -root \\n\ - GL: cubestorm -root \\n\ - eruption -root \\n\ - GL: flipflop -root \\n\ - GL: flyingtoasters -root \\n\ - fontglide -root \\n\ - GL: gleidescope -root \\n\ - GL: glknots -root \\n\ - GL: glmatrix -root \\n\ -- GL: glslideshow -root \\n\ - GL: hypertorus -root \\n\ -- GL: jigglypuff -root \\n\ - metaballs -root \\n\ - GL: mirrorblob -root \\n\ - piecewise -root \\n\ - GL: polytopes -root \\n\ - pong -root \\n\ - popsquares -root \\n\ - GL: surfaces -root \\n\ - xanalogtv -root \\n\ - abstractile -root \\n\ - anemotaxis -root \\n\ -- GL: antinspect -root \\n\ - fireworkx -root \\n\ - fuzzyflakes -root \\n\ - interaggregate -root \\n\ - intermomentary -root \\n\ - memscroller -root \\n\ - GL: noof -root \\n\ - pacman -root \\n\ - GL: pinion -root \\n\ - GL: polyhedra -root \\n\ -- GL: providence -root \\n\ - substrate -root \\n\ - wormhole -root \\n\ -- GL: antmaze -root \\n\ - GL: boing -root \\n\ - boxfit -root \\n\ - GL: carousel -root \\n\ - celtic -root \\n\ - GL: crackberg -root \\n\ - GL: cube21 -root \\n\ - fiberlamp -root \\n\ - GL: fliptext -root \\n\ - GL: glhanoi -root \\n\ - GL: tangram -root \\n\ - GL: timetunnel -root \\n\ - GL: glschool -root \\n\ - GL: topblock -root \\n\ - GL: cubicgrid -root \\n\ - cwaves -root \\n\ - GL: gears -root \\n\ - GL: glcells -root \\n\ - GL: lockward -root \\n\ - m6502 -root \\n\ - GL: moebiusgears -root \\n\ - GL: voronoi -root \\n\ - GL: hypnowheel -root \\n\ - GL: klein -root \\n\ -- lcdscrub -root \\n\ - GL: photopile -root \\n\ - GL: skytentacles -root \\n\ - GL: rubikblocks -root \\n\ - GL: companioncube -root \\n\ - GL: hilbert -root \\n\ - GL: tronbit -root \\n\ - GL: geodesic -root \\n\ - hexadrop -root \\n\ - GL: kaleidocycle -root \\n\ - GL: quasicrystal -root \\n\ - GL: unknownpleasures -root \\n\ - binaryring -root \\n\ - GL: cityflow -root \\n\ - GL: geodesicgears -root \\n\ - GL: projectiveplane -root \\n\ - GL: romanboy -root \\n\ - tessellimage -root \\n\ - GL: winduprobot -root \\n\ - GL: splitflap -root \\n\ - GL: cubestack -root \\n\ - GL: cubetwist -root \\n\ - GL: discoball -root \\n\ - GL: dymaxionmap -root \\n\ - GL: energystream -root \\n\ - GL: hexstrut -root \\n\ - GL: hydrostat -root \\n\ - GL: raverhoop -root \\n\ - GL: splodesic -root \\n\ - GL: unicrud -root \\n\ - GL: esper -root \\n\ - GL: vigilance -root \\n\ - GL: crumbler -root \\n\ - filmleader -root \\n\ - glitchpeg -root \\n\ - GL: handsy -root \\n\ - GL: maze3d -root \\n\ - GL: peepers -root \\n\ - GL: razzledazzle -root \\n\ - vfeedback -root \\n\ - GL: deepstars -root \\n\ - GL: gravitywell -root \\n\ - GL: beats -root \\n\ - GL: covid19 -root \\n\ - GL: etruscanvenus -root \\n\ - GL: gibson -root \\n\ - GL: headroom -root \\n\ - GL: sphereeversion -root \\n", -"*hacks.antinspect.name: Ant Inspect", -"*hacks.antmaze.name: Ant Maze", -"*hacks.antspotlight.name: Ant Spotlight", -"*hacks.apple2.name: Apple ][", -"*hacks.binaryring.name: Binary Ring", -"*hacks.blinkbox.name: Blink Box", -"*hacks.blitspin.name: Blit Spin", -"*hacks.blocktube.name: Block Tube", -"*hacks.bouncingcow.name: Bouncing Cow", -"*hacks.boxfit.name: Box Fit", -"*hacks.bsod.name: BSOD", -"*hacks.bubble3d.name: Bubble 3D", -"*hacks.ccurve.name: C Curve", -"*hacks.cityflow.name: City Flow", -"*hacks.cloudlife.name: Cloud Life", -"*hacks.companioncube.name: Companion Cube", -"*hacks.covid19.name: COVID19", -"*hacks.cube21.name: Cube 21", -"*hacks.cubestack.name: Cube Stack", -"*hacks.cubestorm.name: Cube Storm", -"*hacks.cubetwist.name: Cube Twist", -"*hacks.cubicgrid.name: Cubic Grid", -"*hacks.cwaves.name: C Waves", -"*hacks.dangerball.name: Danger Ball", -"*hacks.decayscreen.name: Decay Screen", -"*hacks.deepstars.name: Deep Stars", -"*hacks.dnalogo.name: DNA Logo", -"*hacks.dymaxionmap.name: Dymaxion Map", -"*hacks.energystream.name: Energy Stream", -"*hacks.etruscanvenus.name: Etruscan Venus", -"*hacks.euler2d.name: Euler 2D", -"*hacks.fadeplot.name: Fade Plot", -"*hacks.fiberlamp.name: Fiber Lamp", -"*hacks.filmleader.name: Film Leader", -"*hacks.flipflop.name: Flip Flop", -"*hacks.flipscreen3d.name: Flip Screen 3D", -"*hacks.fliptext.name: Flip Text", -"*hacks.fluidballs.name: Fluid Balls", -"*hacks.flyingtoasters.name: Flying Toasters", -"*hacks.fontglide.name: Font Glide", -"*hacks.fuzzyflakes.name: Fuzzy Flakes", -"*hacks.geodesicgears.name: Geodesic Gears", -"*hacks.gflux.name: GFlux", -"*hacks.glblur.name: GL Blur", -"*hacks.glcells.name: GL Cells", -"*hacks.gleidescope.name: Gleidescope", -"*hacks.glforestfire.name: GL Forest Fire", -"*hacks.glhanoi.name: GL Hanoi", -"*hacks.glitchpeg.name: GlitchPEG", -"*hacks.glknots.name: GL Knots", -"*hacks.glmatrix.name: GL Matrix", -"*hacks.glplanet.name: GL Planet", -"*hacks.glschool.name: GL School", -"*hacks.glslideshow.name: GL Slideshow", -"*hacks.glsnake.name: GL Snake", -"*hacks.gltext.name: GL Text", -"*hacks.gravitywell.name: Gravity Well", -"*hacks.hexstrut.name: Hex Strut", -"*hacks.ifs.name: IFS", -"*hacks.imsmap.name: IMS Map", -"*hacks.jigglypuff.name: Jiggly Puff", -"*hacks.juggler3d.name: Juggler 3D", -"*hacks.lcdscrub.name: LCD Scrub", -"*hacks.lmorph.name: LMorph", -"*hacks.m6502.name: m6502", -"*hacks.maze3d.name: Maze 3D", -"*hacks.memscroller.name: Mem Scroller", -"*hacks.metaballs.name: Meta Balls", -"*hacks.mirrorblob.name: Mirror Blob", -"*hacks.moebius.name: Möbius", -"*hacks.moebiusgears.name: Möbius Gears", -"*hacks.moire.name: Moiré", -"*hacks.moire2.name: Moiré 2", -"*hacks.morph3d.name: Morph 3D", -"*hacks.nerverot.name: Nerve Rot", -"*hacks.noseguy.name: Nose Guy", -"*hacks.pacman.name: Pac-Man", -"*hacks.photopile.name: Photo Pile", -"*hacks.popsquares.name: Pop Squares", -"*hacks.projectiveplane.name:Projective Plane", -"*hacks.quasicrystal.name: Quasi-Crystal", -"*hacks.raverhoop.name: Raver Hoop", -"*hacks.razzledazzle.name: Razzle Dazzle", -"*hacks.rd-bomb.name: RD-Bomb", -"*hacks.rd-bomb.name: RD-Bomb", -"*hacks.romanboy.name: Roman Boy", -"*hacks.rotzoomer.name: Rot Zoomer", -"*hacks.rubikblocks.name: Rubik Blocks", -"*hacks.sballs.name: SBalls", -"*hacks.shadebobs.name: Shade Bobs", -"*hacks.sierpinski3d.name: Sierpinski 3D", -"*hacks.skytentacles.name: Sky Tentacles", -"*hacks.slidescreen.name: Slide Screen", -"*hacks.speedmine.name: Speed Mine", -"*hacks.sphereeversion.name: Sphere Eversion", -"*hacks.splitflap.name: Split-Flap", -"*hacks.starwars.name: Star Wars", -"*hacks.stonerview.name: Stoner View", -"*hacks.t3d.name: T3D", -"*hacks.testx11.name: Test X11", -"*hacks.timetunnel.name: Time Tunnel", -"*hacks.topblock.name: Top Block", -"*hacks.tronbit.name: Tron Bit", -"*hacks.unknownpleasures.name:Unknown Pleasures", -"*hacks.vfeedback.name: VFeedback", -"*hacks.vidwhacker.name: Vid Whacker", -"*hacks.webcollage.name: Web Collage", -"*hacks.whirlwindwarp.name: Whirlwind Warp", -"*hacks.winduprobot.name: Windup Robot", -"*hacks.xanalogtv.name: XAnalogTV", -"*hacks.xrayswarm.name: XRaySwarm", diff --git a/driver/splash.c b/driver/splash.c deleted file mode 100644 index b971ade..0000000 --- a/driver/splash.c +++ /dev/null @@ -1,917 +0,0 @@ -/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <X11/Intrinsic.h> - -#include "xscreensaver.h" -#include "resources.h" -#include "font-retry.h" - -#undef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) - -void -draw_shaded_rectangle (Display *dpy, Window window, - int x, int y, - int width, int height, - int thickness, - unsigned long top_color, - unsigned long bottom_color) -{ - XPoint points[4]; - XGCValues gcv; - GC gc1, gc2; - if (thickness == 0) return; - - gcv.foreground = top_color; - gc1 = XCreateGC (dpy, window, GCForeground, &gcv); - gcv.foreground = bottom_color; - gc2 = XCreateGC (dpy, window, GCForeground, &gcv); - - points [0].x = x; - points [0].y = y; - points [1].x = x + width; - points [1].y = y; - points [2].x = x + width - thickness; - points [2].y = y + thickness; - points [3].x = x; - points [3].y = y + thickness; - XFillPolygon (dpy, window, gc1, points, 4, Convex, CoordModeOrigin); - - points [0].x = x; - points [0].y = y + thickness; - points [1].x = x; - points [1].y = y + height; - points [2].x = x + thickness; - points [2].y = y + height - thickness; - points [3].x = x + thickness; - points [3].y = y + thickness; - XFillPolygon (dpy, window, gc1, points, 4, Convex, CoordModeOrigin); - - points [0].x = x + width; - points [0].y = y; - points [1].x = x + width - thickness; - points [1].y = y + thickness; - points [2].x = x + width - thickness; - points [2].y = y + height - thickness; - points [3].x = x + width; - points [3].y = y + height - thickness; - XFillPolygon (dpy, window, gc2, points, 4, Convex, CoordModeOrigin); - - points [0].x = x; - points [0].y = y + height; - points [1].x = x + width; - points [1].y = y + height; - points [2].x = x + width; - points [2].y = y + height - thickness; - points [3].x = x + thickness; - points [3].y = y + height - thickness; - XFillPolygon (dpy, window, gc2, points, 4, Convex, CoordModeOrigin); - - XFreeGC (dpy, gc1); - XFreeGC (dpy, gc2); -} - - -int -string_width (XFontStruct *font, char *s) -{ - return XTextWidth(font, s, strlen(s)); -} - - -static void update_splash_window (saver_info *si); -static void draw_splash_window (saver_info *si); -static void destroy_splash_window (saver_info *si); -static void unsplash_timer (XtPointer closure, XtIntervalId *id); - -static void do_demo (saver_screen_info *ssi); -#ifdef PREFS_BUTTON -static void do_prefs (saver_screen_info *ssi); -#endif /* PREFS_BUTTON */ -static void do_help (saver_screen_info *ssi); - - -XFontStruct * -splash_load_font (Display *dpy, char *name, char *class) -{ - char *s = get_string_resource (dpy, name, class); - XFontStruct *f; - if (!s || !*s) - s = "-*-helvetica-bold-r-*-*-*-140-*-*-*-*-*-*"; - f = load_font_retry (dpy, s); - if (!f) abort(); - return f; -} - - -struct splash_dialog_data { - - saver_screen_info *prompt_screen; - XtIntervalId timer; - - Dimension width; - Dimension height; - - char *heading_label; - char *body_label; - char *body2_label; - char *body3_label; - char *body4_label; - char *demo_label; -#ifdef PREFS_BUTTON - char *prefs_label; -#endif /* PREFS_BUTTON */ - char *help_label; - - XFontStruct *heading_font; - XFontStruct *body_font; - XFontStruct *button_font; - - Pixel foreground; - Pixel background; - Pixel border; - Pixel button_foreground; - Pixel button_background; - Pixel shadow_top; - Pixel shadow_bottom; - - Dimension logo_width; - Dimension logo_height; - Dimension internal_border; - Dimension shadow_width; - - Dimension button_width, button_height; - Dimension demo_button_x, demo_button_y; -#ifdef PREFS_BUTTON - Dimension prefs_button_x, prefs_button_y; -#endif /* PREFS_BUTTON */ - Dimension help_button_x, help_button_y; - - Pixmap logo_pixmap; - Pixmap logo_clipmask; - int logo_npixels; - unsigned long *logo_pixels; - - int pressed; -}; - - -void -make_splash_dialog (saver_info *si) -{ - saver_preferences *p = &si->prefs; - int x, y, bw; - XSetWindowAttributes attrs; - unsigned long attrmask = 0; - splash_dialog_data *sp; - saver_screen_info *ssi; - Colormap cmap; - - Bool whyne = senesculent_p (); - - if (whyne) - { - /* If locking is not enabled, make sure they see the message. */ - if (!p->lock_p) - { - si->prefs.splash_p = True; - if (si->prefs.splash_duration < 5000) - si->prefs.splash_duration = 5000; - } - si->prefs.splash_duration += 3000; - } - - if (si->sp_data) - return; - if (!si->prefs.splash_p || - si->prefs.splash_duration <= 0) - return; - - ssi = &si->screens[mouse_screen (si)]; - - if (!ssi || !ssi->screen) - return; /* WTF? Trying to splash while no screens connected? */ - - cmap = DefaultColormapOfScreen (ssi->screen); - - sp = (splash_dialog_data *) calloc (1, sizeof(*sp)); - sp->prompt_screen = ssi; - - sp->heading_label = get_string_resource (si->dpy, - "splash.heading.label", - "Dialog.Label.Label"); - sp->body_label = get_string_resource (si->dpy, - "splash.body.label", - "Dialog.Label.Label"); - sp->body2_label = get_string_resource (si->dpy, - "splash.body2.label", - "Dialog.Label.Label"); - sp->demo_label = get_string_resource (si->dpy, - "splash.demo.label", - "Dialog.Button.Label"); -#ifdef PREFS_BUTTON - sp->prefs_label = get_string_resource (si->dpy, - "splash.prefs.label", - "Dialog.Button.Label"); -#endif /* PREFS_BUTTON */ - sp->help_label = get_string_resource (si->dpy, - "splash.help.label", - "Dialog.Button.Label"); - - - - if (whyne) - { - sp->body3_label = strdup("WARNING: This version is very old!"); - sp->body4_label = strdup("Please upgrade!"); - } - - if (!sp->heading_label) - sp->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY"); - if (!sp->body_label) - sp->body_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY"); - if (!sp->body2_label) - sp->body2_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY"); - if (!sp->demo_label) sp->demo_label = strdup("ERROR"); -#ifdef PREFS_BUTTON - if (!sp->prefs_label) sp->prefs_label = strdup("ERROR"); -#endif /* PREFS_BUTTON */ - if (!sp->help_label) sp->help_label = strdup("ERROR"); - - /* Put the version number in the label. */ - { - char *s = (char *) malloc (strlen(sp->heading_label) + 20); - sprintf(s, sp->heading_label, si->version); - free (sp->heading_label); - sp->heading_label = s; - } - - sp->heading_font = - splash_load_font (si->dpy, "splash.headingFont", "Dialog.Font"); - sp->body_font = - splash_load_font (si->dpy, "splash.bodyFont", "Dialog.Font"); - sp->button_font = - splash_load_font (si->dpy, "splash.buttonFont", "Dialog.Font"); - - sp->foreground = get_pixel_resource (si->dpy, cmap, - "splash.foreground", - "Dialog.Foreground"); - sp->background = get_pixel_resource (si->dpy, cmap, - "splash.background", - "Dialog.Background"); - sp->border = get_pixel_resource (si->dpy, cmap, - "splash.borderColor", - "Dialog.borderColor"); - - if (sp->foreground == sp->background) - { - /* Make sure the error messages show up. */ - sp->foreground = BlackPixelOfScreen (ssi->screen); - sp->background = WhitePixelOfScreen (ssi->screen); - } - - sp->button_foreground = get_pixel_resource (si->dpy, cmap, - "splash.Button.foreground", - "Dialog.Button.Foreground"); - sp->button_background = get_pixel_resource (si->dpy, cmap, - "splash.Button.background", - "Dialog.Button.Background"); - sp->shadow_top = get_pixel_resource (si->dpy, cmap, - "splash.topShadowColor", - "Dialog.Foreground"); - sp->shadow_bottom = get_pixel_resource (si->dpy, cmap, - "splash.bottomShadowColor", - "Dialog.Background"); - - sp->logo_width = get_integer_resource (si->dpy, - "splash.logo.width", - "Dialog.Logo.Width"); - sp->logo_height = get_integer_resource (si->dpy, - "splash.logo.height", - "Dialog.Logo.Height"); - sp->internal_border = get_integer_resource (si->dpy, - "splash.internalBorderWidth", - "Dialog.InternalBorderWidth"); - sp->shadow_width = get_integer_resource (si->dpy, - "splash.shadowThickness", - "Dialog.ShadowThickness"); - - if (sp->logo_width == 0) sp->logo_width = 150; - if (sp->logo_height == 0) sp->logo_height = 150; - if (sp->internal_border == 0) sp->internal_border = 15; - if (sp->shadow_width == 0) sp->shadow_width = 4; - - { - int direction, ascent, descent; - XCharStruct overall; - - sp->width = 0; - sp->height = 0; - - /* Measure the heading_label. */ - XTextExtents (sp->heading_font, - sp->heading_label, strlen(sp->heading_label), - &direction, &ascent, &descent, &overall); - if (overall.width > sp->width) sp->width = overall.width; - sp->height += ascent + descent; - - /* Measure the body_label. */ - XTextExtents (sp->body_font, - sp->body_label, strlen(sp->body_label), - &direction, &ascent, &descent, &overall); - if (overall.width > sp->width) sp->width = overall.width; - sp->height += ascent + descent; - - /* Measure the body2_label. */ - XTextExtents (sp->body_font, - sp->body2_label, strlen(sp->body2_label), - &direction, &ascent, &descent, &overall); - if (overall.width > sp->width) sp->width = overall.width; - sp->height += ascent + descent; - - /* Measure the optional body3_label. */ - if (sp->body3_label) - { - XTextExtents (sp->heading_font, - sp->body3_label, strlen(sp->body3_label), - &direction, &ascent, &descent, &overall); - if (overall.width > sp->width) sp->width = overall.width; - XTextExtents (sp->heading_font, - sp->body4_label, strlen(sp->body4_label), - &direction, &ascent, &descent, &overall); - if (overall.width > sp->width) sp->width = overall.width; - sp->height += (ascent + descent) * 5; - } - - { - Dimension w2 = 0, w3 = 0, w4 = 0; - Dimension h2 = 0, h3 = 0, h4 = 0; - - /* Measure the Demo button. */ - XTextExtents (sp->button_font, - sp->demo_label, strlen(sp->demo_label), - &direction, &ascent, &descent, &overall); - w2 = overall.width; - h2 = ascent + descent; - -#ifdef PREFS_BUTTON - /* Measure the Prefs button. */ - XTextExtents (sp->button_font, - sp->prefs_label, strlen(sp->prefs_label), - &direction, &ascent, &descent, &overall); - w3 = overall.width; - h3 = ascent + descent; -#else /* !PREFS_BUTTON */ - w3 = 0; - h3 = 0; -#endif /* !PREFS_BUTTON */ - - /* Measure the Help button. */ - XTextExtents (sp->button_font, - sp->help_label, strlen(sp->help_label), - &direction, &ascent, &descent, &overall); - w4 = overall.width; - h4 = ascent + descent; - - w2 = MAX(w2, w3); w2 = MAX(w2, w4); - h2 = MAX(h2, h3); h2 = MAX(h2, h4); - - /* Add some horizontal padding inside the buttons. */ - w2 += ascent; - - w2 += ((ascent + descent) / 2) + (sp->shadow_width * 2); - h2 += ((ascent + descent) / 2) + (sp->shadow_width * 2); - - sp->button_width = w2; - sp->button_height = h2; - -#ifdef PREFS_BUTTON - w2 *= 3; -#else /* !PREFS_BUTTON */ - w2 *= 2; -#endif /* !PREFS_BUTTON */ - - w2 += ((ascent + descent) * 2); /* for space between buttons */ - - if (w2 > sp->width) sp->width = w2; - sp->height += h2; - } - - sp->width += (sp->internal_border * 2); - sp->height += (sp->internal_border * 3); - - if (sp->logo_height > sp->height) - sp->height = sp->logo_height; - else if (sp->height > sp->logo_height) - sp->logo_height = sp->height; - - sp->logo_width = sp->logo_height; - - sp->width += sp->logo_width; - } - - attrmask |= CWOverrideRedirect; attrs.override_redirect = True; - attrmask |= CWEventMask; - attrs.event_mask = (ExposureMask | ButtonPressMask | ButtonReleaseMask); - - { - int sx = 0, sy = 0, w, h; - - x = ssi->x; - y = ssi->y; - w = ssi->width; - h = ssi->height; - if (si->prefs.debug_p) w /= 2; - x = sx + (((w + sp->width) / 2) - sp->width); - y = sy + (((h + sp->height) / 2) - sp->height); - if (x < sx) x = sx; - if (y < sy) y = sy; - } - - bw = get_integer_resource (si->dpy, - "splash.borderWidth", - "Dialog.BorderWidth"); - - si->splash_dialog = - XCreateWindow (si->dpy, - RootWindowOfScreen(ssi->screen), - x, y, sp->width, sp->height, bw, - DefaultDepthOfScreen (ssi->screen), InputOutput, - DefaultVisualOfScreen(ssi->screen), - attrmask, &attrs); - XSetWindowBackground (si->dpy, si->splash_dialog, sp->background); - XSetWindowBorder (si->dpy, si->splash_dialog, sp->border); - - - sp->logo_pixmap = xscreensaver_logo (ssi->screen, - /* same visual as si->splash_dialog */ - DefaultVisualOfScreen (ssi->screen), - si->splash_dialog, cmap, - sp->background, - &sp->logo_pixels, &sp->logo_npixels, - &sp->logo_clipmask, True); - - XMapRaised (si->dpy, si->splash_dialog); - XSync (si->dpy, False); - - si->sp_data = sp; - - sp->timer = XtAppAddTimeOut (si->app, si->prefs.splash_duration, - unsplash_timer, (XtPointer) si); - - draw_splash_window (si); - XSync (si->dpy, False); -} - - -static void -draw_splash_window (saver_info *si) -{ - splash_dialog_data *sp = si->sp_data; - XGCValues gcv; - GC gc1, gc2; - int vspacing, height; - int x1, x2, x3, y1, y2; - int sw; - -#ifdef PREFS_BUTTON - int hspacing; - int nbuttons = 3; -#endif /* !PREFS_BUTTON */ - - height = (sp->heading_font->ascent + sp->heading_font->descent + - sp->body_font->ascent + sp->body_font->descent + - sp->body_font->ascent + sp->body_font->descent + - sp->button_font->ascent + sp->button_font->descent); - vspacing = ((sp->height - - (4 * sp->shadow_width) - - (2 * sp->internal_border) - - height) / 5); - if (vspacing < 0) vspacing = 0; - if (vspacing > (sp->heading_font->ascent * 2)) - vspacing = (sp->heading_font->ascent * 2); - - gcv.foreground = sp->foreground; - gc1 = XCreateGC (si->dpy, si->splash_dialog, GCForeground, &gcv); - gc2 = XCreateGC (si->dpy, si->splash_dialog, GCForeground, &gcv); - x1 = sp->logo_width; - x3 = sp->width - (sp->shadow_width * 2); - y1 = sp->internal_border; - - /* top heading - */ - XSetFont (si->dpy, gc1, sp->heading_font->fid); - sw = string_width (sp->heading_font, sp->heading_label); - x2 = (x1 + ((x3 - x1 - sw) / 2)); - y1 += sp->heading_font->ascent; - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, - sp->heading_label, strlen(sp->heading_label)); - y1 += sp->heading_font->descent; - - /* text below top heading - */ - XSetFont (si->dpy, gc1, sp->body_font->fid); - y1 += vspacing + sp->body_font->ascent; - sw = string_width (sp->body_font, sp->body_label); - x2 = (x1 + ((x3 - x1 - sw) / 2)); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, - sp->body_label, strlen(sp->body_label)); - y1 += sp->body_font->descent; - - y1 += sp->body_font->ascent; - sw = string_width (sp->body_font, sp->body2_label); - x2 = (x1 + ((x3 - x1 - sw) / 2)); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, - sp->body2_label, strlen(sp->body2_label)); - y1 += sp->body_font->descent; - - if (sp->body3_label) - { - XSetFont (si->dpy, gc1, sp->heading_font->fid); - y1 += sp->heading_font->ascent + sp->heading_font->descent; - y1 += sp->heading_font->ascent; - sw = string_width (sp->heading_font, sp->body3_label); - x2 = (x1 + ((x3 - x1 - sw) / 2)); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, - sp->body3_label, strlen(sp->body3_label)); - y1 += sp->heading_font->descent + sp->heading_font->ascent; - sw = string_width (sp->heading_font, sp->body4_label); - x2 = (x1 + ((x3 - x1 - sw) / 2)); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y1, - sp->body4_label, strlen(sp->body4_label)); - y1 += sp->heading_font->descent; - XSetFont (si->dpy, gc1, sp->body_font->fid); - } - - /* The buttons - */ - XSetForeground (si->dpy, gc1, sp->button_foreground); - XSetForeground (si->dpy, gc2, sp->button_background); - -/* y1 += (vspacing * 2);*/ - y1 = sp->height - sp->internal_border - sp->button_height; - - x1 += sp->internal_border; - y2 = (y1 + ((sp->button_height - - (sp->button_font->ascent + sp->button_font->descent)) - / 2) - + sp->button_font->ascent); -#ifdef PREFS_BUTTON - hspacing = ((sp->width - x1 - (sp->shadow_width * 2) - - sp->internal_border - (sp->button_width * nbuttons)) - / 2); -#endif - - x2 = x1 + ((sp->button_width - string_width(sp->button_font, sp->demo_label)) - / 2); - XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1, - sp->button_width, sp->button_height); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2, - sp->demo_label, strlen(sp->demo_label)); - sp->demo_button_x = x1; - sp->demo_button_y = y1; - -#ifdef PREFS_BUTTON - x1 += hspacing + sp->button_width; - x2 = x1 + ((sp->button_width - string_width(sp->button_font,sp->prefs_label)) - / 2); - XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1, - sp->button_width, sp->button_height); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2, - sp->prefs_label, strlen(sp->prefs_label)); - sp->prefs_button_x = x1; - sp->prefs_button_y = y1; -#endif /* PREFS_BUTTON */ - -#ifdef PREFS_BUTTON - x1 += hspacing + sp->button_width; -#else /* !PREFS_BUTTON */ - x1 = (sp->width - sp->button_width - - sp->internal_border - (sp->shadow_width * 2)); -#endif /* !PREFS_BUTTON */ - - x2 = x1 + ((sp->button_width - string_width(sp->button_font,sp->help_label)) - / 2); - XFillRectangle (si->dpy, si->splash_dialog, gc2, x1, y1, - sp->button_width, sp->button_height); - XDrawString (si->dpy, si->splash_dialog, gc1, x2, y2, - sp->help_label, strlen(sp->help_label)); - sp->help_button_x = x1; - sp->help_button_y = y1; - - - /* The logo - */ - x1 = sp->shadow_width * 6; - y1 = sp->shadow_width * 6; - x2 = sp->logo_width - (sp->shadow_width * 12); - y2 = sp->logo_height - (sp->shadow_width * 12); - - if (sp->logo_pixmap) - { - Window root; - int x, y; - unsigned int w, h, bw, d; - XGetGeometry (si->dpy, sp->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d); - XSetForeground (si->dpy, gc1, sp->foreground); - XSetBackground (si->dpy, gc1, sp->background); - XSetClipMask (si->dpy, gc1, sp->logo_clipmask); - XSetClipOrigin (si->dpy, gc1, x1 + ((x2 - (int)w) /2), y1 + ((y2 - (int)h) / 2)); - if (d == 1) - XCopyPlane (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1, - 0, 0, w, h, - x1 + ((x2 - (int)w) / 2), - y1 + ((y2 - (int)h) / 2), - 1); - else - XCopyArea (si->dpy, sp->logo_pixmap, si->splash_dialog, gc1, - 0, 0, w, h, - x1 + ((x2 - (int)w) / 2), - y1 + ((y2 - (int)h) / 2)); - } - - /* Solid border inside the logo box. */ -#if 0 - XSetForeground (si->dpy, gc1, sp->foreground); - XDrawRectangle (si->dpy, si->splash_dialog, gc1, x1, y1, x2-1, y2-1); -#endif - - /* The shadow around the logo - */ - draw_shaded_rectangle (si->dpy, si->splash_dialog, - sp->shadow_width * 4, - sp->shadow_width * 4, - sp->logo_width - (sp->shadow_width * 8), - sp->logo_height - (sp->shadow_width * 8), - sp->shadow_width, - sp->shadow_bottom, sp->shadow_top); - - /* The shadow around the whole window - */ - draw_shaded_rectangle (si->dpy, si->splash_dialog, - 0, 0, sp->width, sp->height, sp->shadow_width, - sp->shadow_top, sp->shadow_bottom); - - XFreeGC (si->dpy, gc1); - XFreeGC (si->dpy, gc2); - - update_splash_window (si); -} - - -static void -update_splash_window (saver_info *si) -{ - splash_dialog_data *sp = si->sp_data; - int pressed; - if (!sp) return; - pressed = sp->pressed; - - /* The shadows around the buttons - */ - draw_shaded_rectangle (si->dpy, si->splash_dialog, - sp->demo_button_x, sp->demo_button_y, - sp->button_width, sp->button_height, sp->shadow_width, - (pressed == 1 ? sp->shadow_bottom : sp->shadow_top), - (pressed == 1 ? sp->shadow_top : sp->shadow_bottom)); -#ifdef PREFS_BUTTON - draw_shaded_rectangle (si->dpy, si->splash_dialog, - sp->prefs_button_x, sp->prefs_button_y, - sp->button_width, sp->button_height, sp->shadow_width, - (pressed == 2 ? sp->shadow_bottom : sp->shadow_top), - (pressed == 2 ? sp->shadow_top : sp->shadow_bottom)); -#endif /* PREFS_BUTTON */ - draw_shaded_rectangle (si->dpy, si->splash_dialog, - sp->help_button_x, sp->help_button_y, - sp->button_width, sp->button_height, sp->shadow_width, - (pressed == 3 ? sp->shadow_bottom : sp->shadow_top), - (pressed == 3 ? sp->shadow_top : sp->shadow_bottom)); -} - -static void -destroy_splash_window (saver_info *si) -{ - splash_dialog_data *sp = si->sp_data; - saver_screen_info *ssi = sp->prompt_screen; - Colormap cmap = DefaultColormapOfScreen (ssi->screen); - Pixel black = BlackPixelOfScreen (ssi->screen); - Pixel white = WhitePixelOfScreen (ssi->screen); - - if (sp->timer) - XtRemoveTimeOut (sp->timer); - - if (si->splash_dialog) - { - XDestroyWindow (si->dpy, si->splash_dialog); - si->splash_dialog = 0; - } - - if (sp->heading_label) free (sp->heading_label); - if (sp->body_label) free (sp->body_label); - if (sp->body2_label) free (sp->body2_label); - if (sp->body3_label) free (sp->body3_label); - if (sp->body4_label) free (sp->body4_label); - if (sp->demo_label) free (sp->demo_label); -#ifdef PREFS_BUTTON - if (sp->prefs_label) free (sp->prefs_label); -#endif /* PREFS_BUTTON */ - if (sp->help_label) free (sp->help_label); - - if (sp->heading_font) XFreeFont (si->dpy, sp->heading_font); - if (sp->body_font) XFreeFont (si->dpy, sp->body_font); - if (sp->button_font) XFreeFont (si->dpy, sp->button_font); - - if (sp->foreground != black && sp->foreground != white) - XFreeColors (si->dpy, cmap, &sp->foreground, 1, 0L); - if (sp->background != black && sp->background != white) - XFreeColors (si->dpy, cmap, &sp->background, 1, 0L); - if (sp->button_foreground != black && sp->button_foreground != white) - XFreeColors (si->dpy, cmap, &sp->button_foreground, 1, 0L); - if (sp->button_background != black && sp->button_background != white) - XFreeColors (si->dpy, cmap, &sp->button_background, 1, 0L); - if (sp->shadow_top != black && sp->shadow_top != white) - XFreeColors (si->dpy, cmap, &sp->shadow_top, 1, 0L); - if (sp->shadow_bottom != black && sp->shadow_bottom != white) - XFreeColors (si->dpy, cmap, &sp->shadow_bottom, 1, 0L); - - if (sp->logo_pixmap) - XFreePixmap (si->dpy, sp->logo_pixmap); - if (sp->logo_clipmask) - XFreePixmap (si->dpy, sp->logo_clipmask); - if (sp->logo_pixels) - { - if (sp->logo_npixels) - XFreeColors (si->dpy, cmap, sp->logo_pixels, sp->logo_npixels, 0L); - free (sp->logo_pixels); - sp->logo_pixels = 0; - sp->logo_npixels = 0; - } - - memset (sp, 0, sizeof(*sp)); - free (sp); - si->sp_data = 0; -} - -void -handle_splash_event (saver_info *si, XEvent *event) -{ - splash_dialog_data *sp = si->sp_data; - saver_screen_info *ssi; - int which = 0; - if (!sp) return; - ssi = sp->prompt_screen; - - switch (event->xany.type) - { - case Expose: - draw_splash_window (si); - break; - - case ButtonPress: case ButtonRelease: - - if (event->xbutton.x >= sp->demo_button_x && - event->xbutton.x < sp->demo_button_x + sp->button_width && - event->xbutton.y >= sp->demo_button_y && - event->xbutton.y < sp->demo_button_y + sp->button_height) - which = 1; - -#ifdef PREFS_BUTTON - else if (event->xbutton.x >= sp->prefs_button_x && - event->xbutton.x < sp->prefs_button_x + sp->button_width && - event->xbutton.y >= sp->prefs_button_y && - event->xbutton.y < sp->prefs_button_y + sp->button_height) - which = 2; -#endif /* PREFS_BUTTON */ - - else if (event->xbutton.x >= sp->help_button_x && - event->xbutton.x < sp->help_button_x + sp->button_width && - event->xbutton.y >= sp->help_button_y && - event->xbutton.y < sp->help_button_y + sp->button_height) - which = 3; - - if (event->xany.type == ButtonPress) - { - sp->pressed = which; - update_splash_window (si); - if (which == 0) - XBell (si->dpy, False); - } - else if (event->xany.type == ButtonRelease) - { - if (which && sp->pressed == which) - { - destroy_splash_window (si); - sp = si->sp_data; - switch (which) - { - case 1: do_demo (ssi); break; -#ifdef PREFS_BUTTON - case 2: do_prefs (ssi); break; -#endif /* PREFS_BUTTON */ - case 3: do_help (ssi); break; - default: abort(); - } - } - else if (which == 0 && sp->pressed == 0) - { - /* click and release on the window but not in a button: - treat that as "dismiss the splash dialog." */ - destroy_splash_window (si); - sp = si->sp_data; - } - if (sp) sp->pressed = 0; - update_splash_window (si); - } - break; - - default: - break; - } -} - -static void -unsplash_timer (XtPointer closure, XtIntervalId *id) -{ - saver_info *si = (saver_info *) closure; - if (si && si->sp_data) - destroy_splash_window (si); -} - - -/* Button callbacks */ - -#ifdef VMS -# define pid_t int -# define fork vfork -#endif /* VMS */ - - -static void -do_demo (saver_screen_info *ssi) -{ - saver_info *si = ssi->global; - saver_preferences *p = &si->prefs; - const char *cmd = p->demo_command; - - if (cmd && *cmd) - fork_and_exec (ssi, cmd); - else - fprintf (stderr, "%s: no demo-mode command has been specified.\n", - blurb()); -} - -#ifdef PREFS_BUTTON -static void -do_prefs (saver_screen_info *ssi) -{ - saver_info *si = ssi->global; - saver_preferences *p = &si->prefs; - const char *cmd = p->prefs_command; - - if (cmd && *cmd) - fork_and_exec (ssi, cmd); - else - fprintf (stderr, "%s: no preferences command has been specified.\n", - blurb()); -} -#endif /* PREFS_BUTTON */ - -static void -do_help (saver_screen_info *ssi) -{ - saver_info *si = ssi->global; - saver_preferences *p = &si->prefs; - char *help_command = 0; - - if (!p->load_url_command || !*p->load_url_command) - { - fprintf (stderr, "%s: no URL command has been specified.\n", blurb()); - return; - } - if (!p->help_url || !*p->help_url) - { - fprintf (stderr, "%s: no Help URL has been specified.\n", blurb()); - return; - } - - help_command = (char *) malloc (strlen (p->load_url_command) + - (strlen (p->help_url) * 4) + 10); - sprintf (help_command, p->load_url_command, - p->help_url, p->help_url, p->help_url, p->help_url); - - fork_and_exec (ssi, help_command); - free (help_command); -} diff --git a/driver/test-apm.c b/driver/test-apm.c deleted file mode 100644 index 6b87c7e..0000000 --- a/driver/test-apm.c +++ /dev/null @@ -1,101 +0,0 @@ -/* test-apm.c --- playing with the APM library. - * xscreensaver, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif - -#include <stdio.h> -#include <time.h> -#include <sys/time.h> - -#include <X11/Xlib.h> -#include <X11/Intrinsic.h> - -#include <apm.h> - -#define countof(x) (sizeof((x))/sizeof(*(x))) - - -char *progname = 0; -char *progclass = "XScreenSaver"; - -static const char * -blurb (void) -{ - static char buf[255]; - time_t now = time ((time_t *) 0); - char *ct = (char *) ctime (&now); - int n = strlen(progname); - if (n > 100) n = 99; - strncpy(buf, progname, n); - buf[n++] = ':'; - buf[n++] = ' '; - strncpy(buf+n, ct+11, 8); - strcpy(buf+n+9, ": "); - return buf; -} - -static void -apm_cb (XtPointer closure, int *fd, XtInputId *id) -{ - apm_event_t events[100]; - int n, i; - while ((n = apm_get_events (*fd, 0, events, countof(events))) - > 0) - for (i = 0; i < n; i++) - { - fprintf (stderr, "%s: APM event 0x%x: %s.\n", blurb(), - events[i], apm_event_name (events[i])); -#if 0 - switch (events[i]) - { - case APM_SYS_STANDBY: - case APM_USER_STANDBY: - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - case APM_CRITICAL_SUSPEND: - break; - } -#endif - } -} - -int -main (int argc, char **argv) -{ - XtAppContext app; - Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, - &argc, argv, 0, 0, 0); - Display *dpy = XtDisplay (toplevel_shell); - int fd; - XtInputId id; - XtGetApplicationNameAndClass (dpy, &progname, &progclass); - - fd = apm_open (); - if (fd <= 0) - { - fprintf (stderr, "%s: couldn't initialize APM.\n", blurb()); - exit (1); - } - - id = XtAppAddInput(app, fd, - (XtPointer) (XtInputReadMask | XtInputWriteMask), - apm_cb, 0); - XtAppMainLoop (app); - exit (0); -} diff --git a/driver/test-mlstring.c b/driver/test-mlstring.c deleted file mode 100644 index e269a00..0000000 --- a/driver/test-mlstring.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * (c) 2007, Quest Software, Inc. All rights reserved. - * - * This file is part of XScreenSaver, - * Copyright (c) 1993-2004 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#include "mlstring.c" /* hokey, but whatever */ - -#define WRAP_WIDTH_PX 100 - -#undef Bool -#undef True -#undef False -typedef int Bool; -#define True 1 -#define False 0 - -#define SKIPPED -1 -#define SUCCESS 0 -#define FAILURE 1 - -#define FAIL(msg, ...) \ - do { \ - ++failcount; \ - fprintf(stderr, "[FAIL] "); \ - fprintf(stderr, msg, __VA_ARGS__); \ - putc('\n', stderr); \ - return FAILURE; \ - } while (0) - -#define SUCCEED(testname) \ - do { \ - fprintf(stderr, "[SUCCESS] %s\n", (testname)); \ - } while (0) - -#define SKIP(testname) \ - do { \ - fprintf(stderr, "[SKIPPED] %s\n", (testname)); \ - } while (0) - -extern mlstring* mlstring_allocate(const char *msg); -extern void mlstring_wrap(mlstring *mstr, XFontStruct *font, Dimension width); - -static int failcount = 0; - -static char *mlstring_to_cstr(const mlstring *mlstr) { - char *cstr; - size_t cstrlen = 0, alloclen = 1024; - const struct mlstr_line *line; - - cstr = malloc(alloclen); - if (!cstr) - return NULL; - cstr[0] = '\0'; - - for (line = mlstr->lines; line; line = line->next_line) { - /* Extend the buffer if necessary. */ - if (cstrlen + strlen(line->line) + 1 > alloclen) { - cstr = realloc(cstr, alloclen *= 2); - if (!cstr) - return NULL; - } - - /* If this is not the first line */ - if (line != mlstr->lines) { - /* Append a newline character */ - cstr[cstrlen] = '\n'; - ++cstrlen; - cstr[cstrlen] = '\0'; - } - - strcat(cstr, line->line); - cstrlen += strlen(line->line); - } - return cstr; -} - -/* Pass -1 for expect_min or expect_exact to not check that value. - * expect_empty_p means an empty line is expected at some point in the string. - * Also ensures that the string was not too wide after wrapping. */ -static int mlstring_expect_lines(const mlstring *mlstr, int expect_min, int expect_exact, Bool expect_empty_p) -{ - int count; - Bool got_empty_line = False; - const struct mlstr_line *line = mlstr->lines; - - for (count = 0; line; line = line->next_line) { - if (line->line[0] == '\0') { - if (!expect_empty_p) - FAIL("Not expecting empty lines, but got one on line %d of [%s]", count + 1, mlstring_to_cstr(mlstr)); - got_empty_line = True; - } - ++count; - } - - if (expect_empty_p && !got_empty_line) - FAIL("Expecting an empty line, but none found in [%s]", mlstring_to_cstr(mlstr)); - - if (expect_exact != -1 && expect_exact != count) - FAIL("Expected %d lines, got %d", expect_exact, count); - - if (expect_min != -1 && count < expect_min) - FAIL("Expected at least %d lines, got %d", expect_min, count); - - return SUCCESS; -} - -static int mlstring_expect(const char *msg, int expect_lines, const mlstring *mlstr, Bool expect_empty_p) -{ - char *str, *str_top; - const struct mlstr_line *cur; - int linecount = 0; - - /* Duplicate msg so we can chop it up */ - str_top = strdup(msg); - if (!str_top) - return SKIPPED; - - /* Replace all newlines with NUL */ - str = str_top; - while ((str = strchr(str, '\n'))) - *str++ = '\0'; - - /* str is now used to point to the expected string */ - str = str_top; - - for (cur = mlstr->lines; cur; cur = cur->next_line) - { - ++linecount; - if (strcmp(cur->line, str)) - FAIL("lines didn't match; expected [%s], got [%s]", str, cur->line); - - str += strlen(str) + 1; /* Point to the next expected string */ - } - - free(str_top); - - return mlstring_expect_lines(mlstr, -1, expect_lines, expect_empty_p); -} - -/* Ensures that the width has been set properly after wrapping */ -static int check_width(const char *msg, const mlstring *mlstr) { - if (mlstr->overall_width == 0) - FAIL("Overall width was zero for string [%s]", msg); - - if (mlstr->overall_width > WRAP_WIDTH_PX) - FAIL("Overall width was %hu but the maximum wrap width was %d", mlstr->overall_width, WRAP_WIDTH_PX); - - return SUCCESS; -} - -/* FAIL() actually returns the wrong return codes in main, but it - * prints a message which is what we want. */ - -#define TRY_NEW(str, numl, expect_empty) \ - do { \ - mlstr = mlstring_allocate((str)); \ - if (!mlstr) \ - FAIL("%s", #str); \ - if (SUCCESS == mlstring_expect((str), (numl), mlstr, (expect_empty))) \ - SUCCEED(#str); \ - free(mlstr); \ - } while (0) - -/* Expects an XFontStruct* font, and tries to wrap to 100px */ -#define TRY_WRAP(str, minl, expect_empty) \ - do { \ - mltest = mlstring_allocate((str)); \ - if (!mltest) \ - SKIP(#str); \ - else { \ - mlstring_wrap(mltest, font, WRAP_WIDTH_PX); \ - check_width((str), mltest); \ - if (SUCCESS == mlstring_expect_lines(mltest, (minl), -1, (expect_empty))) \ - SUCCEED(#str); \ - free(mltest); \ - mltest = NULL; \ - } \ - } while (0) - - -/* Ideally this function would use stub functions rather than real Xlib. - * Then it would be possible to test for exact line counts, which would be - * more reliable. - * It also doesn't handle Xlib errors. - * - * Don't print anything based on the return value of this function, it only - * returns a value so that I can use the FAIL() macro without warning. - * - * Anyone who understands this function wins a cookie ;) - */ -static int test_wrapping(void) -{ - Display *dpy = NULL; - XFontStruct *font = NULL; - mlstring *mltest = NULL; - int ok = 0; - int chars_per_line, chars_first_word, i; - - const char *test_short = "a"; - const char *test_hardwrap = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - const char *test_withnewlines = "a\nb"; - char *test_softwrap = NULL; - - dpy = XOpenDisplay(NULL); - if (!dpy) - goto end; - - font = XLoadQueryFont(dpy, "fixed"); - if (!font) - goto end; - - TRY_WRAP(test_short, 1, False); - TRY_WRAP(test_hardwrap, 2, False); - TRY_WRAP(test_withnewlines, 2, False); - - /* See if wrapping splits on word boundaries like it should */ - chars_per_line = WRAP_WIDTH_PX / font->max_bounds.width; - if (chars_per_line < 3) - goto end; - - /* Allocate for 2 lines + \0 */ - test_softwrap = malloc(chars_per_line * 2 + 1); - if (!test_softwrap) - goto end; - - /* 2 = strlen(' a'); that is, the minimum space required to start a new word - * on the same line. */ - chars_first_word = chars_per_line - 2; - - for (i = 0; i < chars_first_word; ++i) { - test_softwrap[i] = 'a'; /* first word */ - test_softwrap[i + chars_per_line] = 'b'; /* second word */ - } - /* space between first & second words */ - test_softwrap[chars_first_word] = ' '; - /* first char of second word (last char of first line) */ - test_softwrap[chars_first_word + 1] = 'b'; - /* after second word */ - test_softwrap[chars_per_line * 2] = '\0'; - - mltest = mlstring_allocate(test_softwrap); - mlstring_wrap(mltest, font, WRAP_WIDTH_PX); - - /* reusing 'i' for a moment here to make freeing mltest easier */ - i = strlen(mltest->lines->line); - free(mltest); - - if (i != chars_first_word) - FAIL("Soft wrap failed, expected the first line to be %d chars, but it was %d.", chars_first_word, i); - SUCCEED("Soft wrap"); - - ok = 1; - -end: - if (test_softwrap) - free(test_softwrap); - - if (font) - XFreeFont(dpy, font); - - if (dpy) - XCloseDisplay(dpy); - - if (!ok) - SKIP("wrapping"); - - return ok ? SUCCESS : SKIPPED; /* Unused, actually */ -} - - -int main(int argc, char *argv[]) -{ - const char *oneline = "1Foo"; - const char *twolines = "2Foo\nBar"; - const char *threelines = "3Foo\nBar\nWhippet"; - const char *trailnewline = "4Foo\n"; - const char *trailnewlines = "5Foo\n\n"; - const char *embeddednewlines = "6Foo\n\nBar"; - mlstring *mlstr; - - TRY_NEW(oneline, 1, False); - TRY_NEW(twolines, 2, False); - TRY_NEW(threelines, 3, False); - TRY_NEW(trailnewline, 2, True); - TRY_NEW(trailnewlines, 3, True); - TRY_NEW(embeddednewlines, 3, True); - - (void) test_wrapping(); - - fprintf(stdout, "%d test failures.\n", failcount); - - return !!failcount; -} - -/* vim:ts=8:sw=2:noet - */ diff --git a/driver/timers.c b/driver/timers.c deleted file mode 100644 index 5aa568c..0000000 --- a/driver/timers.c +++ /dev/null @@ -1,1794 +0,0 @@ -/* timers.c --- detecting when the user is idle, and other timer-related tasks. - * xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <X11/Xlib.h> -#include <X11/Intrinsic.h> -#include <X11/Xos.h> -#include <X11/Xatom.h> -#include <time.h> -#include <sys/time.h> -#ifdef HAVE_XMU -# ifndef VMS -# include <X11/Xmu/Error.h> -# else /* VMS */ -# include <Xmu/Error.h> -# endif /* VMS */ -# else /* !HAVE_XMU */ -# include "xmu.h" -#endif /* !HAVE_XMU */ - -#ifdef HAVE_XIDLE_EXTENSION -#include <X11/extensions/xidle.h> -#endif /* HAVE_XIDLE_EXTENSION */ - -#ifdef HAVE_MIT_SAVER_EXTENSION -#include <X11/extensions/scrnsaver.h> -#endif /* HAVE_MIT_SAVER_EXTENSION */ - -#ifdef HAVE_SGI_SAVER_EXTENSION -#include <X11/extensions/XScreenSaver.h> -#endif /* HAVE_SGI_SAVER_EXTENSION */ - -#ifdef HAVE_RANDR -#include <X11/extensions/Xrandr.h> -#endif /* HAVE_RANDR */ - -#include "xscreensaver.h" - -#undef ABS -#define ABS(x)((x)<0?-(x):(x)) - -#undef MAX -#define MAX(x,y)((x)>(y)?(x):(y)) - - -#ifdef HAVE_PROC_INTERRUPTS -static Bool proc_interrupts_activity_p (saver_info *si); -#endif /* HAVE_PROC_INTERRUPTS */ - -static void check_for_clock_skew (saver_info *si); - - -void -idle_timer (XtPointer closure, XtIntervalId *id) -{ - saver_info *si = (saver_info *) closure; - - /* What an amazingly shitty design. Not only does Xt execute timeout - events from XtAppNextEvent() instead of from XtDispatchEvent(), but - there is no way to tell Xt to block until there is an X event OR a - timeout happens. Once your timeout proc is called, XtAppNextEvent() - still won't return until a "real" X event comes in. - - So this function pushes a stupid, gratuitous, unnecessary event back - on the event queue to force XtAppNextEvent to return Right Fucking Now. - When the code in sleep_until_idle() sees an event of type XAnyEvent, - which the server never generates, it knows that a timeout has occurred. - */ - XEvent fake_event; - fake_event.type = 0; /* XAnyEvent type, ignored. */ - fake_event.xany.display = si->dpy; - fake_event.xany.window = 0; - XPutBackEvent (si->dpy, &fake_event); - - /* If we are the timer that just went off, clear the pointer to the id. */ - if (id) - { - if (si->timer_id && *id != si->timer_id) - abort(); /* oops, scheduled timer twice?? */ - si->timer_id = 0; - } -} - - -void -schedule_wakeup_event (saver_info *si, Time when, Bool verbose_p) -{ - if (si->timer_id) - { - if (verbose_p) - fprintf (stderr, "%s: idle_timer already running\n", blurb()); - return; - } - - /* Wake up periodically to ask the server if we are idle. */ - si->timer_id = XtAppAddTimeOut (si->app, when, idle_timer, - (XtPointer) si); - - if (verbose_p) - fprintf (stderr, "%s: starting idle_timer (%ld, %ld)\n", - blurb(), when, si->timer_id); -} - - -static void -notice_events (saver_info *si, Window window, Bool top_p) -{ - saver_preferences *p = &si->prefs; - XWindowAttributes attrs; - unsigned long events; - Window root, parent, *kids; - unsigned int nkids; - int screen_no; - - if (XtWindowToWidget (si->dpy, window)) - /* If it's one of ours, don't mess up its event mask. */ - return; - - if (!XQueryTree (si->dpy, window, &root, &parent, &kids, &nkids)) - return; - if (window == root) - top_p = False; - - /* Figure out which screen this window is on, for the diagnostics. */ - for (screen_no = 0; screen_no < si->nscreens; screen_no++) - if (root == RootWindowOfScreen (si->screens[screen_no].screen)) - break; - - XGetWindowAttributes (si->dpy, window, &attrs); - events = ((attrs.all_event_masks | attrs.do_not_propagate_mask) - & (KeyPressMask | PropertyChangeMask)); - - /* Select for SubstructureNotify on all windows. - Select for PropertyNotify on all windows. - Select for KeyPress on all windows that already have it selected. - - Note that we can't select for ButtonPress, because of X braindamage: - only one client at a time may select for ButtonPress on a given - window, though any number can select for KeyPress. Someone explain - *that* to me. - - So, if the user spends a while clicking the mouse without ever moving - the mouse or touching the keyboard, we won't know that they've been - active, and the screensaver will come on. That sucks, but I don't - know how to get around it. - - Since X presents mouse wheels as clicks, this applies to those, too: - scrolling through a document using only the mouse wheel doesn't - count as activity... Fortunately, /proc/interrupts helps, on - systems that have it. Oh, if it's a PS/2 mouse, not serial or USB. - This sucks! - */ - XSelectInput (si->dpy, window, - SubstructureNotifyMask | PropertyChangeMask | events); - - if (top_p && p->debug_p && (events & KeyPressMask)) - { - /* Only mention one window per tree (hack hack). */ - fprintf (stderr, "%s: %d: selected KeyPress on 0x%lX\n", - blurb(), screen_no, (unsigned long) window); - top_p = False; - } - - if (kids) - { - while (nkids) - notice_events (si, kids [--nkids], top_p); - XFree ((char *) kids); - } -} - - -int -BadWindow_ehandler (Display *dpy, XErrorEvent *error) -{ - /* When we notice a window being created, we spawn a timer that waits - 30 seconds or so, and then selects events on that window. This error - handler is used so that we can cope with the fact that the window - may have been destroyed <30 seconds after it was created. - */ - if (error->error_code == BadWindow || - error->error_code == BadMatch || - error->error_code == BadDrawable) - return 0; - else - return saver_ehandler (dpy, error); -} - - -struct notice_events_timer_arg { - saver_info *si; - Window w; -}; - -static void -notice_events_timer (XtPointer closure, XtIntervalId *id) -{ - struct notice_events_timer_arg *arg = - (struct notice_events_timer_arg *) closure; - - XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler); - - saver_info *si = arg->si; - Window window = arg->w; - - free(arg); - notice_events (si, window, True); - XSync (si->dpy, False); - XSetErrorHandler (old_handler); -} - -void -start_notice_events_timer (saver_info *si, Window w, Bool verbose_p) -{ - saver_preferences *p = &si->prefs; - struct notice_events_timer_arg *arg = - (struct notice_events_timer_arg *) malloc(sizeof(*arg)); - arg->si = si; - arg->w = w; - XtAppAddTimeOut (si->app, p->notice_events_timeout, notice_events_timer, - (XtPointer) arg); - - if (verbose_p) - fprintf (stderr, "%s: starting notice_events_timer for 0x%X (%lu)\n", - blurb(), (unsigned int) w, p->notice_events_timeout); -} - - -/* When the screensaver is active, this timer will periodically change - the running program. - */ -void -cycle_timer (XtPointer closure, XtIntervalId *id) -{ - saver_info *si = (saver_info *) closure; - saver_preferences *p = &si->prefs; - Time how_long = p->cycle; - - if (si->selection_mode > 0 && - screenhack_running_p (si)) - /* If we're in "SELECT n" mode, the cycle timer going off will just - restart this same hack again. There's not much point in doing this - every 5 or 10 minutes, but on the other hand, leaving one hack running - for days is probably not a great idea, since they tend to leak and/or - crash. So, restart the thing once an hour. */ - how_long = 1000 * 60 * 60; - - if (si->dbox_up_p) - { - if (p->verbose_p) - fprintf (stderr, "%s: dialog box up; delaying hack change.\n", - blurb()); - how_long = 30000; /* 30 secs */ - } - else - { - int i; - maybe_reload_init_file (si); - for (i = 0; i < si->nscreens; i++) - kill_screenhack (&si->screens[i]); - - raise_window (si, True, True, False); - - if (!si->throttled_p) - for (i = 0; i < si->nscreens; i++) - spawn_screenhack (&si->screens[i]); - else - { - if (p->verbose_p) - fprintf (stderr, "%s: not launching new hack (throttled.)\n", - blurb()); - } - } - - if (how_long > 0) - { - si->cycle_id = XtAppAddTimeOut (si->app, how_long, cycle_timer, - (XtPointer) si); - - if (p->debug_p) - fprintf (stderr, "%s: starting cycle_timer (%ld, %ld)\n", - blurb(), how_long, si->cycle_id); - } - else - { - if (p->debug_p) - fprintf (stderr, "%s: not starting cycle_timer: how_long == %ld\n", - blurb(), (unsigned long) how_long); - } -} - - -void -activate_lock_timer (XtPointer closure, XtIntervalId *id) -{ - saver_info *si = (saver_info *) closure; - saver_preferences *p = &si->prefs; - - if (p->verbose_p) - fprintf (stderr, "%s: timed out; activating lock.\n", blurb()); - - if (!si->locked_p) - /* So that "xscreensaver-command -watch" reports the time that the - screen was locked, instead of duplicating the blank time. */ - si->blank_time = time ((time_t *) 0); - - set_locked_p (si, True); -} - - -/* Call this when user activity (or "simulated" activity) has been noticed. - */ -void -reset_timers (saver_info *si) -{ - saver_preferences *p = &si->prefs; - if (si->using_mit_saver_extension || si->using_sgi_saver_extension) - return; - - if (si->timer_id) - { - if (p->debug_p) - fprintf (stderr, "%s: killing idle_timer (%ld, %ld)\n", - blurb(), p->timeout, si->timer_id); - XtRemoveTimeOut (si->timer_id); - si->timer_id = 0; - } - - schedule_wakeup_event (si, p->timeout, p->debug_p); /* sets si->timer_id */ - - if (si->cycle_id) abort (); /* no cycle timer when inactive */ - - si->last_activity_time = time ((time_t *) 0); - - /* This will (hopefully, supposedly) tell the server to re-set its - DPMS timer. Without this, the -deactivate clientmessage would - prevent xscreensaver from blanking, but would not prevent the - monitor from powering down. */ -#if 0 - /* #### With some servers, this causes the screen to flicker every - time a key is pressed! Ok, I surrender. I give up on ever - having DPMS work properly. - */ - XForceScreenSaver (si->dpy, ScreenSaverReset); - - /* And if the monitor is already powered off, turn it on. - You'd think the above would do that, but apparently not? */ - monitor_power_on (si, True); -#endif - -} - - -/* Returns true if a mouse has moved since the last time we checked. - Small motions (of less than "hysteresis" pixels/second) are ignored. - */ -static Bool -device_pointer_moved_p (saver_info *si, poll_mouse_data *last_poll_mouse, - poll_mouse_data *this_poll_mouse, Bool mods_p, - const char *debug_type, int debug_id) -{ - saver_preferences *p = &si->prefs; - - unsigned int distance, dps; - unsigned long seconds = 0; - Bool moved_p = False; - - distance = MAX (ABS (last_poll_mouse->root_x - this_poll_mouse->root_x), - ABS (last_poll_mouse->root_y - this_poll_mouse->root_y)); - seconds = (this_poll_mouse->time - last_poll_mouse->time); - - - /* When the screen is blanked, we get MotionNotify events, but when not - blanked, we poll only every 5 seconds, and that's not enough resolution - to do hysteresis based on a 1 second interval. So, assume that any - motion we've seen during the 5 seconds when our eyes were closed happened - in the last 1 second instead. - */ - if (seconds > 1) seconds = 1; - - dps = (seconds <= 0 ? distance : (distance / seconds)); - - /* Motion only counts if the rate is more than N pixels per second. - */ - if (dps >= p->pointer_hysteresis && - distance > 0) - moved_p = True; - - /* If the mouse is not on this screen but used to be, that's motion. - If the mouse was not on this screen, but is now, that's motion. - */ - { - Bool on_screen_p = (this_poll_mouse->root_x != -1 && - this_poll_mouse->root_y != -1); - Bool was_on_screen_p = (last_poll_mouse->root_x != -1 && - last_poll_mouse->root_y != -1); - - if (on_screen_p != was_on_screen_p) - moved_p = True; - } - - if (p->debug_p && (distance != 0 || moved_p)) - { - fprintf (stderr, "%s: %s %d: pointer %s", blurb(), debug_type, debug_id, - (moved_p ? "moved: " : "ignored:")); - if (last_poll_mouse->root_x == -1) - fprintf (stderr, "off screen"); - else - fprintf (stderr, "%d,%d", - last_poll_mouse->root_x, - last_poll_mouse->root_y); - fprintf (stderr, " -> "); - if (this_poll_mouse->root_x == -1) - fprintf (stderr, "off screen"); - else - fprintf (stderr, "%d,%d", this_poll_mouse->root_x, - this_poll_mouse->root_y); - if (last_poll_mouse->root_x != -1 && this_poll_mouse->root_x != -1) - fprintf (stderr, " (%d,%d; %d/%lu=%d)", - ABS(last_poll_mouse->root_x - this_poll_mouse->root_x), - ABS(last_poll_mouse->root_y - this_poll_mouse->root_y), - distance, seconds, dps); - - fprintf (stderr, ".\n"); - } - - if (!moved_p && - mods_p && - this_poll_mouse->mask != last_poll_mouse->mask) - { - moved_p = True; - - if (p->debug_p) - fprintf (stderr, "%s: %s %d: modifiers changed: 0x%04x -> 0x%04x.\n", - blurb(), debug_type, debug_id, - last_poll_mouse->mask, this_poll_mouse->mask); - } - - last_poll_mouse->child = this_poll_mouse->child; - last_poll_mouse->mask = this_poll_mouse->mask; - - if (moved_p || seconds > 0) - { - last_poll_mouse->time = this_poll_mouse->time; - last_poll_mouse->root_x = this_poll_mouse->root_x; - last_poll_mouse->root_y = this_poll_mouse->root_y; - } - - return moved_p; -} - -/* Returns true if core mouse pointer has moved since the last time we checked. - */ -static Bool -pointer_moved_p (saver_screen_info *ssi, Bool mods_p) -{ - saver_info *si = ssi->global; - - Window root; - poll_mouse_data this_poll_mouse; - int x, y; - - /* don't check xinerama pseudo-screens. */ - if (!ssi->real_screen_p) return False; - - this_poll_mouse.time = time ((time_t *) 0); - - if (!XQueryPointer (si->dpy, ssi->screensaver_window, &root, - &this_poll_mouse.child, - &this_poll_mouse.root_x, &this_poll_mouse.root_y, - &x, &y, &this_poll_mouse.mask)) - { - /* If XQueryPointer() returns false, the mouse is not on this screen. - */ - this_poll_mouse.root_x = -1; - this_poll_mouse.root_y = -1; - this_poll_mouse.child = 0; - this_poll_mouse.mask = 0; - } - else - si->last_activity_screen = ssi; - - return device_pointer_moved_p(si, &(ssi->last_poll_mouse), &this_poll_mouse, - mods_p, "screen", ssi->number); -} - - -/* When we aren't using a server extension, this timer is used to periodically - wake up and poll the mouse position, which is possibly more reliable than - selecting motion events on every window. - */ -static void -check_pointer_timer (XtPointer closure, XtIntervalId *id) -{ - int i; - saver_info *si = (saver_info *) closure; - saver_preferences *p = &si->prefs; - Bool active_p = False; - - if (!si->using_proc_interrupts && - (si->using_xidle_extension || - si->using_mit_saver_extension || - si->using_sgi_saver_extension)) - /* If an extension is in use, we should not be polling the mouse. - Unless we're also checking /proc/interrupts, in which case, we should. - */ - abort (); - - if (id && *id == si->check_pointer_timer_id) /* this is us - it's expired */ - si->check_pointer_timer_id = 0; - - if (si->check_pointer_timer_id) /* only queue one at a time */ - XtRemoveTimeOut (si->check_pointer_timer_id); - - si->check_pointer_timer_id = /* now re-queue */ - XtAppAddTimeOut (si->app, p->pointer_timeout, check_pointer_timer, - (XtPointer) si); - - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - if (pointer_moved_p (ssi, True)) - active_p = True; - } - -#ifdef HAVE_PROC_INTERRUPTS - if (!active_p && - si->using_proc_interrupts && - proc_interrupts_activity_p (si)) - { - active_p = True; - } -#endif /* HAVE_PROC_INTERRUPTS */ - - if (active_p) - reset_timers (si); - - check_for_clock_skew (si); -} - - -/* An unfortunate situation is this: the saver is not active, because the - user has been typing. The machine is a laptop. The user closes the lid - and suspends it. The CPU halts. Some hours later, the user opens the - lid. At this point, Xt's timers will fire, and xscreensaver will blank - the screen. - - So far so good -- well, not really, but it's the best that we can do, - since the OS doesn't send us a signal *before* shutdown -- but if the - user had delayed locking (lockTimeout > 0) then we should start off - in the locked state, rather than only locking N minutes from when the - lid was opened. Also, eschewing fading is probably a good idea, to - clamp down as soon as possible. - - We only do this when we'd be polling the mouse position anyway. - This amounts to an assumption that machines with APM support also - have /proc/interrupts. - - Now here's a thing that sucks about this: if the user actually changes - the time of the machine, it will either trigger or delay the triggering - of a lock. On most systems, that requires root, but I'll bet at least - some GUI configs let non-root do it. Also, NTP attacks. - - On Linux 2.6.39+ systems, there exists clock_gettime(CLOCK_BOOTTIME) - which would allow us to detect the "laptop CPU had been halted" state - independently of changes in wall-clock time. But of course that's not - portable. - - When the wall clock changes, what do Xt timers do, anyway? If I have - a timer set for 30 seconds from now, and adjust the wall clock +15 seconds, - does the timer fire 30 seconds from now or 15? I actually have no idea. - It does not appear to be specified. - */ -static void -check_for_clock_skew (saver_info *si) -{ - saver_preferences *p = &si->prefs; - time_t now = time ((time_t *) 0); - long shift = now - si->last_wall_clock_time; - - if (p->debug_p) - { - int i = (si->last_wall_clock_time == 0 ? 0 : shift); - fprintf (stderr, - "%s: checking wall clock for hibernation (%d:%02d:%02d).\n", - blurb(), - (i / (60 * 60)), ((i / 60) % 60), (i % 60)); - } - - if (si->last_wall_clock_time != 0 && - shift > (p->timeout / 1000)) - { - if (p->verbose_p) - fprintf (stderr, "%s: wall clock has jumped by %ld:%02ld:%02ld%s\n", - blurb(), - (shift / (60 * 60)), ((shift / 60) % 60), (shift % 60), - (p->mode == DONT_BLANK ? " while saver disabled" : "")); - - /* If the saver is entirely disabled, there's no need to do the - emergency-blank-and-lock thing. - */ - if (p->mode != DONT_BLANK) - { - si->emergency_lock_p = True; - idle_timer ((XtPointer) si, 0); - } - } - - si->last_wall_clock_time = now; -} - - - -static void -dispatch_event (saver_info *si, XEvent *event) -{ - /* If this is for the splash dialog, pass it along. - Note that the password dialog is handled with its own event loop, - so events for that window will never come through here. - */ - if (si->splash_dialog && event->xany.window == si->splash_dialog) - handle_splash_event (si, event); - - XtDispatchEvent (event); -} - - -static void -swallow_unlock_typeahead_events (saver_info *si, XEvent *e) -{ - XEvent event; - char buf [100]; - int i = 0; - - memset (buf, 0, sizeof(buf)); - - event = *e; - - do - { - if (event.xany.type == KeyPress) - { - char s[2]; - int size = XLookupString ((XKeyEvent *) &event, s, 1, 0, 0); - if (size != 1) continue; - switch (*s) - { - case '\010': case '\177': /* Backspace */ - if (i > 0) i--; - break; - case '\025': case '\030': /* Erase line */ - case '\012': case '\015': /* Enter */ - case '\033': /* ESC */ - i = 0; - break; - case '\040': /* Space */ - if (i == 0) - break; /* ignore space at beginning of line */ - /* else, fall through */ - default: - buf [i++] = *s; - break; - } - } - - } while (i < sizeof(buf)-1 && - XCheckMaskEvent (si->dpy, KeyPressMask, &event)); - - buf[i] = 0; - - if (si->unlock_typeahead) - { - memset (si->unlock_typeahead, 0, strlen(si->unlock_typeahead)); - free (si->unlock_typeahead); - } - - if (i > 0) - si->unlock_typeahead = strdup (buf); - else - si->unlock_typeahead = 0; - - memset (buf, 0, sizeof(buf)); -} - - -/* methods of detecting idleness: - - explicitly informed by SGI SCREEN_SAVER server event; - explicitly informed by MIT-SCREEN-SAVER server event; - poll server idle time with XIDLE extension; - select events on all windows, and note absence of recent events; - note that /proc/interrupts has not changed in a while; - activated by clientmessage. - - methods of detecting non-idleness: - - read events on the xscreensaver window; - explicitly informed by SGI SCREEN_SAVER server event; - explicitly informed by MIT-SCREEN-SAVER server event; - select events on all windows, and note events on any of them; - note that a client updated their window's _NET_WM_USER_TIME property; - note that /proc/interrupts has changed; - deactivated by clientmessage. - - I trust that explains why this function is a big hairy mess. - */ -void -sleep_until_idle (saver_info *si, Bool until_idle_p) -{ - saver_preferences *p = &si->prefs; - - /* We have to go through this union bullshit because gcc-4.4.0 has - stricter struct-aliasing rules. Without this, the optimizer - can fuck things up. - */ - union { - XEvent x_event; -# ifdef HAVE_RANDR - XRRScreenChangeNotifyEvent xrr_event; -# endif /* HAVE_RANDR */ -# ifdef HAVE_MIT_SAVER_EXTENSION - XScreenSaverNotifyEvent sevent; -# endif /* HAVE_MIT_SAVER_EXTENSION */ - } event; - - /* We need to select events on all windows if we're not using any extensions. - Otherwise, we don't need to. */ - Bool scanning_all_windows = !(si->using_xidle_extension || - si->using_mit_saver_extension || - si->using_sgi_saver_extension); - - /* We need to periodically wake up and check for idleness if we're not using - any extensions, or if we're using the XIDLE extension. The other two - extensions explicitly deliver events when we go idle/non-idle, so we - don't need to poll. */ - Bool polling_for_idleness = !(si->using_mit_saver_extension || - si->using_sgi_saver_extension); - - /* Whether we need to periodically wake up and check to see if the mouse has - moved. We only need to do this when not using any extensions. The reason - this isn't the same as `polling_for_idleness' is that the "idleness" poll - can happen (for example) 5 minutes from now, whereas the mouse-position - poll should happen with low periodicity. We don't need to poll the mouse - position with the XIDLE extension, but we do need to periodically wake up - and query the server with that extension. For our purposes, polling - /proc/interrupts is just like polling the mouse position. It has to - happen on the same kind of schedule. */ - Bool polling_mouse_position = (si->using_proc_interrupts || - !(si->using_xidle_extension || - si->using_mit_saver_extension || - si->using_sgi_saver_extension) || - si->using_xinput_extension); - - const char *why = 0; /* What caused the idle-state to change? */ - - if (until_idle_p) - { - if (polling_for_idleness) - /* This causes a no-op event to be delivered to us in a while, so that - we come back around through the event loop again. */ - schedule_wakeup_event (si, p->timeout, p->debug_p); - - if (polling_mouse_position) - /* Check to see if the mouse has moved, and set up a repeating timer - to do so periodically (typically, every 5 seconds.) */ - check_pointer_timer ((XtPointer) si, 0); - } - - while (1) - { - XtAppNextEvent (si->app, &event.x_event); - - switch (event.x_event.xany.type) { - case 0: /* our synthetic "timeout" event has been signalled */ - if (until_idle_p) - { - Time idle; - - /* We may be idle; check one last time to see if the mouse has - moved, just in case the idle-timer went off within the 5 second - window between mouse polling. If the mouse has moved, then - check_pointer_timer() will reset last_activity_time. - */ - if (polling_mouse_position) - check_pointer_timer ((XtPointer) si, 0); - -#ifdef HAVE_XIDLE_EXTENSION - if (si->using_xidle_extension) - { - /* The XIDLE extension uses the synthetic event to prod us into - re-asking the server how long the user has been idle. */ - if (! XGetIdleTime (si->dpy, &idle)) - { - fprintf (stderr, "%s: XGetIdleTime() failed.\n", blurb()); - saver_exit (si, 1, 0); - } - } - else -#endif /* HAVE_XIDLE_EXTENSION */ -#ifdef HAVE_MIT_SAVER_EXTENSION - if (si->using_mit_saver_extension) - { - /* We don't need to do anything in this case - the synthetic - event isn't necessary, as we get sent specific events - to wake us up. In fact, this event generally shouldn't - be being delivered when the MIT extension is in use. */ - idle = 0; - } - else -#endif /* HAVE_MIT_SAVER_EXTENSION */ -#ifdef HAVE_SGI_SAVER_EXTENSION - if (si->using_sgi_saver_extension) - { - /* We don't need to do anything in this case - the synthetic - event isn't necessary, as we get sent specific events - to wake us up. In fact, this event generally shouldn't - be being delivered when the SGI extension is in use. */ - idle = 0; - } - else -#endif /* HAVE_SGI_SAVER_EXTENSION */ - { - /* Otherwise, no server extension is in use. The synthetic - event was to tell us to wake up and see if the user is now - idle. Compute the amount of idle time by comparing the - `last_activity_time' to the wall clock. The l_a_t was set - by calling `reset_timers()', which is called only in only - two situations: when polling the mouse position has revealed - the the mouse has moved (user activity) or when we have read - an event (again, user activity.) - */ - idle = 1000 * (si->last_activity_time - time ((time_t *) 0)); - } - - if (idle >= p->timeout) - { - /* Look, we've been idle long enough. We're done. */ - why = "timeout"; - goto DONE; - } - else if (si->emergency_lock_p) - { - /* Oops, the wall clock has jumped far into the future, so - we need to lock down in a hurry! */ - why = "large wall clock change"; - goto DONE; - } - else - { - /* The event went off, but it turns out that the user has not - yet been idle for long enough. So re-signal the event. - Be economical: if we should blank after 5 minutes, and the - user has been idle for 2 minutes, then set this timer to - go off in 3 minutes. - */ - if (polling_for_idleness) - schedule_wakeup_event (si, p->timeout - idle, p->debug_p); - } - } - break; - - case ClientMessage: - if (handle_clientmessage (si, &event.x_event, until_idle_p)) - { - why = "ClientMessage"; - goto DONE; - } - break; - - case CreateNotify: - /* A window has been created on the screen somewhere. If we're - supposed to scan all windows for events, prepare this window. */ - if (scanning_all_windows) - { - Window w = event.x_event.xcreatewindow.window; - start_notice_events_timer (si, w, p->debug_p); - } - break; - - case KeyPress: - case ButtonPress: - /* Ignore release events so that hitting ESC at the password dialog - doesn't result in the password dialog coming right back again when - the fucking release key is seen! */ - /* case KeyRelease:*/ - /* case ButtonRelease:*/ - case MotionNotify: - - if (p->debug_p) - { - Window root=0, window=0; - int x=-1, y=-1; - const char *type = 0; - if (event.x_event.xany.type == MotionNotify) - { - /*type = "MotionNotify";*/ - root = event.x_event.xmotion.root; - window = event.x_event.xmotion.window; - x = event.x_event.xmotion.x_root; - y = event.x_event.xmotion.y_root; - } - else if (event.x_event.xany.type == KeyPress) - { - type = "KeyPress"; - root = event.x_event.xkey.root; - window = event.x_event.xkey.window; - x = y = -1; - } - else if (event.x_event.xany.type == ButtonPress) - { - type = "ButtonPress"; - root = event.x_event.xkey.root; - window = event.x_event.xkey.window; - x = event.x_event.xmotion.x_root; - y = event.x_event.xmotion.y_root; - } - - if (type) - { - int i; - for (i = 0; i < si->nscreens; i++) - if (root == RootWindowOfScreen (si->screens[i].screen)) - break; - fprintf (stderr,"%s: %d: %s on 0x%lx", - blurb(), i, type, (unsigned long) window); - - /* Be careful never to do this unless in -debug mode, as - this could expose characters from the unlock password. */ - if (p->debug_p && event.x_event.xany.type == KeyPress) - { - KeySym keysym; - char c = 0; - XLookupString (&event.x_event.xkey, &c, 1, &keysym, 0); - fprintf (stderr, " (%s%s)", - (event.x_event.xkey.send_event ? "synthetic " : ""), - XKeysymToString (keysym)); - } - - if (x == -1) - fprintf (stderr, "\n"); - else - fprintf (stderr, " at %d,%d.\n", x, y); - } - } - - /* If any widgets want to handle this event, let them. */ - dispatch_event (si, &event.x_event); - - - /* If we got a MotionNotify event, figure out what screen it - was on and poll the mouse there: if the mouse hasn't moved - far enough to count as "real" motion, then ignore this - event. - */ - if (event.x_event.xany.type == MotionNotify) - { - int i; - for (i = 0; i < si->nscreens; i++) - if (event.x_event.xmotion.root == - RootWindowOfScreen (si->screens[i].screen)) - break; - if (i < si->nscreens) - { - if (!pointer_moved_p (&si->screens[i], False)) - continue; - } - } - - - /* We got a user event. - If we're waiting for the user to become active, this is it. - If we're waiting until the user becomes idle, reset the timers - (since now we have longer to wait.) - */ - if (!until_idle_p) - { - if (si->demoing_p && - (event.x_event.xany.type == MotionNotify || - event.x_event.xany.type == KeyRelease)) - /* When we're demoing a single hack, mouse motion doesn't - cause deactivation. Only clicks and keypresses do. */ - ; - else - { - /* If we're not demoing, then any activity causes deactivation. - */ - why = (event.x_event.xany.type == MotionNotify ?"mouse motion": - event.x_event.xany.type == KeyPress?"keyboard activity": - event.x_event.xany.type == ButtonPress ? "mouse click" : - "unknown user activity"); - goto DONE; - } - } - else - reset_timers (si); - - break; - - case PropertyNotify: - - /* Starting in late 2014, GNOME programs don't actually select for - or receive KeyPress events: they do it behind the scenes through - some kind of Input Method magic, even when running in an en_US - locale. However, those applications *do* update the WM_USER_TIME - property on their own windows every time they recieve a secret - KeyPress, so we must *also* monitor that property on every - window, and treat changes to it as identical to KeyPress. - - _NET_WM_USER_TIME is documented (such as it is) here: - - http://standards.freedesktop.org/wm-spec/latest/ar01s05.html - #idm139870829932528 - - Specifically: - - "Contains the XServer time at which last user activity in this - window took place. [...] A client [...] might, for example, - use the timestamp of the last KeyPress or ButtonPress event." - - As of early 2016, KDE4 does something really stupid, though: some - hidden power management thing reduces the display brightness 150 - seconds after the screen is blanked -- and sets a WM_USER_TIME - property on a hidden "kded4" window whose time is in the distant - past (the time at which the X server launched). - - So we ignore any WM_USER_TIME whose timestamp is more than a - couple seconds old. - */ - if (event.x_event.xproperty.state == PropertyNewValue && - event.x_event.xproperty.atom == XA_NET_WM_USER_TIME) - { - int threshold = 2; /* seconds */ - Bool bogus_p = True; - Window w = event.x_event.xproperty.window; - - Atom type; - int format; - unsigned long nitems, bytesafter; - unsigned char *data = 0; - Cardinal user_time = 0; - XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler); - - if (XGetWindowProperty (si->dpy, w, - XA_NET_WM_USER_TIME, 0L, 1L, False, - XA_CARDINAL, &type, &format, &nitems, - &bytesafter, &data) - == Success && - data && - type == XA_CARDINAL && - format == 32 && - nitems == 1) - { - long diff; - user_time = ((Cardinal *) data)[0]; - diff = event.x_event.xproperty.time - user_time; - if (diff >= 0 && diff < threshold) - bogus_p = False; - } - - if (data) XFree (data); - - why = "WM_USER_TIME"; - - if (p->debug_p) - { - XWindowAttributes xgwa; - int i; - - XGetWindowAttributes (si->dpy, w, &xgwa); - for (i = 0; i < si->nscreens; i++) - if (xgwa.root == RootWindowOfScreen (si->screens[i].screen)) - break; - fprintf (stderr,"%s: %d: %s = %ld%s on 0x%lx\n", - blurb(), i, why, (unsigned long) user_time, - (bogus_p ? " (bad)" : ""), - (unsigned long) w); - } - - XSync (si->dpy, False); - XSetErrorHandler (old_handler); - - if (bogus_p) - break; - else if (until_idle_p) - reset_timers (si); - else - goto DONE; - } - break; - - default: - -#ifdef HAVE_MIT_SAVER_EXTENSION - if (event.x_event.type == si->mit_saver_ext_event_number) - { - /* This event's number is that of the MIT-SCREEN-SAVER server - extension. This extension has one event number, and the event - itself contains sub-codes that say what kind of event it was - (an "idle" or "not-idle" event.) - */ - if (event.sevent.state == ScreenSaverOn) - { - int i = 0; - if (p->verbose_p) - fprintf (stderr, "%s: MIT ScreenSaverOn event received.\n", - blurb()); - - /* Get the "real" server window(s) out of the way as soon - as possible. */ - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - if (ssi->server_mit_saver_window && - window_exists_p (si->dpy, - ssi->server_mit_saver_window)) - XUnmapWindow (si->dpy, ssi->server_mit_saver_window); - } - - if (event.sevent.kind != ScreenSaverExternal) - { - fprintf (stderr, - "%s: ScreenSaverOn event wasn't of type External!\n", - blurb()); - } - - if (until_idle_p) - { - why = "MIT ScreenSaverOn"; - goto DONE; - } - } - else if (event.sevent.state == ScreenSaverOff) - { - if (p->verbose_p) - fprintf (stderr, "%s: MIT ScreenSaverOff event received.\n", - blurb()); - if (!until_idle_p) - { - why = "MIT ScreenSaverOff"; - goto DONE; - } - } - else - fprintf (stderr, - "%s: unknown MIT-SCREEN-SAVER event %d received!\n", - blurb(), event.sevent.state); - } - else - -#endif /* HAVE_MIT_SAVER_EXTENSION */ - - -#ifdef HAVE_SGI_SAVER_EXTENSION - if (event.x_event.type == (si->sgi_saver_ext_event_number + ScreenSaverStart)) - { - /* The SGI SCREEN_SAVER server extension has two event numbers, - and this event matches the "idle" event. */ - if (p->verbose_p) - fprintf (stderr, "%s: SGI ScreenSaverStart event received.\n", - blurb()); - - if (until_idle_p) - { - why = "SGI ScreenSaverStart"; - goto DONE; - } - } - else if (event.x_event.type == (si->sgi_saver_ext_event_number + - ScreenSaverEnd)) - { - /* The SGI SCREEN_SAVER server extension has two event numbers, - and this event matches the "idle" event. */ - if (p->verbose_p) - fprintf (stderr, "%s: SGI ScreenSaverEnd event received.\n", - blurb()); - if (!until_idle_p) - { - why = "SGI ScreenSaverEnd"; - goto DONE; - } - } - else -#endif /* HAVE_SGI_SAVER_EXTENSION */ - -#ifdef HAVE_XINPUT - /* If we got a MotionNotify event, check to see if the mouse has - moved far enough to count as "real" motion, if not, then ignore - this event. - */ - if ((si->num_xinput_devices > 0) && - (event.x_event.type == si->xinput_DeviceMotionNotify)) - { - XDeviceMotionEvent *dme = (XDeviceMotionEvent *) &event; - poll_mouse_data *last_poll_mouse = NULL; - int d; - - for (d = 0; d < si->num_xinput_devices; d++) - { - if (si->xinput_devices[d].device->device_id == dme->deviceid) - { - last_poll_mouse = &(si->xinput_devices[d].last_poll_mouse); - break; - } - } - - if (last_poll_mouse) - { - poll_mouse_data this_poll_mouse; - this_poll_mouse.root_x = dme->x_root; - this_poll_mouse.root_y = dme->y_root; - this_poll_mouse.child = dme->subwindow; - this_poll_mouse.mask = dme->device_state; - this_poll_mouse.time = dme->time / 1000; /* milliseconds */ - - if (!device_pointer_moved_p (si, last_poll_mouse, - &this_poll_mouse, False, - "device", dme->deviceid)) - continue; - } - else if (p->debug_p) - fprintf (stderr, - "%s: received MotionNotify from unknown device %d\n", - blurb(), (int) dme->deviceid); - } - - if ((!until_idle_p) && - (si->num_xinput_devices > 0) && - (event.x_event.type == si->xinput_DeviceMotionNotify || - event.x_event.type == si->xinput_DeviceButtonPress)) - /* Ignore DeviceButtonRelease, see ButtonRelease comment above. */ - { - - dispatch_event (si, &event.x_event); - if (si->demoing_p && - event.x_event.type == si->xinput_DeviceMotionNotify) - /* When we're demoing a single hack, mouse motion doesn't - cause deactivation. Only clicks and keypresses do. */ - ; - else - /* If we're not demoing, then any activity causes deactivation. - */ - { - why = (event.x_event.type == si->xinput_DeviceMotionNotify - ? "XI mouse motion" : - event.x_event.type == si->xinput_DeviceButtonPress - ? "XI mouse click" : "unknown XINPUT event"); - goto DONE; - } - } - else -#endif /* HAVE_XINPUT */ - -#ifdef HAVE_RANDR - if (si->using_randr_extension && - (event.x_event.type == - (si->randr_event_number + RRScreenChangeNotify))) - { - /* The Resize and Rotate extension sends an event when the - size, rotation, or refresh rate of any screen has changed. - */ - if (p->verbose_p) - { - /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */ - int screen = XRRRootToScreen (si->dpy, event.xrr_event.window); - fprintf (stderr, "%s: %d: screen change event received\n", - blurb(), screen); - } - -# ifdef RRScreenChangeNotifyMask - /* Inform Xlib that it's ok to update its data structures. */ - XRRUpdateConfiguration (&event.x_event); /* Xrandr.h 1.9, 2002/09/29 */ -# endif /* RRScreenChangeNotifyMask */ - - /* Resize the existing xscreensaver windows and cached ssi data. */ - if (update_screen_layout (si)) - { - if (p->verbose_p) - { - fprintf (stderr, "%s: new layout:\n", blurb()); - describe_monitor_layout (si); - } - resize_screensaver_window (si); - } - } - else -#endif /* HAVE_RANDR */ - - /* Just some random event. Let the Widgets handle it, if desired. */ - dispatch_event (si, &event.x_event); - } - } - DONE: - - if (p->verbose_p) - { - if (! why) why = "unknown reason"; - fprintf (stderr, "%s: %s (%s)\n", blurb(), - (until_idle_p ? "user is idle" : "user is active"), - why); - } - - /* If there's a user event on the queue, swallow it. - If we're using a server extension, and the user becomes active, we - get the extension event before the user event -- so the keypress or - motion or whatever is still on the queue. This makes "unfade" not - work, because it sees that event, and bugs out. (This problem - doesn't exhibit itself without an extension, because in that case, - there's only one event generated by user activity, not two.) - */ - if (!until_idle_p && si->locked_p) - swallow_unlock_typeahead_events (si, &event.x_event); - else - while (XCheckMaskEvent (si->dpy, - (KeyPressMask|ButtonPressMask|PointerMotionMask), - &event.x_event)) - ; - - - if (si->check_pointer_timer_id) - { - XtRemoveTimeOut (si->check_pointer_timer_id); - si->check_pointer_timer_id = 0; - } - if (si->timer_id) - { - XtRemoveTimeOut (si->timer_id); - si->timer_id = 0; - } - - if (until_idle_p && si->cycle_id) /* no cycle timer when inactive */ - abort (); -} - - - -/* Some crap for dealing with /proc/interrupts. - - On Linux systems, it's possible to see the hardware interrupt count - associated with the keyboard. We can therefore use that as another method - of detecting idleness. - - Why is it a good idea to do this? Because it lets us detect keyboard - activity that is not associated with X events. For example, if the user - has switched to another virtual console, it's good for xscreensaver to not - be running graphics hacks on the (non-visible) X display. The common - complaint that checking /proc/interrupts addresses is that the user is - playing Quake on a non-X console, and the GL hacks are perceptibly slowing - the game... - - This is tricky for a number of reasons. - - * First, we must be sure to only do this when running on an X server that - is on the local machine (because otherwise, we'd be reacting to the - wrong keyboard.) The way we do this is by noting that the $DISPLAY is - pointing to display 0 on the local machine. It *could* be that display - 1 is also on the local machine (e.g., two X servers, each on a different - virtual-terminal) but it's also possible that screen 1 is an X terminal, - using this machine as the host. So we can't take that chance. - - * Second, one can only access these interrupt numbers in a completely - and utterly brain-damaged way. You would think that one would use an - ioctl for this. But no. The ONLY way to get this information is to - open the pseudo-file /proc/interrupts AS A FILE, and read the numbers - out of it TEXTUALLY. Because this is Unix, and all the world's a file, - and the only real data type is the short-line sequence of ASCII bytes. - - Now it's all well and good that the /proc/interrupts pseudo-file - exists; that's a clever idea, and a useful API for things that are - already textually oriented, like shell scripts, and users doing - interactive debugging sessions. But to make a *C PROGRAM* open a file - and parse the textual representation of integers out of it is just - insane. - - * Third, you can't just hold the file open, and fseek() back to the - beginning to get updated data! If you do that, the data never changes. - And I don't want to call open() every five seconds, because I don't want - to risk going to disk for any inodes. It turns out that if you dup() - it early, then each copy gets fresh data, so we can get around that in - this way (but for how many releases, one might wonder?) - - * Fourth, the format of the output of the /proc/interrupts file is - undocumented, and has changed several times already! In Linux 2.0.33, - even on a multiprocessor machine, it looks like this: - - 0: 309453991 timer - 1: 4771729 keyboard - - but in Linux 2.2 and 2.4 kernels with MP machines, it looks like this: - - CPU0 CPU1 - 0: 1671450 1672618 IO-APIC-edge timer - 1: 13037 13495 IO-APIC-edge keyboard - - and in Linux 2.6, it's gotten even goofier: now there are two lines - labelled "i8042". One of them is the keyboard, and one of them is - the PS/2 mouse -- and of course, you can't tell them apart, except - by wiggling the mouse and noting which one changes: - - CPU0 CPU1 - 1: 32051 30864 IO-APIC-edge i8042 - 12: 476577 479913 IO-APIC-edge i8042 - - Joy! So how are we expected to parse that? Well, this code doesn't - parse it: it saves the first line with the string "keyboard" (or - "i8042") in it, and does a string-comparison to note when it has - changed. If there are two "i8042" lines, we assume the first is - the keyboard and the second is the mouse (doesn't matter which is - which, really, as long as we don't compare them against each other.) - - Thanks to Nat Friedman <nat@nat.org> for figuring out most of this crap. - - Note that if you have a serial or USB mouse, or a USB keyboard, it won't - detect it. That's because there's no way to tell the difference between a - serial mouse and a general serial port, and all USB devices look the same - from here. It would be somewhat unfortunate to have the screensaver turn - off when the modem on COM1 burped, or when a USB disk was accessed. - */ - - -#ifdef HAVE_PROC_INTERRUPTS - -#define PROC_INTERRUPTS "/proc/interrupts" - -Bool -query_proc_interrupts_available (saver_info *si, const char **why) -{ - /* We can use /proc/interrupts if $DISPLAY points to :0, and if the - "/proc/interrupts" file exists and is readable. - */ - FILE *f; - if (why) *why = 0; - - if (!display_is_on_console_p (si)) - { - if (why) *why = "not on primary console"; - return False; - } - - f = fopen (PROC_INTERRUPTS, "r"); - if (!f) - { - if (why) *why = "does not exist"; - return False; - } - - fclose (f); - return True; -} - - -static Bool -proc_interrupts_activity_p (saver_info *si) -{ - static FILE *f0 = 0; - FILE *f1 = 0; - int fd; - static char last_kbd_line[255] = { 0, }; - static char last_ptr_line[255] = { 0, }; - char new_line[sizeof(last_kbd_line)]; - Bool checked_kbd = False, kbd_changed = False; - Bool checked_ptr = False, ptr_changed = False; - int i8042_count = 0; - - if (!f0) - { - /* First time -- open the file. */ - f0 = fopen (PROC_INTERRUPTS, "r"); - if (!f0) - { - char buf[255]; - sprintf(buf, "%s: error opening %s", blurb(), PROC_INTERRUPTS); - perror (buf); - goto FAIL; - } - -# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) - /* Close this fd upon exec instead of inheriting / leaking it. */ - if (fcntl (fileno (f0), F_SETFD, FD_CLOEXEC) != 0) - perror ("fcntl: CLOEXEC:"); -# endif - } - - if (f0 == (FILE *) -1) /* means we got an error initializing. */ - return False; - - fd = dup (fileno (f0)); - if (fd < 0) - { - char buf[255]; - sprintf(buf, "%s: could not dup() the %s fd", blurb(), PROC_INTERRUPTS); - perror (buf); - goto FAIL; - } - - f1 = fdopen (fd, "r"); - if (!f1) - { - char buf[255]; - sprintf(buf, "%s: could not fdopen() the %s fd", blurb(), - PROC_INTERRUPTS); - perror (buf); - goto FAIL; - } - - /* Actually, I'm unclear on why this fseek() is necessary, given the timing - of the dup() above, but it is. */ - if (fseek (f1, 0, SEEK_SET) != 0) - { - char buf[255]; - sprintf(buf, "%s: error rewinding %s", blurb(), PROC_INTERRUPTS); - perror (buf); - goto FAIL; - } - - /* Now read through the pseudo-file until we find the "keyboard", - "PS/2 mouse", or "i8042" lines. */ - - while (fgets (new_line, sizeof(new_line)-1, f1)) - { - Bool i8042_p = !!strstr (new_line, "i8042"); - if (i8042_p) i8042_count++; - - if (strchr (new_line, ',')) - { - /* Ignore any line that has a comma on it: this is because - a setup like this: - - 12: 930935 XT-PIC usb-uhci, PS/2 Mouse - - is really bad news. It *looks* like we can note mouse - activity from that line, but really, that interrupt gets - fired any time any USB device has activity! So we have - to ignore any shared IRQs. - */ - } - else if (!checked_kbd && - (strstr (new_line, "keyboard") || - (i8042_p && i8042_count == 1))) - { - /* Assume the keyboard interrupt is the line that says "keyboard", - or the *first* line that says "i8042". - */ - kbd_changed = (*last_kbd_line && !!strcmp (new_line, last_kbd_line)); - strcpy (last_kbd_line, new_line); - checked_kbd = True; - } - else if (!checked_ptr && - (strstr (new_line, "PS/2 Mouse") || - (i8042_p && i8042_count == 2))) - { - /* Assume the mouse interrupt is the line that says "PS/2 mouse", - or the *second* line that says "i8042". - */ - ptr_changed = (*last_ptr_line && !!strcmp (new_line, last_ptr_line)); - strcpy (last_ptr_line, new_line); - checked_ptr = True; - } - - if (checked_kbd && checked_ptr) - break; - } - - if (checked_kbd || checked_ptr) - { - fclose (f1); - - if (si->prefs.debug_p && (kbd_changed || ptr_changed)) - fprintf (stderr, "%s: /proc/interrupts activity: %s\n", - blurb(), - ((kbd_changed && ptr_changed) ? "mouse and kbd" : - kbd_changed ? "kbd" : - ptr_changed ? "mouse" : "ERR")); - - return (kbd_changed || ptr_changed); - } - - - /* If we got here, we didn't find either a "keyboard" or a "PS/2 Mouse" - line in the file at all. */ - fprintf (stderr, "%s: no keyboard or mouse data in %s?\n", - blurb(), PROC_INTERRUPTS); - - FAIL: - if (f1) - fclose (f1); - - if (f0 && f0 != (FILE *) -1) - fclose (f0); - - f0 = (FILE *) -1; - return False; -} - -#endif /* HAVE_PROC_INTERRUPTS */ - - -/* This timer goes off every few minutes, whether the user is idle or not, - to try and clean up anything that has gone wrong. - - It calls disable_builtin_screensaver() so that if xset has been used, - or some other program (like xlock) has messed with the XSetScreenSaver() - settings, they will be set back to sensible values (if a server extension - is in use, messing with xlock can cause xscreensaver to never get a wakeup - event, and could cause monitor power-saving to occur, and all manner of - heinousness.) - - If the screen is currently blanked, it raises the window, in case some - other window has been mapped on top of it. - - If the screen is currently blanked, and there is no hack running, it - clears the window, in case there is an error message printed on it (we - don't want the error message to burn in.) - */ - -static void -watchdog_timer (XtPointer closure, XtIntervalId *id) -{ - saver_info *si = (saver_info *) closure; - saver_preferences *p = &si->prefs; - - disable_builtin_screensaver (si, False); - - /* If the DPMS settings on the server have changed, change them back to - what ~/.xscreensaver says they should be. */ - sync_server_dpms_settings (si->dpy, - (p->dpms_enabled_p && - p->mode != DONT_BLANK), - p->dpms_quickoff_p, - p->dpms_standby / 1000, - p->dpms_suspend / 1000, - p->dpms_off / 1000, - False); - - if (si->screen_blanked_p) - { - Bool running_p = screenhack_running_p (si); - - if (si->dbox_up_p) - { - if (si->prefs.debug_p) - fprintf (stderr, "%s: dialog box is up: not raising screen.\n", - blurb()); - } - else - { - if (si->prefs.debug_p) - fprintf (stderr, "%s: watchdog timer raising %sscreen.\n", - blurb(), (running_p ? "" : "and clearing ")); - - raise_window (si, True, True, running_p); - } - - if (screenhack_running_p (si) && - !monitor_powered_on_p (si)) - { - int i; - if (si->prefs.verbose_p) - fprintf (stderr, - "%s: X says monitor has powered down; " - "killing running hacks.\n", blurb()); - for (i = 0; i < si->nscreens; i++) - kill_screenhack (&si->screens[i]); - } - - /* Re-schedule this timer. The watchdog timer defaults to a bit less - than the hack cycle period, but is never longer than one hour. - */ - si->watchdog_id = 0; - reset_watchdog_timer (si, True); - } -} - - -void -reset_watchdog_timer (saver_info *si, Bool on_p) -{ - saver_preferences *p = &si->prefs; - - if (si->watchdog_id) - { - XtRemoveTimeOut (si->watchdog_id); - si->watchdog_id = 0; - } - - if (on_p && p->watchdog_timeout) - { - si->watchdog_id = XtAppAddTimeOut (si->app, p->watchdog_timeout, - watchdog_timer, (XtPointer) si); - - if (p->debug_p) - fprintf (stderr, "%s: restarting watchdog_timer (%ld, %ld)\n", - blurb(), p->watchdog_timeout, si->watchdog_id); - } -} - - -/* It's possible that a race condition could have led to the saver - window being unexpectedly still mapped. This can happen like so: - - - screen is blanked - - hack is launched - - that hack tries to grab a screen image (it does this by - first unmapping the saver window, then remapping it.) - - hack unmaps window - - hack waits - - user becomes active - - hack re-maps window (*) - - driver kills subprocess - - driver unmaps window (**) - - The race is that (*) might have been sent to the server before - the client process was killed, but, due to scheduling randomness, - might not have been received by the server until after (**). - In other words, (*) and (**) might happen out of order, meaning - the driver will unmap the window, and then after that, the - recently-dead client will re-map it. This leaves the user - locked out (it looks like a desktop, but it's not!) - - To avoid this: after un-blanking the screen, we launch a timer - that wakes up once a second for ten seconds, and makes damned - sure that the window is still unmapped. - */ - -void -de_race_timer (XtPointer closure, XtIntervalId *id) -{ - saver_info *si = (saver_info *) closure; - saver_preferences *p = &si->prefs; - int secs = 1; - - if (id == 0) /* if id is 0, this is the initialization call. */ - { - si->de_race_ticks = 10; - if (p->verbose_p) - fprintf (stderr, "%s: starting de-race timer (%d seconds.)\n", - blurb(), si->de_race_ticks); - } - else - { - int i; - XSync (si->dpy, False); - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - Window w = ssi->screensaver_window; - XWindowAttributes xgwa; - XGetWindowAttributes (si->dpy, w, &xgwa); - if (xgwa.map_state != IsUnmapped) - { - if (p->verbose_p) - fprintf (stderr, - "%s: %d: client race! emergency unmap 0x%lx.\n", - blurb(), i, (unsigned long) w); - XUnmapWindow (si->dpy, w); - } - else if (p->debug_p) - fprintf (stderr, "%s: %d: (de-race of 0x%lx is cool.)\n", - blurb(), i, (unsigned long) w); - } - XSync (si->dpy, False); - - si->de_race_ticks--; - } - - if (id && *id == si->de_race_id) - si->de_race_id = 0; - - if (si->de_race_id) abort(); - - if (si->de_race_ticks <= 0) - { - si->de_race_id = 0; - if (p->verbose_p) - fprintf (stderr, "%s: de-race completed.\n", blurb()); - } - else - { - si->de_race_id = XtAppAddTimeOut (si->app, secs * 1000, - de_race_timer, closure); - } -} diff --git a/driver/vms-getpwnam.c b/driver/vms-getpwnam.c deleted file mode 100644 index ec0650c..0000000 --- a/driver/vms-getpwnam.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * getpwnam(name) - retrieves a UAF entry - * - * Author: Patrick L. Mahan - * Location: TGV, Inc - * Date: 15-Nov-1991 - * - * Purpose: Provides emulation for the UNIX getpwname routine. - * - * Modification History - * - * Date | Who | Version | Reason - * ------------+-----------+---------------+--------------------------- - * 15-Nov-1991 | PLM | 1.0 | First Write - */ - -#define PASSWDROUTINES - -#include <stdio.h> -#include <descrip.h> -#include <uaidef.h> -#include <string.h> -#include <stdlib.h> -#include <starlet.h> -#include "vms-pwd.h" - -struct uic { - unsigned short uid; - unsigned short gid; -}; - -#define TEST(ptr, str) { if (ptr == NULL) { \ - fprintf(stderr, "getpwnam: memory allocation failure for \"%s\"\n", \ - str); \ - return ((struct passwd *)(NULL)); \ - } } - -struct passwd *getpwnam(name) -char *name; -{ - int istatus; - int UserNameLen; - int UserOwnerLen; - int UserDeviceLen; - int UserDirLen; - static char UserName[13]; - static char UserOwner[32]; - static char UserDevice[32]; - static char UserDir[64]; - char *cptr, *sptr; - unsigned long int UserPwd[2]; - unsigned short int UserSalt; - unsigned long int UserEncrypt; - struct uic UicValue; - struct passwd *entry; - - struct dsc$descriptor_s VMSNAME = - {strlen(name), DSC$K_DTYPE_T, DSC$K_CLASS_S, name}; - - struct itmlist3 { - unsigned short int length; - unsigned short int item; - unsigned long int addr; - unsigned long int retaddr; - } ItemList[] = { - {12, UAI$_USERNAME, (unsigned long)&UserName, (unsigned long)&UserNameLen}, - {8, UAI$_PWD, (unsigned long)&UserPwd, 0}, - {4, UAI$_UIC, (unsigned long)&UicValue, 0}, - {32, UAI$_OWNER, (unsigned long)&UserOwner, (unsigned long)&UserOwnerLen}, - {32, UAI$_DEFDEV, (unsigned long)&UserDevice, (unsigned long)&UserDeviceLen}, - {64, UAI$_DEFDIR, (unsigned long)&UserDir, (unsigned long)&UserDirLen}, - {2, UAI$_SALT, (unsigned long)&UserSalt, 0}, - {4, UAI$_ENCRYPT, (unsigned long)&UserEncrypt, 0}, - {0, 0, 0, 0} - }; - - UserNameLen = 0; - istatus = sys$getuai (0, 0, &VMSNAME, &ItemList, 0, 0, 0); - - if (!(istatus & 1)) { - fprintf (stderr, "getpwnam: unable to retrieve passwd entry for %s\n", - name); - fprintf (stderr, "getpwnam: vms error number is 0x%x\n", istatus); - return ((struct passwd *)NULL); - } - - entry = (struct passwd *) calloc (1, sizeof(struct passwd)); - TEST(entry, "PASSWD_ENTRY"); - - entry->pw_uid = UicValue.uid; - entry->pw_gid = UicValue.gid; - entry->pw_salt = UserSalt; - entry->pw_encrypt = UserEncrypt; - - sptr = UserName; - cptr = calloc (UserNameLen+1, sizeof(char)); - TEST(cptr, "USERNAME"); - strncpy (cptr, sptr, UserNameLen); - cptr[UserNameLen] = '\0'; - entry->pw_name = cptr; - - cptr = calloc(8, sizeof(char)); - TEST(cptr, "PASSWORD"); - memcpy(cptr, UserPwd, 8); - entry->pw_passwd = cptr; - - sptr = UserOwner; sptr++; - cptr = calloc ((int)UserOwner[0]+1, sizeof(char)); - TEST(cptr, "FULLNAME"); - strncpy (cptr, sptr, (int)UserOwner[0]); - cptr[(int)UserOwner[0]] = '\0'; - entry->pw_gecos = cptr; - - cptr = calloc ((int)UserDevice[0]+(int)UserDir[0]+1, sizeof(char)); - TEST(cptr, "HOME"); - sptr = UserDevice; sptr++; - strncpy (cptr, sptr, (int)UserDevice[0]); - sptr = UserDir; sptr++; - strncat (cptr, sptr, (int)UserDir[0]); - cptr[(int)UserDevice[0]+(int)UserDir[0]] = '\0'; - entry->pw_dir = cptr; - - cptr = calloc (strlen("SYS$SYSTEM:LOGINOUT.EXE")+1, sizeof(char)); - TEST(cptr,"SHELL"); - strcpy (cptr, "SYS$SYSTEM:LOGINOUT.EXE"); - entry->pw_shell = cptr; - - return (entry); -} diff --git a/driver/vms-hpwd.c b/driver/vms-hpwd.c deleted file mode 100644 index 707e3ea..0000000 --- a/driver/vms-hpwd.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * VAX/VMS Password hashing routines: - * - * uses the System Service SYS$HASH_PASSWORD - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - */ - -#include <syidef.h> -#include <descrip.h> -#include <string.h> -#include <starlet.h> -/* - * Hashing routine - */ -hash_vms_password(output_buf,input_buf,input_length,username,encryption_type,salt) -char *output_buf; -char *input_buf; -int input_length; -char *username; -int encryption_type; -unsigned short salt; -{ - struct dsc$descriptor_s password; - struct dsc$descriptor_s user; - - /* - * Check the VMS Version. If this is V5.4 or later, then - * we can use the new system service SYS$HASH_PASSWORD. Else - * fail and return garbage. - */ - - static char VMS_Version[32]; - struct { - unsigned short int Size; - unsigned short int Code; - char *Buffer; - unsigned short int *Resultant_Size; - } Item_List[2]={32, SYI$_VERSION, VMS_Version, 0, 0, 0}; - struct {int Size; char *Ptr;} Descr1; - - /* - * Get the information - */ - sys$getsyiw(0,0,0,Item_List,0,0,0); - /* - * Call the old routine if this isn't V5.4 or later... - */ -#ifndef __DECC - if ((VMS_Version[1] < '5') || - ((VMS_Version[1] == '5') && (VMS_Version[3] < '4'))) { - printf("Unsupported OS version\n"); - return(1); - } -#endif /* !__DECC */ - /* - * Call the SYS$HASH_PASSWORD system service... - */ - password.dsc$b_dtype = DSC$K_DTYPE_T; - password.dsc$b_class = DSC$K_CLASS_S; - password.dsc$w_length = input_length; - password.dsc$a_pointer = input_buf; - user.dsc$b_dtype = DSC$K_DTYPE_T; - user.dsc$b_class = DSC$K_CLASS_S; - user.dsc$w_length = strlen(username); - user.dsc$a_pointer = username; - sys$hash_password (&password, encryption_type, salt, &user, output_buf); -} diff --git a/driver/vms-pwd.h b/driver/vms-pwd.h deleted file mode 100644 index 6cb73d3..0000000 --- a/driver/vms-pwd.h +++ /dev/null @@ -1,48 +0,0 @@ -/* @(#)pwd.h 1.7 89/08/24 SMI; from S5R2 1.1 */ - -#ifndef __pwd_h -#define __pwd_h - -#ifdef vax11c -#include <types.h> -#else -#include <sys/types.h> -#endif /* vax11c */ - -#ifdef PASSWDROUTINES -#define EXTERN -#else -#define EXTERN extern -#endif /* PASSWDROUTINES */ - -struct passwd { - char *pw_name; - char *pw_passwd; - int pw_uid; - int pw_gid; - short pw_salt; - int pw_encrypt; - char *pw_age; - char *pw_comment; - char *pw_gecos; - char *pw_dir; - char *pw_shell; -}; - - -#ifndef _POSIX_SOURCE -extern struct passwd *getpwent(); - -struct comment { - char *c_dept; - char *c_name; - char *c_acct; - char *c_bin; -}; - -#endif - -EXTERN struct passwd *getpwuid(/* uid_t uid */); -EXTERN struct passwd *getpwnam(/* char *name */); - -#endif /* !__pwd_h */ diff --git a/driver/vms-validate.c b/driver/vms-validate.c deleted file mode 100644 index 8f7141d..0000000 --- a/driver/vms-validate.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * validate a password for a user - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -/* - * Includes - */ -#include <stdio.h> -#include <ctype.h> -#include <string.h> - -#include "vms-pwd.h" -int hash_vms_password(char *output_buf,char *input_buf,int input_length, - char *username,int encryption_type,unsigned short salt); - -/* - * - * Validate a VMS UserName/Password pair. - * - */ - -int validate_user(name,password) -char *name; -char *password; -{ - char password_buf[64]; - char username_buf[31]; - char encrypt_buf[8]; - register int i; - register char *cp,*cp1; - struct passwd *user_entry; - - /* - * Get the users UAF entry - */ - user_entry = getpwnam(name); - - /* - * If user_entry == NULL then we got a bad error - * return -1 to indicate a bad error - */ - if (user_entry == NULL) return (-1); - - /* - * Uppercase the password - */ - cp = password; - cp1 = password_buf; - while (*cp) - if (islower(*cp)) - *cp1++ = toupper(*cp++); - else - *cp1++ = *cp++; - /* - * Get the length of the password - */ - i = strlen(password); - /* - * Encrypt the password - */ - hash_vms_password(encrypt_buf,password_buf,i,user_entry->pw_name, - user_entry->pw_encrypt, user_entry->pw_salt); - if (memcmp(encrypt_buf,user_entry->pw_passwd,8) == 0) - return(1); - else return(0); -} - diff --git a/driver/xscreensaver-getimage.c b/driver/xscreensaver-getimage.c deleted file mode 100644 index 092540d..0000000 --- a/driver/xscreensaver-getimage.c +++ /dev/null @@ -1,2000 +0,0 @@ -/* xscreensaver, Copyright (c) 2001-2018 by Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -/* xscreensaver-getimage -- helper program that puts a random image - onto the given window or pixmap. That image is either a screen-grab, - a file loaded from disk, or a frame grabbed from the system's video - input. - */ - -#include "utils.h" - -#include <X11/Intrinsic.h> -#include <ctype.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/time.h> - -#ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> /* for waitpid() and associated macros */ -#endif - -#ifdef HAVE_XMU -# ifndef VMS -# include <X11/Xmu/Error.h> -# else /* VMS */ -# include <Xmu/Error.h> -# endif -#else -# include "xmu.h" -#endif - -#include "yarandom.h" -#include "grabscreen.h" -#include "resources.h" -#include "colorbars.h" -#include "visual.h" -#include "prefs.h" -#include "version.h" -#include "vroot.h" - -#ifndef _XSCREENSAVER_VROOT_H_ -# error Error! You have an old version of vroot.h! Check -I args. -#endif /* _XSCREENSAVER_VROOT_H_ */ - -#ifdef HAVE_GDK_PIXBUF -# undef HAVE_JPEGLIB -# ifdef HAVE_GTK2 -# include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h> -# else /* !HAVE_GTK2 */ -# include <gdk-pixbuf/gdk-pixbuf-xlib.h> -# endif /* !HAVE_GTK2 */ -#endif /* HAVE_GDK_PIXBUF */ - -#ifdef HAVE_JPEGLIB -# undef HAVE_GDK_PIXBUF -# include <jpeglib.h> -#endif - - -#ifdef __APPLE__ - /* On MacOS under X11, the usual X11 mechanism of getting a screen shot - doesn't work, and we need to use an external program. This is only - used when running under X11 on MacOS. If it's a Cocoa build, this - path is not taken, and OSX/grabclient-osx.m is used instead. - */ -# define USE_EXTERNAL_SCREEN_GRABBER -#endif - - -#ifdef __GNUC__ - __extension__ /* shut up about "string length is greater than the length - ISO C89 compilers are required to support" when including - the .ad file... */ -#endif - -static char *defaults[] = { -#include "../driver/XScreenSaver_ad.h" - 0 -}; - - - -char *progname = 0; -char *progclass = "XScreenSaver"; -XrmDatabase db; -XtAppContext app; - -extern void grabscreen_verbose (void); - -typedef enum { - GRAB_DESK, GRAB_VIDEO, GRAB_FILE, GRAB_BARS -} grab_type; - - -#define GETIMAGE_VIDEO_PROGRAM "xscreensaver-getimage-video" -#define GETIMAGE_FILE_PROGRAM "xscreensaver-getimage-file" -#define GETIMAGE_SCREEN_PROGRAM "xscreensaver-getimage-desktop" - -extern const char *blurb (void); - -const char * -blurb (void) -{ - return progname; -} - - -static int -x_ehandler (Display *dpy, XErrorEvent *error) -{ - if (error->error_code == BadWindow || error->error_code == BadDrawable) - { - fprintf (stderr, "%s: target %s 0x%lx unexpectedly deleted\n", progname, - (error->error_code == BadWindow ? "window" : "pixmap"), - (unsigned long) error->resourceid); - } - else - { - fprintf (stderr, "\nX error in %s:\n", progname); - XmuPrintDefaultErrorMessage (dpy, error, stderr); - } - exit (-1); - return 0; -} - - -static Bool error_handler_hit_p = False; - -static int -ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) -{ - error_handler_hit_p = True; - return 0; -} - -#ifndef USE_EXTERNAL_SCREEN_GRABBER -static int -ignore_badmatch_ehandler (Display *dpy, XErrorEvent *error) -{ - if (error->error_code == BadMatch) - return ignore_all_errors_ehandler (dpy, error); - else - return x_ehandler (dpy, error); -} -#endif /* ! USE_EXTERNAL_SCREEN_GRABBER */ - - -/* Returns True if the given Drawable is a Window; False if it's a Pixmap. - */ -static Bool -drawable_window_p (Display *dpy, Drawable d) -{ - XErrorHandler old_handler; - XWindowAttributes xgwa; - - XSync (dpy, False); - old_handler = XSetErrorHandler (ignore_all_errors_ehandler); - error_handler_hit_p = False; - XGetWindowAttributes (dpy, d, &xgwa); - XSync (dpy, False); - XSetErrorHandler (old_handler); - XSync (dpy, False); - - if (!error_handler_hit_p) - return True; /* It's a Window. */ - else - return False; /* It's a Pixmap, or an invalid ID. */ -} - - -/* Returns true if the window is the root window, or a virtual root window, - but *not* the xscreensaver window. That is, if it's a "real" desktop - root window of some kind. - */ -static Bool -root_window_p (Screen *screen, Window window) -{ - Display *dpy = DisplayOfScreen (screen); - Atom type; - int format; - unsigned long nitems, bytesafter; - unsigned char *version; - - if (window != RootWindowOfScreen (screen)) - return False; - - if (XGetWindowProperty (dpy, window, - XInternAtom (dpy, "_SCREENSAVER_VERSION", False), - 0, 1, False, XA_STRING, - &type, &format, &nitems, &bytesafter, - &version) - == Success - && type != None) - return False; - - return True; -} - - -/* Clear the window or pixmap to black, or its background color. - */ -static void -clear_drawable (Screen *screen, Drawable drawable) -{ - Display *dpy = DisplayOfScreen (screen); - XGCValues gcv; - GC gc; - Window root; - int x, y; - unsigned int w, h, bw, d; - XGetGeometry (dpy, drawable, &root, &x, &y, &w, &h, &bw, &d); - - /* The window might have no-op background of None, so to clear it, - draw a black rectangle first, then do XClearWindow (in case the - actual background color is non-black...) */ - - /* #### really we should allocate "black" instead, but I'm lazy... */ - gcv.foreground = BlackPixelOfScreen (screen); - gc = XCreateGC (dpy, drawable, GCForeground, &gcv); - XFillRectangle (dpy, drawable, gc, 0, 0, w, h); - XFreeGC (dpy, gc); - if (drawable_window_p (dpy, drawable)) - XClearWindow (dpy, (Window) drawable); - XFlush (dpy); -} - - -/* Figure out what kind of scaling/positioning we ought to do to display - a src-sized image in a dest-sized window/pixmap. Returns the width - and height to which the image should be scaled, and the position where - it should be displayed to center it. - */ -static void -compute_image_scaling (int src_w, int src_h, - int dest_w, int dest_h, - Bool verbose_p, - int *scaled_from_x_ret, int *scaled_from_y_ret, - int *scaled_to_x_ret, int *scaled_to_y_ret, - int *scaled_w_ret, int *scaled_h_ret) -{ - int srcx, srcy, destx, desty; - - Bool exact_fit_p = ((src_w == dest_w && src_h <= dest_h) || - (src_h == dest_h && src_w <= dest_w)); - - if (!exact_fit_p) /* scale the image up or down */ - { - float rw = (float) dest_w / src_w; - float rh = (float) dest_h / src_h; - float r = (rw < rh ? rw : rh); - int tw, th, pct; - - /* If the window is a goofy aspect ratio, take a middle slice of - the image instead. */ - if (dest_w > dest_h * 5 || dest_h > dest_w * 5) - { - double r2 = (dest_w > dest_h - ? dest_w / (double) dest_h - : dest_h / (double) dest_w); - r *= r2; - if (verbose_p) - fprintf (stderr, "%s: weird aspect: scaling by %.1f\n", - progname, r2); - } - - tw = src_w * r; - th = src_h * r; - pct = (r * 100); - -#if 0 - /* this optimization breaks things */ - if (pct < 95 || pct > 105) /* don't scale if it's close */ -#endif - { - if (verbose_p) - fprintf (stderr, "%s: scaling image by %d%% (%dx%d -> %dx%d)\n", - progname, pct, src_w, src_h, tw, th); - src_w = tw; - src_h = th; - } - } - - /* Center the image on the window/pixmap. */ - srcx = 0; - srcy = 0; - destx = (dest_w - src_w) / 2; - desty = (dest_h - src_h) / 2; - if (destx < 0) srcx = -destx, destx = 0; - if (desty < 0) srcy = -desty, desty = 0; - - /* if (dest_w < src_w) src_w = dest_w; - if (dest_h < src_h) src_h = dest_h; */ - - *scaled_w_ret = src_w; - *scaled_h_ret = src_h; - *scaled_from_x_ret = srcx; - *scaled_from_y_ret = srcy; - *scaled_to_x_ret = destx; - *scaled_to_y_ret = desty; - - if (verbose_p) - fprintf (stderr, "%s: displaying %dx%d+%d+%d image at %d,%d in %dx%d.\n", - progname, src_w, src_h, srcx, srcy, destx, desty, dest_w, dest_h); -} - - -static void -colorbars (Screen *screen, Visual *visual, Drawable drawable, Colormap cmap) -{ - Pixmap mask = 0; - unsigned long *pixels; /* ignored - unfreed */ - int npixels; - Pixmap logo = xscreensaver_logo (screen, visual, drawable, cmap, - BlackPixelOfScreen (screen), - &pixels, &npixels, &mask, True); - draw_colorbars (screen, visual, drawable, cmap, 0, 0, 0, 0, logo, mask); - XFreePixmap (DisplayOfScreen (screen), logo); - XFreePixmap (DisplayOfScreen (screen), mask); -} - - -/* Scales an XImage, modifying it in place. - This doesn't do dithering or smoothing, so it might have artifacts. - If out of memory, returns False, and the XImage will have been - destroyed and freed. - */ -#if !defined(USE_EXTERNAL_SCREEN_GRABBER) || defined(HAVE_JPEGLIB) -static Bool -scale_ximage (Screen *screen, Visual *visual, - XImage *ximage, int new_width, int new_height) -{ - Display *dpy = DisplayOfScreen (screen); - int depth = visual_depth (screen, visual); - int x, y; - double xscale, yscale; - - XImage *ximage2 = XCreateImage (dpy, visual, depth, - ZPixmap, 0, 0, - new_width, new_height, 8, 0); - ximage2->data = (char *) calloc (ximage2->height, ximage2->bytes_per_line); - - if (!ximage2->data) - { - fprintf (stderr, "%s: out of memory scaling %dx%d image to %dx%d\n", - progname, - ximage->width, ximage->height, - ximage2->width, ximage2->height); - if (ximage->data) free (ximage->data); - if (ximage2->data) free (ximage2->data); - ximage->data = 0; - ximage2->data = 0; - XDestroyImage (ximage); - XDestroyImage (ximage2); - return False; - } - - /* Brute force scaling... */ - xscale = (double) ximage->width / ximage2->width; - yscale = (double) ximage->height / ximage2->height; - for (y = 0; y < ximage2->height; y++) - for (x = 0; x < ximage2->width; x++) - XPutPixel (ximage2, x, y, - XGetPixel (ximage, x * xscale, y * yscale)); - - free (ximage->data); - ximage->data = 0; - - (*ximage) = (*ximage2); - - ximage2->data = 0; - XDestroyImage (ximage2); - - return True; -} -#endif /* !USE_EXTERNAL_SCREEN_GRABBER || HAVE_JPEGLIB */ - - -#ifdef HAVE_GDK_PIXBUF - -/* Reads the given image file and renders it on the Drawable, using GDK. - Returns False if it fails. - */ -static Bool -read_file_gdk (Screen *screen, Window window, Drawable drawable, - const char *filename, Bool verbose_p, - XRectangle *geom_ret) -{ - GdkPixbuf *pb; - Display *dpy = DisplayOfScreen (screen); - unsigned int win_width, win_height, win_depth; -# ifdef HAVE_GTK2 - GError *gerr = 0; -# endif /* HAVE_GTK2 */ - - /* Find the size of the Drawable. */ - { - Window root; - int x, y; - unsigned int bw; - XGetGeometry (dpy, drawable, - &root, &x, &y, &win_width, &win_height, &bw, &win_depth); - } - - gdk_pixbuf_xlib_init_with_depth (dpy, screen_number (screen), win_depth); -# ifdef HAVE_GTK2 -# if !GLIB_CHECK_VERSION(2, 36 ,0) - g_type_init(); -# endif -# else /* !HAVE_GTK2 */ - xlib_rgb_init (dpy, screen); -# endif /* !HAVE_GTK2 */ - - pb = gdk_pixbuf_new_from_file (filename -# ifdef HAVE_GTK2 - , &gerr -# endif /* HAVE_GTK2 */ - ); - - if (!pb) - { - fprintf (stderr, "%s: unable to load \"%s\"\n", progname, filename); -# ifdef HAVE_GTK2 - if (gerr && gerr->message && *gerr->message) - fprintf (stderr, "%s: reason: %s\n", progname, gerr->message); -# endif /* HAVE_GTK2 */ - return False; - } - else - { - int w = gdk_pixbuf_get_width (pb); - int h = gdk_pixbuf_get_height (pb); - int srcx, srcy, destx, desty, w2, h2; - Bool bg_p = False; - -# ifdef HAVE_GDK_PIXBUF_APPLY_EMBEDDED_ORIENTATION - { - int ow = w, oh = h; - GdkPixbuf *opb = pb; - pb = gdk_pixbuf_apply_embedded_orientation (opb); - g_object_unref (opb); - w = gdk_pixbuf_get_width (pb); - h = gdk_pixbuf_get_height (pb); - if (verbose_p && (w != ow || h != oh)) - fprintf (stderr, "%s: rotated %dx%d to %dx%d\n", - progname, ow, oh, w, h); - } -# endif - - compute_image_scaling (w, h, win_width, win_height, verbose_p, - &srcx, &srcy, &destx, &desty, &w2, &h2); - if (w != w2 || h != h2) - { - GdkPixbuf *pb2 = gdk_pixbuf_scale_simple (pb, w2, h2, - GDK_INTERP_BILINEAR); - if (pb2) - { - g_object_unref (pb); - pb = pb2; - w = w2; - h = h2; - } - else - fprintf (stderr, "%s: out of memory when scaling?\n", progname); - } - - /* If we're rendering onto the root window (and it's not the - xscreensaver pseudo-root) then put the image in the window's - background. Otherwise, just paint the image onto the window. - */ - bg_p = (window == drawable && root_window_p (screen, window)); - - if (bg_p) - { - XGCValues gcv; - GC gc; - drawable = XCreatePixmap (dpy, window, - win_width, win_height, win_depth); - gcv.foreground = BlackPixelOfScreen (screen); - gc = XCreateGC (dpy, drawable, GCForeground, &gcv); - XFillRectangle (dpy, drawable, gc, 0, 0, win_width, win_height); - XFreeGC (dpy, gc); - } - else - clear_drawable (screen, drawable); - - /* #### Note that this always uses the default colormap! Morons! - Owen says that in Gnome 2.0, I should try using - gdk_pixbuf_render_pixmap_and_mask_for_colormap() instead. - But I haven't tried. - */ - if (srcx > 0) w -= srcx; - if (srcy > 0) h -= srcy; - gdk_pixbuf_xlib_render_to_drawable_alpha (pb, drawable, - srcx, srcy, destx, desty, - w, h, - GDK_PIXBUF_ALPHA_FULL, 127, - XLIB_RGB_DITHER_NORMAL, - 0, 0); - if (bg_p) - { - XSetWindowBackgroundPixmap (dpy, window, drawable); - XClearWindow (dpy, window); - } - - if (geom_ret) - { - geom_ret->x = destx; - geom_ret->y = desty; - geom_ret->width = w; - geom_ret->height = h; - } - } - - XSync (dpy, False); - return True; -} - -#endif /* HAVE_GDK_PIXBUF */ - - - -#ifdef HAVE_JPEGLIB - -/* Allocates a colormap that makes a PseudoColor or DirectColor - visual behave like a TrueColor visual of the same depth. - - #### Duplicated in utils/grabscreen.c - */ -static void -allocate_cubic_colormap (Screen *screen, Visual *visual, Colormap cmap, - Bool verbose_p) -{ - Display *dpy = DisplayOfScreen (screen); - int nr, ng, nb, cells; - int r, g, b; - int depth; - XColor colors[4097]; - int i; - - depth = visual_depth (screen, visual); - - switch (depth) - { - case 8: nr = 3; ng = 3; nb = 2; cells = 256; break; - case 12: nr = 4; ng = 4; nb = 4; cells = 4096; break; - default: abort(); break; - } - - memset(colors, 0, sizeof(colors)); - for (r = 0; r < (1 << nr); r++) - for (g = 0; g < (1 << ng); g++) - for (b = 0; b < (1 << nb); b++) - { - i = (r | (g << nr) | (b << (nr + ng))); - colors[i].pixel = i; - colors[i].flags = DoRed|DoGreen|DoBlue; - if (depth == 8) - { - colors[i].red = ((r << 13) | (r << 10) | (r << 7) | - (r << 4) | (r << 1)); - colors[i].green = ((g << 13) | (g << 10) | (g << 7) | - (g << 4) | (g << 1)); - colors[i].blue = ((b << 14) | (b << 12) | (b << 10) | - (b << 8) | (b << 6) | (b << 4) | - (b << 2) | b); - } - else - { - colors[i].red = (r << 12) | (r << 8) | (r << 4) | r; - colors[i].green = (g << 12) | (g << 8) | (g << 4) | g; - colors[i].blue = (b << 12) | (b << 8) | (b << 4) | b; - } - } - - { - int j; - int allocated = 0; - int interleave = cells / 8; /* skip around, rather than allocating in - order, so that we get better coverage if - we can't allocated all of them. */ - for (j = 0; j < interleave; j++) - for (i = 0; i < cells; i += interleave) - if (XAllocColor (dpy, cmap, &colors[i + j])) - allocated++; - - if (verbose_p) - fprintf (stderr, "%s: allocated %d of %d colors for cubic map\n", - progname, allocated, cells); - } -} - -/* Find the pixel index that is closest to the given color - (using linear distance in RGB space -- which is far from the best way.) - - #### Duplicated in utils/grabscreen.c - */ -static unsigned long -find_closest_pixel (XColor *colors, int ncolors, - unsigned long r, unsigned long g, unsigned long b) -{ - unsigned long distance = ~0; - int i, found = 0; - - if (ncolors == 0) - abort(); - for (i = 0; i < ncolors; i++) - { - unsigned long d; - int rd, gd, bd; - - rd = r - colors[i].red; - gd = g - colors[i].green; - bd = b - colors[i].blue; - if (rd < 0) rd = -rd; - if (gd < 0) gd = -gd; - if (bd < 0) bd = -bd; - d = (rd << 1) + (gd << 2) + bd; - - if (d < distance) - { - distance = d; - found = i; - if (distance == 0) - break; - } - } - - return found; -} - - -/* Given an XImage with 8-bit or 12-bit RGB data, convert it to be - displayable with the given X colormap. The farther from a perfect - color cube the contents of the colormap are, the lossier the - transformation will be. No dithering is done. - - #### Duplicated in utils/grabscreen.c - */ -static void -remap_image (Screen *screen, Colormap cmap, XImage *image, Bool verbose_p) -{ - Display *dpy = DisplayOfScreen (screen); - unsigned long map[4097]; - int x, y, i; - int cells; - XColor colors[4097]; - - if (image->depth == 8) - cells = 256; - else if (image->depth == 12) - cells = 4096; - else - abort(); - - memset(map, -1, sizeof(*map)); - memset(colors, -1, sizeof(*colors)); - - for (i = 0; i < cells; i++) - colors[i].pixel = i; - XQueryColors (dpy, cmap, colors, cells); - - if (verbose_p) - fprintf(stderr, "%s: building color cube for %d bit image\n", - progname, image->depth); - - for (i = 0; i < cells; i++) - { - unsigned short r, g, b; - - if (cells == 256) - { - /* "RRR GGG BB" In an 8 bit map. Convert that to - "RRR RRR RR" "GGG GGG GG" "BB BB BB BB" to give - an even spread. */ - r = (i & 0x07); - g = (i & 0x38) >> 3; - b = (i & 0xC0) >> 6; - - r = ((r << 13) | (r << 10) | (r << 7) | (r << 4) | (r << 1)); - g = ((g << 13) | (g << 10) | (g << 7) | (g << 4) | (g << 1)); - b = ((b << 14) | (b << 12) | (b << 10) | (b << 8) | - (b << 6) | (b << 4) | (b << 2) | b); - } - else - { - /* "RRRR GGGG BBBB" In a 12 bit map. Convert that to - "RRRR RRRR" "GGGG GGGG" "BBBB BBBB" to give an even - spread. */ - r = (i & 0x00F); - g = (i & 0x0F0) >> 4; - b = (i & 0xF00) >> 8; - - r = (r << 12) | (r << 8) | (r << 4) | r; - g = (g << 12) | (g << 8) | (g << 4) | g; - b = (b << 12) | (b << 8) | (b << 4) | b; - } - - map[i] = find_closest_pixel (colors, cells, r, g, b); - } - - if (verbose_p) - fprintf(stderr, "%s: remapping colors in %d bit image\n", - progname, image->depth); - - for (y = 0; y < image->height; y++) - for (x = 0; x < image->width; x++) - { - unsigned long pixel = XGetPixel(image, x, y); - if (pixel >= cells) abort(); - XPutPixel(image, x, y, map[pixel]); - } -} - - -/* If the file has a PPM (P6) on it, read it and return an XImage. - Otherwise, rewind the fd back to the beginning, and return 0. - */ -static XImage * -maybe_read_ppm (Screen *screen, Visual *visual, - const char *filename, FILE *in, Bool verbose_p) -{ - Display *dpy = DisplayOfScreen (screen); - int depth = visual_depth (screen, visual); - struct stat st; - char *buf = 0; - int bufsiz = 0; - char *s, dummy; - int i, j; - int x, y, w, h, maxval; - XImage *ximage = 0; - - if (fstat (fileno (in), &st)) - goto FAIL; - - bufsiz = st.st_size; - buf = (char *) malloc (bufsiz + 1); - if (!buf) - { - fprintf (stderr, "%s: out of memory loading %d byte PPM file %s\n", - progname, bufsiz, filename); - goto FAIL; - } - - if (! (s = fgets (buf, bufsiz, in))) /* line 1 */ - goto FAIL; - - if (!strncmp (buf, "\107\111", 2)) - { - fprintf (stderr, "%s: %s: sorry, GIF files not supported" - " when compiled with JPEGlib instead of GDK_Pixbuf.\n", - progname, filename); - goto FAIL; - } - else if (!strncmp (buf, "\211\120", 2)) - { - fprintf (stderr, "%s: %s: sorry, PNG files not supported" - " when compiled with JPEGlib instead of GDK_Pixbuf.\n", - progname, filename); - goto FAIL; - } - - if (strncmp (s, "P6", 2)) - goto FAIL; - - if (! (s = fgets (buf, bufsiz, in))) /* line 2 */ - goto FAIL; - if (2 != sscanf (s, " %d %d %c", &w, &h, &dummy)) - { - fprintf (stderr, "%s: %s: invalid PPM (line 2)\n", progname, filename); - goto FAIL; - } - - if (! (s = fgets (buf, bufsiz, in))) /* line 3 */ - goto FAIL; - if (1 != sscanf (s, " %d %c", &maxval, &dummy)) - { - fprintf (stderr, "%s: %s: invalid PPM (line 3)\n", progname, filename); - goto FAIL; - } - if (maxval != 255) - { - fprintf (stderr, "%s: %s: unparsable PPM: maxval is %d\n", - progname, filename, maxval); - goto FAIL; - } - - ximage = XCreateImage (dpy, visual, depth, ZPixmap, 0, 0, - w, h, 8, 0); - if (ximage) - ximage->data = (char *) calloc (ximage->height, ximage->bytes_per_line); - if (!ximage || !ximage->data) - { - fprintf (stderr, "%s: out of memory loading %dx%d PPM file %s\n", - progname, ximage->width, ximage->height, filename); - goto FAIL; - } - - s = buf; - j = bufsiz; - while ((i = fread (s, 1, j, in)) > 0) - s += i, j -= i; - - i = 0; - for (y = 0; y < ximage->height; y++) - for (x = 0; x < ximage->width; x++) - { - unsigned char r = buf[i++]; - unsigned char g = buf[i++]; - unsigned char b = buf[i++]; - unsigned long pixel; - - if (depth > 16) - pixel = (r << 16) | (g << 8) | b; - else if (depth == 8) - pixel = ((r >> 5) | ((g >> 5) << 3) | ((b >> 6) << 6)); - else if (depth == 12) - pixel = ((r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8)); - else if (depth == 16 || depth == 15) - pixel = (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3))); - else - abort(); - - XPutPixel (ximage, x, y, pixel); - } - - free (buf); - return ximage; - - FAIL: - if (buf) free (buf); - if (ximage && ximage->data) - { - free (ximage->data); - ximage->data = 0; - } - if (ximage) XDestroyImage (ximage); - fseek (in, 0, SEEK_SET); - return 0; -} - - -typedef struct { - struct jpeg_error_mgr pub; /* this is what passes for subclassing in C */ - const char *filename; - Screen *screen; - Visual *visual; - Drawable drawable; - Colormap cmap; -} getimg_jpg_error_mgr; - - -static void -jpg_output_message (j_common_ptr cinfo) -{ - getimg_jpg_error_mgr *err = (getimg_jpg_error_mgr *) cinfo->err; - char buf[JMSG_LENGTH_MAX]; - cinfo->err->format_message (cinfo, buf); - fprintf (stderr, "%s: %s: %s\n", progname, err->filename, buf); -} - - -static void -jpg_error_exit (j_common_ptr cinfo) -{ - getimg_jpg_error_mgr *err = (getimg_jpg_error_mgr *) cinfo->err; - cinfo->err->output_message (cinfo); - colorbars (err->screen, err->visual, err->drawable, err->cmap); - XSync (DisplayOfScreen (err->screen), False); - exit (1); -} - - -/* Reads a JPEG file, returns an RGB XImage of it. - */ -static XImage * -read_jpeg_ximage (Screen *screen, Visual *visual, Drawable drawable, - Colormap cmap, const char *filename, Bool verbose_p) -{ - Display *dpy = DisplayOfScreen (screen); - int depth = visual_depth (screen, visual); - - FILE *in = 0; - XImage *ximage = 0; - struct jpeg_decompress_struct cinfo; - getimg_jpg_error_mgr jerr; - JSAMPARRAY scanbuf = 0; - int y; - - jerr.filename = filename; - jerr.screen = screen; - jerr.visual = visual; - jerr.drawable = drawable; - jerr.cmap = cmap; - - if (! (depth >= 15 || depth == 12 || depth == 8)) - { - fprintf (stderr, "%s: unsupported depth: %d\n", progname, depth); - goto FAIL; - } - - in = fopen (filename, "rb"); - if (!in) - { - fprintf (stderr, "%s: %s: unreadable\n", progname, filename); - goto FAIL; - } - - /* Check to see if it's a PPM, and if so, read that instead of using - the JPEG library. Yeah, this is all modular and stuff. - */ - if ((ximage = maybe_read_ppm (screen, visual, filename, in, verbose_p))) - { - fclose (in); - return ximage; - } - - cinfo.err = jpeg_std_error (&jerr.pub); - jerr.pub.output_message = jpg_output_message; - jerr.pub.error_exit = jpg_error_exit; - - jpeg_create_decompress (&cinfo); - jpeg_stdio_src (&cinfo, in); - jpeg_read_header (&cinfo, TRUE); - - /* set some decode parameters */ - cinfo.out_color_space = JCS_RGB; - cinfo.quantize_colors = FALSE; - - jpeg_start_decompress (&cinfo); - - ximage = XCreateImage (dpy, visual, depth, ZPixmap, 0, 0, - cinfo.output_width, cinfo.output_height, - 8, 0); - if (ximage) - ximage->data = (char *) calloc (ximage->height, ximage->bytes_per_line); - - if (ximage && ximage->data) - scanbuf = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, - cinfo.rec_outbuf_height * - cinfo.output_width * - cinfo.output_components, - 1); - if (!ximage || !ximage->data || !scanbuf) - { - fprintf (stderr, "%s: out of memory loading %dx%d file %s\n", - progname, ximage->width, ximage->height, filename); - goto FAIL; - } - - y = 0; - while (cinfo.output_scanline < cinfo.output_height) - { - int n = jpeg_read_scanlines (&cinfo, scanbuf, 1); - int i; - for (i = 0; i < n; i++) - { - int x; - for (x = 0; x < ximage->width; x++) - { - int j = x * cinfo.output_components; - unsigned char r = scanbuf[i][j]; - unsigned char g = scanbuf[i][j+1]; - unsigned char b = scanbuf[i][j+2]; - unsigned long pixel; - - if (depth > 16) - pixel = (r << 16) | (g << 8) | b; - else if (depth == 8) - pixel = ((r >> 5) | ((g >> 5) << 3) | ((b >> 6) << 6)); - else if (depth == 12) - pixel = ((r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8)); - else if (depth == 15) - /* Gah! I don't understand why these are in the other - order. */ - pixel = (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3))); - else if (depth == 16) - pixel = (((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3))); - else - abort(); - - XPutPixel (ximage, x, y, pixel); - } - y++; - } - } - - if (cinfo.output_scanline < cinfo.output_height) - /* don't goto FAIL -- we might have viewable partial data. */ - jpeg_abort_decompress (&cinfo); - else - jpeg_finish_decompress (&cinfo); - - jpeg_destroy_decompress (&cinfo); - fclose (in); - in = 0; - - return ximage; - - FAIL: - if (in) fclose (in); - if (ximage && ximage->data) - { - free (ximage->data); - ximage->data = 0; - } - if (ximage) XDestroyImage (ximage); - if (scanbuf) free (scanbuf); - return 0; -} - - -/* Reads the given image file and renders it on the Drawable, using JPEG lib. - Returns False if it fails. - */ -static Bool -read_file_jpeglib (Screen *screen, Window window, Drawable drawable, - const char *filename, Bool verbose_p, - XRectangle *geom_ret) -{ - Display *dpy = DisplayOfScreen (screen); - XImage *ximage; - Visual *visual; - int class, depth; - Colormap cmap; - unsigned int win_width, win_height, win_depth; - int srcx, srcy, destx, desty, w2, h2; - - /* Find the size of the Drawable, and the Visual/Colormap of the Window. */ - { - Window root; - int x, y; - unsigned int bw; - XWindowAttributes xgwa; - XGetWindowAttributes (dpy, window, &xgwa); - visual = xgwa.visual; - cmap = xgwa.colormap; - XGetGeometry (dpy, drawable, - &root, &x, &y, &win_width, &win_height, &bw, &win_depth); - } - - /* Make sure we're not on some weirdo visual... - */ - class = visual_class (screen, visual); - depth = visual_depth (screen, visual); - if ((class == PseudoColor || class == DirectColor) && - (depth != 8 && depth != 12)) - { - fprintf (stderr, "%s: Pseudo/DirectColor depth %d unsupported\n", - progname, depth); - return False; - } - - /* Read the file... - */ - ximage = read_jpeg_ximage (screen, visual, drawable, cmap, - filename, verbose_p); - if (!ximage) return False; - - /* Scale it, if necessary... - */ - compute_image_scaling (ximage->width, ximage->height, - win_width, win_height, verbose_p, - &srcx, &srcy, &destx, &desty, &w2, &h2); - if (ximage->width != w2 || ximage->height != h2) - if (! scale_ximage (screen, visual, ximage, w2, h2)) - return False; - - /* Allocate a colormap, if we need to... - */ - if (class == PseudoColor || class == DirectColor) - { - allocate_cubic_colormap (screen, visual, cmap, verbose_p); - remap_image (screen, cmap, ximage, verbose_p); - } - - /* Finally, put the resized image on the window. - */ - { - GC gc; - XGCValues gcv; - - /* If we're rendering onto the root window (and it's not the xscreensaver - pseudo-root) then put the image in the window's background. Otherwise, - just paint the image onto the window. - */ - if (window == drawable && root_window_p (screen, window)) - { - Pixmap bg = XCreatePixmap (dpy, window, - win_width, win_height, win_depth); - gcv.foreground = BlackPixelOfScreen (screen); - gc = XCreateGC (dpy, drawable, GCForeground, &gcv); - XFillRectangle (dpy, bg, gc, 0, 0, win_width, win_height); - XPutImage (dpy, bg, gc, ximage, - srcx, srcy, destx, desty, ximage->width, ximage->height); - XSetWindowBackgroundPixmap (dpy, window, bg); - XClearWindow (dpy, window); - } - else - { - gc = XCreateGC (dpy, drawable, 0, &gcv); - clear_drawable (screen, drawable); - XPutImage (dpy, drawable, gc, ximage, - srcx, srcy, destx, desty, ximage->width, ximage->height); - } - - XFreeGC (dpy, gc); - } - - if (geom_ret) - { - geom_ret->x = destx; - geom_ret->y = desty; - geom_ret->width = ximage->width; - geom_ret->height = ximage->height; - } - - free (ximage->data); - ximage->data = 0; - XDestroyImage (ximage); - XSync (dpy, False); - return True; -} - -#endif /* HAVE_JPEGLIB */ - - -/* Reads the given image file and renders it on the Drawable. - Returns False if it fails. - */ -static Bool -display_file (Screen *screen, Window window, Drawable drawable, - const char *filename, Bool verbose_p, - XRectangle *geom_ret) -{ - if (verbose_p) - fprintf (stderr, "%s: loading \"%s\"\n", progname, filename); - -# if defined(HAVE_GDK_PIXBUF) - if (read_file_gdk (screen, window, drawable, filename, verbose_p, geom_ret)) - return True; -# elif defined(HAVE_JPEGLIB) - if (read_file_jpeglib (screen, window, drawable, filename, verbose_p, - geom_ret)) - return True; -# else /* !(HAVE_GDK_PIXBUF || HAVE_JPEGLIB) */ - /* shouldn't get here if we have no image-loading methods available. */ - abort(); -# endif /* !(HAVE_GDK_PIXBUF || HAVE_JPEGLIB) */ - - return False; -} - - -/* Invokes a sub-process and returns its output (presumably, a file to - load.) Free the string when done. 'grab_type' controls which program - to run. Returned pathname may be relative to 'directory', or absolute. - */ -static char * -get_filename_1 (Screen *screen, const char *directory, grab_type type, - Bool verbose_p) -{ - Display *dpy = DisplayOfScreen (screen); - pid_t forked; - int fds [2]; - int in, out; - char buf[10240]; - char *av[20]; - int ac = 0; - - switch (type) - { - case GRAB_FILE: - av[ac++] = GETIMAGE_FILE_PROGRAM; - if (verbose_p) - av[ac++] = "--verbose"; - av[ac++] = "--name"; - av[ac++] = (char *) directory; - break; - - case GRAB_VIDEO: - av[ac++] = GETIMAGE_VIDEO_PROGRAM; - if (verbose_p) - av[ac++] = "--verbose"; - av[ac++] = "--name"; - break; - -# ifdef USE_EXTERNAL_SCREEN_GRABBER - case GRAB_DESK: - av[ac++] = GETIMAGE_SCREEN_PROGRAM; - if (verbose_p) - av[ac++] = "--verbose"; - av[ac++] = "--name"; - break; -# endif - - default: - abort(); - } - av[ac] = 0; - - if (verbose_p) - { - int i; - fprintf (stderr, "%s: executing:", progname); - for (i = 0; i < ac; i++) - fprintf (stderr, " %s", av[i]); - fprintf (stderr, "\n"); - } - - if (pipe (fds)) - { - sprintf (buf, "%s: error creating pipe", progname); - perror (buf); - return 0; - } - - in = fds [0]; - out = fds [1]; - - switch ((int) (forked = fork ())) - { - case -1: - { - sprintf (buf, "%s: couldn't fork", progname); - perror (buf); - return 0; - } - case 0: - { - int stdout_fd = 1; - - close (in); /* don't need this one */ - close (ConnectionNumber (dpy)); /* close display fd */ - - if (dup2 (out, stdout_fd) < 0) /* pipe stdout */ - { - sprintf (buf, "%s: could not dup() a new stdout", progname); - exit (-1); /* exits fork */ - } - - execvp (av[0], av); /* shouldn't return. */ - exit (-1); /* exits fork */ - break; - } - default: - { - struct stat st; - int wait_status = 0; - FILE *f = fdopen (in, "r"); - int L; - char *ret = 0; - - close (out); /* don't need this one */ - *buf = 0; - if (! fgets (buf, sizeof(buf)-1, f)) - *buf = 0; - fclose (f); - - /* Wait for the child to die. */ - waitpid (-1, &wait_status, 0); - - L = strlen (buf); - while (L && buf[L-1] == '\n') - buf[--L] = 0; - - if (!*buf) - return 0; - - ret = strdup (buf); - - if (*ret != '/') - { - /* Program returned path relative to directory. Prepend dir - to buf so that we can properly stat it. */ - strcpy (buf, directory); - if (directory[strlen(directory)-1] != '/') - strcat (buf, "/"); - strcat (buf, ret); - } - - if (stat(buf, &st)) - { - fprintf (stderr, "%s: file does not exist: \"%s\"\n", - progname, buf); - free (ret); - return 0; - } - else - return ret; - } - } - - abort(); -} - - -/* Returns a pathname to an image file. Free the string when you're done. - */ -static char * -get_filename (Screen *screen, const char *directory, Bool verbose_p) -{ - return get_filename_1 (screen, directory, GRAB_FILE, verbose_p); -} - - -/* Grabs a video frame to a file, and returns a pathname to that file. - Delete that file when you are done with it (and free the string.) - */ -static char * -get_video_filename (Screen *screen, Bool verbose_p) -{ - return get_filename_1 (screen, 0, GRAB_VIDEO, verbose_p); -} - -/* Grabs a desktop image to a file, and returns a pathname to that file. - Delete that file when you are done with it (and free the string.) - */ -# ifdef USE_EXTERNAL_SCREEN_GRABBER -static char * -get_desktop_filename (Screen *screen, Bool verbose_p) -{ - return get_filename_1 (screen, 0, GRAB_DESK, verbose_p); -} -#endif /* USE_EXTERNAL_SCREEN_GRABBER */ - - -/* Grabs a video frame, and renders it on the Drawable. - Returns False if it fails; - */ -static Bool -display_video (Screen *screen, Window window, Drawable drawable, - Bool verbose_p, XRectangle *geom_ret) -{ - char *filename = get_video_filename (screen, verbose_p); - Bool status; - - if (!filename) - { - if (verbose_p) - fprintf (stderr, "%s: video grab failed.\n", progname); - return False; - } - - status = display_file (screen, window, drawable, filename, verbose_p, - geom_ret); - - if (unlink (filename)) - { - char buf[512]; - sprintf (buf, "%s: rm %.100s", progname, filename); - perror (buf); - } - else if (verbose_p) - fprintf (stderr, "%s: rm %s\n", progname, filename); - - if (filename) free (filename); - return status; -} - - -/* Grabs a desktop screen shot onto the window and the drawable. - If the window and drawable are not the same size, the image in - the drawable is scaled to fit. - Returns False if it fails. - */ -static Bool -display_desktop (Screen *screen, Window window, Drawable drawable, - Bool verbose_p, XRectangle *geom_ret) -{ -# ifdef USE_EXTERNAL_SCREEN_GRABBER - - Display *dpy = DisplayOfScreen (screen); - Bool top_p = top_level_window_p (screen, window); - char *filename; - Bool status; - - if (top_p) - { - if (verbose_p) - fprintf (stderr, "%s: unmapping 0x%lx.\n", progname, - (unsigned long) window); - XUnmapWindow (dpy, window); - XSync (dpy, False); - } - - filename = get_desktop_filename (screen, verbose_p); - - if (top_p) - { - if (verbose_p) - fprintf (stderr, "%s: mapping 0x%lx.\n", progname, - (unsigned long) window); - XMapRaised (dpy, window); - XSync (dpy, False); - } - - if (!filename) - { - if (verbose_p) - fprintf (stderr, "%s: desktop grab failed.\n", progname); - return False; - } - - status = display_file (screen, window, drawable, filename, verbose_p, - geom_ret); - - if (unlink (filename)) - { - char buf[512]; - sprintf (buf, "%s: rm %.100s", progname, filename); - perror (buf); - } - else if (verbose_p) - fprintf (stderr, "%s: rm %s\n", progname, filename); - - if (filename) free (filename); - return status; - -# else /* !USE_EXTERNAL_SCREEN_GRABBER */ - - Display *dpy = DisplayOfScreen (screen); - XGCValues gcv; - XWindowAttributes xgwa; - Window root; - int px, py; - unsigned int pw, ph, pbw, pd; - int srcx, srcy, destx, desty, w2, h2; - - if (verbose_p) - { - fprintf (stderr, "%s: grabbing desktop image\n", progname); - grabscreen_verbose(); - } - - XGetWindowAttributes (dpy, window, &xgwa); - XGetGeometry (dpy, drawable, &root, &px, &py, &pw, &ph, &pbw, &pd); - - grab_screen_image_internal (screen, window); - - compute_image_scaling (xgwa.width, xgwa.height, - pw, ph, verbose_p, - &srcx, &srcy, &destx, &desty, &w2, &h2); - - if (pw == w2 && ph == h2) /* it fits -- just copy server-side pixmaps */ - { - GC gc = XCreateGC (dpy, drawable, 0, &gcv); - XCopyArea (dpy, window, drawable, gc, - 0, 0, xgwa.width, xgwa.height, 0, 0); - XFreeGC (dpy, gc); - } - else /* size mismatch -- must scale client-side images to fit drawable */ - { - GC gc; - XImage *ximage = 0; - XErrorHandler old_handler; - - XSync (dpy, False); - old_handler = XSetErrorHandler (ignore_badmatch_ehandler); - error_handler_hit_p = False; - - /* This can return BadMatch if the window is not fully on screen. - Trap that error and return color bars in that case. - (Note that this only happens with XGetImage, not with XCopyArea: - yet another totally gratuitous inconsistency in X, thanks.) - */ - ximage = XGetImage (dpy, window, 0, 0, xgwa.width, xgwa.height, - ~0L, ZPixmap); - - XSync (dpy, False); - XSetErrorHandler (old_handler); - XSync (dpy, False); - - if (error_handler_hit_p) - { - ximage = 0; - if (verbose_p) - fprintf (stderr, "%s: BadMatch reading window 0x%x contents!\n", - progname, (unsigned int) window); - } - - if (!ximage || - !scale_ximage (xgwa.screen, xgwa.visual, ximage, w2, h2)) - return False; - - gc = XCreateGC (dpy, drawable, 0, &gcv); - clear_drawable (screen, drawable); - XPutImage (dpy, drawable, gc, ximage, - srcx, srcy, destx, desty, ximage->width, ximage->height); - XDestroyImage (ximage); - XFreeGC (dpy, gc); - } - - if (geom_ret) - { - geom_ret->x = destx; - geom_ret->y = desty; - geom_ret->width = w2; - geom_ret->height = h2; - } - - XSync (dpy, False); - return True; - -# endif /* !USE_EXTERNAL_SCREEN_GRABBER */ -} - - -/* Whether the given Drawable is unreasonably small. - */ -static Bool -drawable_miniscule_p (Display *dpy, Drawable drawable) -{ - Window root; - int xx, yy; - unsigned int bw, d, w = 0, h = 0; - XGetGeometry (dpy, drawable, &root, &xx, &yy, &w, &h, &bw, &d); - return (w < 32 || h < 30); -} - - -/* Grabs an image (from a file, video, or the desktop) and renders it on - the Drawable. If `file' is specified, always use that file. Otherwise, - select randomly, based on the other arguments. - */ -static void -get_image (Screen *screen, - Window window, Drawable drawable, - Bool verbose_p, - Bool desk_p, - Bool video_p, - Bool image_p, - const char *dir, - const char *file) -{ - Display *dpy = DisplayOfScreen (screen); - grab_type which = GRAB_BARS; - struct stat st; - const char *file_prop = 0; - char *absfile = 0; - XRectangle geom = { 0, 0, 0, 0 }; - - if (! drawable_window_p (dpy, window)) - { - fprintf (stderr, "%s: 0x%lx is a pixmap, not a window!\n", - progname, (unsigned long) window); - exit (1); - } - - /* Make sure the Screen and the Window correspond. */ - { - XWindowAttributes xgwa; - XGetWindowAttributes (dpy, window, &xgwa); - screen = xgwa.screen; - } - - if (file && stat (file, &st)) - { - fprintf (stderr, "%s: file \"%s\" does not exist\n", progname, file); - file = 0; - } - - if (verbose_p) - { - fprintf (stderr, "%s: grabDesktopImages: %s\n", - progname, desk_p ? "True" : "False"); - fprintf (stderr, "%s: grabVideoFrames: %s\n", - progname, video_p ? "True" : "False"); - fprintf (stderr, "%s: chooseRandomImages: %s\n", - progname, image_p ? "True" : "False"); - fprintf (stderr, "%s: imageDirectory: %s\n", - progname, (file ? file : dir ? dir : "")); - } - -# if !(defined(HAVE_GDK_PIXBUF) || defined(HAVE_JPEGLIB)) - image_p = False; /* can't load images from files... */ -# ifdef USE_EXTERNAL_SCREEN_GRABBER - desk_p = False; /* ...or from desktops grabbed to files. */ -# endif - - if (file) - { - fprintf (stderr, - "%s: image file loading not available at compile-time\n", - progname); - fprintf (stderr, "%s: can't load \"%s\"\n", progname, file); - file = 0; - } -# endif /* !(HAVE_GDK_PIXBUF || HAVE_JPEGLIB) */ - - if (file) - { - desk_p = False; - video_p = False; - image_p = True; - } - else if (!dir || !*dir) - { - if (verbose_p && image_p) - fprintf (stderr, - "%s: no imageDirectory: turning off chooseRandomImages.\n", - progname); - image_p = False; - } - - /* If the target drawable is really small, no good can come of that. - Always do colorbars in that case. - */ - if (drawable_miniscule_p (dpy, drawable)) - { - desk_p = False; - video_p = False; - image_p = False; - } - -# ifndef _VROOT_H_ -# error Error! This file definitely needs vroot.h! -# endif - - /* We can grab desktop images (using the normal X11 method) if: - - the window is the real root window; - - the window is a toplevel window. - We cannot grab desktop images that way if: - - the window is a non-top-level window. - - Under X11 on MacOS, desktops are just like loaded image files. - Under Cocoa on MacOS, this code is not used at all. - */ -# ifndef USE_EXTERNAL_SCREEN_GRABBER - if (desk_p) - { - if (!top_level_window_p (screen, window)) - { - desk_p = False; - if (verbose_p) - fprintf (stderr, - "%s: 0x%x not top-level: turning off grabDesktopImages.\n", - progname, (unsigned int) window); - } - } -# endif /* !USE_EXTERNAL_SCREEN_GRABBER */ - - if (! (desk_p || video_p || image_p)) - which = GRAB_BARS; - else - { - int i = 0; - int n; - /* Loop until we get one that's permitted. - If files or video are permitted, do them more often - than desktop. - - D+V+I: 10% + 45% + 45%. - V+I: 50% + 50% - D+V: 18% + 82% - D+I: 18% + 82% - */ - AGAIN: - n = (random() % 100); - if (++i > 300) abort(); - else if (desk_p && n < 10) which = GRAB_DESK; /* 10% */ - else if (video_p && n < 55) which = GRAB_VIDEO; /* 45% */ - else if (image_p) which = GRAB_FILE; /* 45% */ - else goto AGAIN; - } - - - /* If we're to search a directory to find an image file, do so now. - */ - if (which == GRAB_FILE && !file) - { - file = get_filename (screen, dir, verbose_p); - if (!file) - { - which = GRAB_BARS; - if (verbose_p) - fprintf (stderr, "%s: no image files found.\n", progname); - } - } - - /* Now actually render something. - */ - switch (which) - { - case GRAB_BARS: - { - XWindowAttributes xgwa; - COLORBARS: - if (verbose_p) - fprintf (stderr, "%s: drawing colorbars.\n", progname); - XGetWindowAttributes (dpy, window, &xgwa); - colorbars (screen, xgwa.visual, drawable, xgwa.colormap); - XSync (dpy, False); - if (! file_prop) file_prop = ""; - - } - break; - - case GRAB_DESK: - if (! display_desktop (screen, window, drawable, verbose_p, &geom)) - goto COLORBARS; - file_prop = "desktop"; - break; - - case GRAB_FILE: - if (*file && *file != '/') /* pathname is relative to dir. */ - { - if (absfile) free (absfile); - absfile = malloc (strlen(dir) + strlen(file) + 10); - strcpy (absfile, dir); - if (dir[strlen(dir)-1] != '/') - strcat (absfile, "/"); - strcat (absfile, file); - } - if (! display_file (screen, window, drawable, - (absfile ? absfile : file), - verbose_p, &geom)) - goto COLORBARS; - file_prop = file; - break; - - case GRAB_VIDEO: - if (! display_video (screen, window, drawable, verbose_p, &geom)) - goto COLORBARS; - file_prop = "video"; - break; - - default: - abort(); - break; - } - - { - Atom a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_FILENAME, False); - if (file_prop && *file_prop) - { - char *f2 = strdup (file_prop); - - /* Take the extension off of the file name. */ - /* Duplicated in utils/grabclient.c. */ - char *slash = strrchr (f2, '/'); - char *dot = strrchr ((slash ? slash : f2), '.'); - if (dot) *dot = 0; - /* Replace slashes with newlines */ - /* while ((dot = strchr(f2, '/'))) *dot = '\n'; */ - /* Replace slashes with spaces */ - /* while ((dot = strchr(f2, '/'))) *dot = ' '; */ - - XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace, - (unsigned char *) f2, strlen(f2)); - free (f2); - } - else - XDeleteProperty (dpy, window, a); - - a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_GEOMETRY, False); - if (geom.width > 0) - { - char gstr[30]; - sprintf (gstr, "%dx%d+%d+%d", geom.width, geom.height, geom.x, geom.y); - XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace, - (unsigned char *) gstr, strlen (gstr)); - } - else - XDeleteProperty (dpy, window, a); - } - - if (absfile) free (absfile); - XSync (dpy, False); -} - - -#ifdef DEBUG -static Bool -mapper (XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks, - XrmRepresentation *type, XrmValue *value, XPointer closure) -{ - int i; - for (i = 0; quarks[i]; i++) - { - if (bindings[i] == XrmBindTightly) - fprintf (stderr, (i == 0 ? "" : ".")); - else if (bindings[i] == XrmBindLoosely) - fprintf (stderr, "*"); - else - fprintf (stderr, " ??? "); - fprintf(stderr, "%s", XrmQuarkToString (quarks[i])); - } - - fprintf (stderr, ": %s\n", (char *) value->addr); - - return False; -} -#endif /* DEBUG */ - - -#define USAGE "usage: %s [ -options... ] window-id [pixmap-id]\n" \ - "\n" \ - " %s\n" \ - "\n" \ - " %s puts an image on the given window or pixmap.\n" \ - "\n" \ - " It is used by those xscreensaver demos that operate on images.\n" \ - " The image may be a file loaded from disk, a frame grabbed from\n" \ - " the system's video camera, or a screenshot of the desktop,\n" \ - " depending on command-line options or the ~/.xscreensaver file.\n" \ - "\n" \ - " Options include:\n" \ - "\n" \ - " -display host:dpy.screen which display to use\n" \ - " -root draw to the root window\n" \ - " -verbose print diagnostics\n" \ - " -images / -no-images whether to allow image file loading\n" \ - " -video / -no-video whether to allow video grabs\n" \ - " -desktop / -no-desktop whether to allow desktop screen grabs\n"\ - " -directory <path> where to find image files to load\n" \ - " -file <filename> load this image file\n" \ - "\n" \ - " The XScreenSaver Control Panel (xscreensaver-demo) lets you set the\n"\ - " defaults for these options in your ~/.xscreensaver file.\n" \ - "\n" - -int -main (int argc, char **argv) -{ - saver_preferences P; - Widget toplevel; - Display *dpy; - Screen *screen; - char *oprogname = progname; - char *file = 0; - char version[255]; - - Window window = (Window) 0; - Drawable drawable = (Drawable) 0; - const char *window_str = 0; - const char *drawable_str = 0; - char *s; - int i; - - progname = argv[0]; - s = strrchr (progname, '/'); - if (s) progname = s+1; - oprogname = progname; - - /* half-assed way of avoiding buffer-overrun attacks. */ - if (strlen (progname) >= 100) progname[100] = 0; - -# ifndef _VROOT_H_ -# error Error! This file definitely needs vroot.h! -# endif - - /* Get the version number, for error messages. */ - { - char *v = (char *) strdup(strchr(screensaver_id, ' ')); - char *s1, *s2, *s3, *s4; - s1 = (char *) strchr(v, ' '); s1++; - s2 = (char *) strchr(s1, ' '); - s3 = (char *) strchr(v, '('); s3++; - s4 = (char *) strchr(s3, ')'); - *s2 = 0; - *s4 = 0; - sprintf (version, "Part of XScreenSaver %s -- %s.", s1, s3); - free(v); - } - - /* We must read exactly the same resources as xscreensaver. - That means we must have both the same progclass *and* progname, - at least as far as the resource database is concerned. So, - put "xscreensaver" in argv[0] while initializing Xt. - */ - progname = argv[0] = "xscreensaver"; - - /* allow one dash or two. */ - for (i = 1; i < argc; i++) - if (argv[i][0] == '-' && argv[i][1] == '-') argv[i]++; - - toplevel = XtAppInitialize (&app, progclass, 0, 0, &argc, argv, - defaults, 0, 0); - dpy = XtDisplay (toplevel); - screen = XtScreen (toplevel); - db = XtDatabase (dpy); - XtGetApplicationNameAndClass (dpy, &s, &progclass); - XSetErrorHandler (x_ehandler); - XSync (dpy, False); - - /* Randomize -- only need to do this here because this program - doesn't use the `screenhack.h' or `lockmore.h' APIs. */ -# undef ya_rand_init - ya_rand_init (0); - - memset (&P, 0, sizeof(P)); - P.db = db; - load_init_file (dpy, &P); - - progname = argv[0] = oprogname; - - for (i = 1; i < argc; i++) - { - unsigned long w; - char dummy; - - /* Have to re-process these, or else the .xscreensaver file - has priority over the command line... - */ - if (!strcmp (argv[i], "-v") || !strcmp (argv[i], "-verbose")) - P.verbose_p = True; - else if (!strcmp (argv[i], "-desktop")) P.grab_desktop_p = True; - else if (!strcmp (argv[i], "-no-desktop")) P.grab_desktop_p = False; - else if (!strcmp (argv[i], "-video")) P.grab_video_p = True; - else if (!strcmp (argv[i], "-no-video")) P.grab_video_p = False; - else if (!strcmp (argv[i], "-images")) P.random_image_p = True; - else if (!strcmp (argv[i], "-no-images")) P.random_image_p = False; - else if (!strcmp (argv[i], "-file")) file = argv[++i]; - else if (!strcmp (argv[i], "-directory") || !strcmp (argv[i], "-dir")) - P.image_directory = argv[++i]; - else if (!strcmp (argv[i], "-root") || !strcmp (argv[i], "root")) - { - if (window) - { - fprintf (stderr, "%s: both %s and %s specified?\n", - progname, argv[i], window_str); - goto LOSE; - } - window_str = argv[i]; - window = VirtualRootWindowOfScreen (screen); - } - else if ((1 == sscanf (argv[i], " 0x%lx %c", &w, &dummy) || - 1 == sscanf (argv[i], " %lu %c", &w, &dummy)) && - w != 0) - { - if (drawable) - { - fprintf (stderr, "%s: both %s and %s specified?\n", - progname, drawable_str, argv[i]); - goto LOSE; - } - else if (window) - { - drawable_str = argv[i]; - drawable = (Drawable) w; - } - else - { - window_str = argv[i]; - window = (Window) w; - } - } - else - { - if (argv[i][0] == '-') - fprintf (stderr, "\n%s: unknown option \"%s\"\n", - progname, argv[i]); - else - fprintf (stderr, "\n%s: unparsable window/pixmap ID: \"%s\"\n", - progname, argv[i]); - LOSE: -# ifdef __GNUC__ - __extension__ /* don't warn about "string length is greater than - the length ISO C89 compilers are required to - support" in the usage string... */ -# endif - fprintf (stderr, USAGE, progname, version, progname); - exit (1); - } - } - - if (window == 0) - { - fprintf (stderr, "\n%s: no window ID specified!\n", progname); - goto LOSE; - } - - -#ifdef DEBUG - if (P.verbose_p) /* Print out all the resources we can see. */ - { - XrmName name = { 0 }; - XrmClass class = { 0 }; - int count = 0; - XrmEnumerateDatabase (db, &name, &class, XrmEnumAllLevels, mapper, - (XtPointer) &count); - } -#endif /* DEBUG */ - - if (!window) abort(); - if (!drawable) drawable = window; - - get_image (screen, window, drawable, P.verbose_p, - P.grab_desktop_p, P.grab_video_p, P.random_image_p, - P.image_directory, file); - exit (0); -} diff --git a/driver/xset.c b/driver/xset.c deleted file mode 100644 index a381429..0000000 --- a/driver/xset.c +++ /dev/null @@ -1,389 +0,0 @@ -/* xset.c --- interacting with server extensions and the builtin screensaver. - * xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/Xos.h> - -/* This file doesn't need the Xt headers, so stub these types out... */ -#undef XtPointer -#define XtAppContext void* -#define XrmDatabase void* -#define XtIntervalId void* -#define XtPointer void* -#define Widget void* - -#include "xscreensaver.h" - -#ifdef _VROOT_H_ -ERROR! You must not include vroot.h in this file. -#endif - - -/* MIT SCREEN-SAVER server extension hackery. - */ - -#ifdef HAVE_MIT_SAVER_EXTENSION - -# include <X11/extensions/scrnsaver.h> - -static int -ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) -{ - return 0; -} - -static void -init_mit_saver_extension (saver_info *si) -{ - int i; - Pixmap *blank_pix = (Pixmap *) calloc (sizeof(Pixmap), si->nscreens); - - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - XID kill_id = 0; - Atom kill_type = 0; - Window root = RootWindowOfScreen (ssi->screen); - blank_pix[i] = XCreatePixmap (si->dpy, root, 1, 1, 1); - - /* Kill off the old MIT-SCREEN-SAVER client if there is one. - This tends to generate X errors, though (possibly due to a bug - in the server extension itself?) so just ignore errors here. */ - if (XScreenSaverGetRegistered (si->dpy, - XScreenNumberOfScreen (ssi->screen), - &kill_id, &kill_type) - && kill_id != blank_pix[i]) - { - XErrorHandler old_handler = - XSetErrorHandler (ignore_all_errors_ehandler); - XKillClient (si->dpy, kill_id); - XSync (si->dpy, False); - XSetErrorHandler (old_handler); - } - XScreenSaverSelectInput (si->dpy, root, ScreenSaverNotifyMask); - XScreenSaverRegister (si->dpy, - XScreenNumberOfScreen (ssi->screen), - (XID) blank_pix[i], XA_PIXMAP); - } - free(blank_pix); -} -#endif /* HAVE_MIT_SAVER_EXTENSION */ - - -#ifdef HAVE_XINPUT -/* XInputExtension device support */ - -Bool -query_xinput_extension (saver_info *si) -{ - XExtCodes codes; - return XQueryExtension (si->dpy, INAME, &codes.major_opcode, - &codes.first_event, &codes.first_error); -} - -void -init_xinput_extension (saver_info *si) -{ - int i, ndevices; - int class; - XDeviceInfo *list; - XDevice *dev; - XAnyClassPtr pClass; - XEventClass *event_list; - int nevents = 0; - - /* skip if already initialized */ - if (si->num_xinput_devices && si->xinput_devices) - return; - - si->num_xinput_devices = 0; - - list = XListInputDevices (si->dpy, &ndevices); - if (list == NULL) - { - si->xinput_devices = NULL; - return; - } - - /* We only care about 3 event types per device (DeviceButtonPress, - DeviceButtonRelease, and DeviceMotionNotify), hence the "* 3" - for the event count. */ - event_list = calloc(ndevices * 3, sizeof(XEventClass)); - if (event_list == NULL) - return; - - si->xinput_devices = calloc(ndevices, sizeof(struct xinput_dev_info)); - if (si->xinput_devices == NULL) - { - free(event_list); - return; - } - - for (i = 0; i < ndevices; i++) - { - if ((list[i].use == IsXExtensionDevice) -#ifdef IsXExtensionPointer - || (list[i].use == IsXExtensionPointer) -#endif - ) - { - struct xinput_dev_info *dev_info = - &si->xinput_devices[si->num_xinput_devices]; - Bool device_we_want = False; - - if (si->prefs.debug_p) - fprintf(stderr, - "Extension device #%2d: XID=%2d type=%3d name=\"%s\"\n", - i, (int) list[i].id, (int) list[i].type, list[i].name); - - dev = XOpenDevice (si->dpy, list[i].id); - if (!dev) - continue; - dev_info->device = dev; - - pClass = list[i].inputclassinfo; - for (class = 0; class < list[i].num_classes; class++) - { - switch (pClass->class) - { - case ButtonClass: - if (((XButtonInfo *) pClass)->num_buttons > 0) - { - /* Macros set values in the second & third arguments */ - DeviceButtonPress (dev, si->xinput_DeviceButtonPress, - dev_info->press); - event_list[nevents++] = dev_info->press; - - DeviceButtonRelease (dev, si->xinput_DeviceButtonRelease, - dev_info->release); - event_list[nevents++] = dev_info->release; - device_we_want = True; - } - break; - - case ValuatorClass: - if (((XValuatorInfo *) pClass)->num_axes > 0) - { - DeviceMotionNotify (dev, si->xinput_DeviceMotionNotify, - dev_info->valuator); - event_list[nevents++] = dev_info->valuator; - device_we_want = True; - } - break; - - default: - /* ignore other classes of devices/events */ - break; - } - - pClass = (XAnyClassPtr) & ((char *) pClass)[pClass->length]; - } - - if (device_we_want) - si->num_xinput_devices++; - else - XCloseDevice (si->dpy, dev); - } - } - - if (list) - XFreeDeviceList (list); - - if ((nevents == 0) || (si->num_xinput_devices == 0)) - { - free(event_list); - free(si->xinput_devices); - si->xinput_devices = NULL; - si->num_xinput_devices = 0; - return; - } - - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - Window root = RootWindowOfScreen (ssi->screen); - XSelectExtensionEvent (si->dpy, root, event_list, nevents); - } - - free(event_list); -} - -#if 0 -/* not used */ -static void -close_xinput_extension (saver_info *si) -{ - int i; - - for (i = 0; i < si->num_xinput_devices; i++) - XCloseDevice (si->dpy, si->xinput_devices[i].device); - - free(si->xinput_devices); - si->xinput_devices = NULL; - si->num_xinput_devices = 0; -} -#endif -#endif /* HAVE_XINPUT */ - - -/* SGI SCREEN_SAVER server extension hackery. - */ - -#ifdef HAVE_SGI_SAVER_EXTENSION - -# include <X11/extensions/XScreenSaver.h> - -static void -init_sgi_saver_extension (saver_info *si) -{ - saver_preferences *p = &si->prefs; - int i; - if (si->screen_blanked_p) - /* If you mess with this while the server thinks it's active, - the server crashes. */ - return; - - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - XScreenSaverDisable (si->dpy, XScreenNumberOfScreen(ssi->screen)); - if (! XScreenSaverEnable (si->dpy, XScreenNumberOfScreen(ssi->screen))) - { - fprintf (stderr, - "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\ - perhaps some other screensaver program is already running?\n", - blurb()); - si->using_sgi_saver_extension = False; - return; - } - } -} - -#endif /* HAVE_SGI_SAVER_EXTENSION */ - - - -/* Figuring out what the appropriate XSetScreenSaver() parameters are - (one wouldn't expect this to be rocket science.) - */ - -void -disable_builtin_screensaver (saver_info *si, Bool unblank_screen_p) -{ - saver_preferences *p = &si->prefs; - int current_server_timeout, current_server_interval; - int current_prefer_blank, current_allow_exp; - int desired_server_timeout, desired_server_interval; - int desired_prefer_blank, desired_allow_exp; - - XGetScreenSaver (si->dpy, ¤t_server_timeout, ¤t_server_interval, - ¤t_prefer_blank, ¤t_allow_exp); - - desired_server_timeout = current_server_timeout; - desired_server_interval = current_server_interval; - desired_prefer_blank = current_prefer_blank; - desired_allow_exp = current_allow_exp; - - /* On SGIs, if interval is non-zero, it is the number of seconds after - screen saving starts at which the monitor should be powered down. - Obviously I don't want that, so set it to 0 (meaning "never".) - - Power saving is disabled if DontPreferBlanking, but in that case, - we don't get extension events either. So we can't turn it off that way. - - Note: if you're running Irix 6.3 (O2), you may find that your monitor is - powering down anyway, regardless of the xset settings. This is fixed by - installing SGI patches 2447 and 2537. - */ - desired_server_interval = 0; - - /* I suspect (but am not sure) that DontAllowExposures might have - something to do with powering off the monitor as well, at least - on some systems that don't support XDPMS? Who knows... */ - desired_allow_exp = AllowExposures; - - if (si->using_mit_saver_extension || si->using_sgi_saver_extension) - { - desired_server_timeout = (p->timeout / 1000); - - /* The SGI extension won't give us events unless blanking is on. - I think (unsure right now) that the MIT extension is the opposite. */ - if (si->using_sgi_saver_extension) - desired_prefer_blank = PreferBlanking; - else - desired_prefer_blank = DontPreferBlanking; - } - else - { - /* When we're not using an extension, set the server-side timeout to 0, - so that the server never gets involved with screen blanking, and we - do it all ourselves. (However, when we *are* using an extension, - we tell the server when to notify us, and rather than blanking the - screen, the server will send us an X event telling us to blank.) - */ - desired_server_timeout = 0; - } - - /* XSetScreenSaver() generates BadValue if either timeout parameter - exceeds 15 bits (signed short.) That is 09:06:07. - */ - if (desired_server_timeout > 0x7FFF) desired_server_timeout = 0x7FFF; - if (desired_server_interval > 0x7FFF) desired_server_interval = 0x7FFF; - - if (desired_server_timeout != current_server_timeout || - desired_server_interval != current_server_interval || - desired_prefer_blank != current_prefer_blank || - desired_allow_exp != current_allow_exp) - { - if (p->verbose_p) - fprintf (stderr, - "%s: disabling server builtin screensaver:\n" - "%s: (xset s %d %d; xset s %s; xset s %s)\n", - blurb(), blurb(), - desired_server_timeout, desired_server_interval, - (desired_prefer_blank ? "blank" : "noblank"), - (desired_allow_exp ? "expose" : "noexpose")); - - XSetScreenSaver (si->dpy, - desired_server_timeout, desired_server_interval, - desired_prefer_blank, desired_allow_exp); - XSync(si->dpy, False); - } - - -#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION) - { - static Bool extension_initted = False; - if (!extension_initted) - { - extension_initted = True; -# ifdef HAVE_MIT_SAVER_EXTENSION - if (si->using_mit_saver_extension) init_mit_saver_extension(si); -# endif -# ifdef HAVE_SGI_SAVER_EXTENSION - if (si->using_sgi_saver_extension) init_sgi_saver_extension(si); -# endif - } - } -#endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */ - - if (unblank_screen_p) - /* Turn off the server builtin saver if it is now running. */ - XForceScreenSaver (si->dpy, ScreenSaverReset); -} |