Screenshot program

One simple problem is this one.
Create a program which has a gui, one button , and creates a png file with contents of your screen when you press it. You could call external programs to create a png, the issue is do this using only library functions. Maybe gtk?

I suspect it’s not actually that simple, in the following sense:

  1. most UI libraries are written to work with windows, not with the entire display
  2. especially, most cross-platform UI libraries will have to eschew accessing the display directly, since such access would be very likely not portable across operating systems or even windowing systems.

So before you can ask “how can I take a screenshot using OCaml libraries ?”, you should ask “how can I take a screenshot using C libraries ?” Once you have the answer to the second question, you can look into whether there is an OCaml library that surfaces that sort of functionality.

I would guess that the answer is “no”, b/c it’s not something people would use often when writing a widget application – from within the application.

This is probably how to do it in dlang

import std.stdio;
import gtk.Main;
import gtk.MainWindow;
import gtk.VBox, gtk.Label, gtk.Button;
import gdk.Gdk;
import gdk.Window;
import gdk.Pixbuf;
private import stdlib = core.stdc.stdlib : exit;

int main(string[] args)
{
	Main.init(args);
	new ApMainWindow();
	Main.run();
	return 0;
}


class ApMainWindow : MainWindow
{
	this()
	{
		super("Screen Capture");
		setTitle("Screen Capture Example");
		setDefaultSize(250, 120);
		VBox box = new VBox(false, 2);
		box.add(new Button("ScreenShot", &screenSave));
		box.add(new Button("Exit", &exitProg));
		add(box);
		showAll();
	}
	
	void screenSave(Button button)
	{
		Window win = Window.getDefaultRootWindow();
		int width = win.getWidth;
		int height = win.getHeight;
		Pixbuf screenshot = getFromWindow(win, 0, 0, width, height);
		screenshot.savev("screenshot.png", "png", null, null);
	}
	
	void exitProg(Button button)
	{
		stdlib.exit(0);
	}
}

Assuming a backend on which your GTK 3 snippet still works, it seems lablgtk didn’t expose gdk_get_default_root_window (it used to be a different macro) or gdk_screen_get_root_window, so that’d be a blocker.

However, your code may not work under Wayland compositors, which specifically restrict this kind of buffer access; no idea about Windows. GTK 4 has in fact removed gdk_get_default_root_window (and root windows as a whole) and points people to use backend-specific APIs instead. @Chet_Murthy’s advice applies here.

You can also call an external program with Unix.execv, like xwd on Linux, or the ImageMagick set of tool include a simple program called import that probably works on any OS.

1 Like