diff --git a/doc/katarakt.txt b/doc/katarakt.txt
index 15ddd1d3147a1acdfabd7ed7118ad415177b0779..adccd230641a260e352b52f25c429b23ef4500e3 100644
--- a/doc/katarakt.txt
+++ b/doc/katarakt.txt
@@ -26,7 +26,7 @@ pixel) scrolling, zooming and adjusting the column count. Pages keep their
 correct relative size and are shown in a grid.
 
 The 'presenter layout' is for giving a presentation. It opens a second window,
-to be viewed on the beamer, and shows the current and next slide in the main
+to be viewed on the projector, and shows the current and next slide in the main
 window.
 
 For every file passed on the command line a separate process is spawned.
@@ -73,7 +73,7 @@ KEY BINDINGS
 *3* ::
 	Switch to 'presenter layout'. Views the current page and a smaller preview
 	of the next page. Also, opens a second window that shows only the current
-	page for displaying on a beamer.
+	page for displaying on a projector.
 
 *Up*, *Down*, *Left*, *Right*, *k*, *j*, *h*, *l* ::
 	Move around (up/down/left/right).
@@ -138,6 +138,9 @@ KEY BINDINGS
 	Show a file dialog to save the current document.
 *F9* ::
 	Toggle the table of contents.
+*x* ::
+	Toggle freezing the slide currently displayed in the projector window. When
+	frozen, scrolling only affects the main window.
 
 VARIABLES
 ---------
diff --git a/share/katarakt.ini b/share/katarakt.ini
index 76188c6b9756e11e13bf106e41f2141dc8e56f56..2fb6334d7cb5915b4e4879706df8b4f7133d2a4a 100644
--- a/share/katarakt.ini
+++ b/share/katarakt.ini
@@ -75,3 +75,4 @@ reload=R
 open=O
 save=S
 toggle_toc=F9
+freeze_presentation=X
diff --git a/src/beamerwindow.cpp b/src/beamerwindow.cpp
index c77e9de7d138848975578cc08cc80ba041267c47..1d81cb2e69d0ef2af702110fce7f31ccaba9bf9e 100644
--- a/src/beamerwindow.cpp
+++ b/src/beamerwindow.cpp
@@ -14,6 +14,7 @@ using namespace std;
 BeamerWindow::BeamerWindow(Viewer *v, QWidget *parent) :
 		QWidget(parent),
 		viewer(v),
+		frozen(false),
 		valid(false) {
 	setFocusPolicy(Qt::StrongFocus);
 
@@ -38,6 +39,15 @@ BeamerWindow::~BeamerWindow() {
 	delete layout;
 }
 
+void BeamerWindow::freeze(bool f) {
+	frozen = f;
+	viewer->get_canvas()->update_page_overlay();
+}
+
+bool BeamerWindow::is_frozen() const {
+	return frozen;
+}
+
 bool BeamerWindow::is_valid() const {
 	return valid;
 }
diff --git a/src/beamerwindow.h b/src/beamerwindow.h
index b10566e0491b4b5f05ce9f0a8159fa460adcb148..d9b78bc4e34a494c1b25fd9def1194762cc288bb 100644
--- a/src/beamerwindow.h
+++ b/src/beamerwindow.h
@@ -15,6 +15,9 @@ public:
 	BeamerWindow(Viewer *v, QWidget *parent = 0);
 	~BeamerWindow();
 
+	void freeze(bool f);
+	bool is_frozen() const;
+
 	bool is_valid() const;
 
 	Layout *get_layout() const;
@@ -43,6 +46,7 @@ private:
 
 	Qt::MouseButton click_link_button;
 
+	bool frozen;
 	bool valid;
 };
 
diff --git a/src/canvas.cpp b/src/canvas.cpp
index 7f6697bff6f4a270a159d7ebaffeb6c47d70c511..b6b31addcf490efb951d03b49f6d62ad1fe51b0d 100644
--- a/src/canvas.cpp
+++ b/src/canvas.cpp
@@ -168,10 +168,14 @@ Layout *Canvas::get_layout() const {
 }
 
 void Canvas::update_page_overlay() {
+	QString frozen_text;
+	if (viewer->get_beamer()->is_frozen()) {
+		frozen_text = QString("Frozen: %1, ").arg(viewer->get_beamer()->get_layout()->get_page() + 1);
+	}
 	QString overlay_text = CFG::get_instance()->get_value("Settings/page_overlay_text").toString()
 		.arg(cur_layout->get_page() + 1)
 		.arg(viewer->get_res()->get_page_count());
-	page_overlay->setText(overlay_text);
+	page_overlay->setText(frozen_text + overlay_text);
 	page_overlay->adjustSize();
 	page_overlay->move(width() - page_overlay->width(), height() - page_overlay->height());
 }
@@ -371,7 +375,9 @@ void Canvas::set_presenter_layout() {
 //		int cur_screen = desktop->screenNumber(viewer);
 //		cout << "primary: " << primary_screen << ", current: " << cur_screen << endl;
 //	}
-	viewer->get_beamer()->get_layout()->scroll_page(cur_layout->get_page(), false);
+	if (!viewer->get_beamer()->is_frozen()) {
+		viewer->get_beamer()->get_layout()->scroll_page(cur_layout->get_page(), false);
+	}
 	viewer->get_beamer()->show();
 	viewer->show_progress(true);
 }
diff --git a/src/config.cpp b/src/config.cpp
index c027d52db914d3efefb774baba5e52490c96c5c5..a900a2a5deb384817f2573e7bfa2c6609da6dd43 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -101,6 +101,7 @@ void CFG::init_defaults() {
 	vk.push_back("Keys/open"); keys[vk.back()] = QStringList() << "O";
 	vk.push_back("Keys/save"); keys[vk.back()] = QStringList() << "S";
 	vk.push_back("Keys/toggle_toc"); keys[vk.back()] = QStringList() << "F9";
+	vk.push_back("Keys/freeze_presentation"); keys[vk.back()] = QStringList() << "X";
 
 	// tmp values
 	tmp_values["start_page"] = 0;
diff --git a/src/layout/gridlayout.cpp b/src/layout/gridlayout.cpp
index 9c3d378113a517fccc2d2cff904e3f9154b41bc9..2ec8260f2f0662d9a8bcdb3ff5ab66d24a030b86 100644
--- a/src/layout/gridlayout.cpp
+++ b/src/layout/gridlayout.cpp
@@ -420,7 +420,7 @@ void GridLayout::render(QPainter *painter) {
 	}
 
 	last_visible_page = last_page;
-	res->collect_garbage(page + horizontal_page - grid->get_offset() - prefetch_count * 3, last_page + prefetch_count * 3);
+	res->collect_garbage(page + horizontal_page - grid->get_offset() - prefetch_count * 3, last_page + prefetch_count * 3, render_index);
 
 	// prefetch
 	int prefetch_first = page + horizontal_page - grid->get_offset() - 1;
diff --git a/src/layout/presenterlayout.cpp b/src/layout/presenterlayout.cpp
index f6f59bf3cd27ccb5eafa7a96f6998d8b68303bd3..56f6b0ef3083a0119d84b20fcecf485636d0f7a7 100644
--- a/src/layout/presenterlayout.cpp
+++ b/src/layout/presenterlayout.cpp
@@ -190,7 +190,9 @@ void PresenterLayout::render(QPainter *painter) {
 			res->unlock_page(page - count);
 		}
 	}
-	res->collect_garbage(page - prefetch_count * 3, page + 1 + prefetch_count * 3);
+	for (int i = 0; i < 2; i++) {
+		res->collect_garbage(page - prefetch_count * 3, page + 1 + prefetch_count * 3, render_index + i);
+	}
 }
 
 void PresenterLayout::advance_invisible_hit(bool forward) {
diff --git a/src/layout/singlelayout.cpp b/src/layout/singlelayout.cpp
index 6e0e081006d890b41f04922e5984e73b1710c7e3..458c759c64371b0118bd9e9033183ddea398d81c 100644
--- a/src/layout/singlelayout.cpp
+++ b/src/layout/singlelayout.cpp
@@ -112,7 +112,7 @@ void SingleLayout::render(QPainter *painter) {
 			res->unlock_page(page - count);
 		}
 	}
-	res->collect_garbage(page - prefetch_count * 3, page + prefetch_count * 3);
+	res->collect_garbage(page - prefetch_count * 3, page + prefetch_count * 3, render_index);
 }
 
 void SingleLayout::advance_invisible_hit(bool forward) {
diff --git a/src/resourcemanager.cpp b/src/resourcemanager.cpp
index 44fcf18d71746eae3750160acbee8f4303eeac29..8c3de19a8869a49b05be4cab1fc56918c9e187db 100644
--- a/src/resourcemanager.cpp
+++ b/src/resourcemanager.cpp
@@ -132,7 +132,9 @@ void ResourceManager::shutdown() {
 		join_threads();
 	}
 	garbageMutex.lock();
-	garbage.clear();
+	for (int i = 0; i < 3; i++) {
+		garbage[i].clear();
+	}
 	garbageMutex.unlock();
 	requests.clear();
 	requestSemaphore.acquire(requestSemaphore.available());
@@ -217,29 +219,29 @@ bool ResourceManager::are_colors_inverted() const {
 	return inverted_colors;
 }
 
-void ResourceManager::collect_garbage(int keep_min, int keep_max) {
+void ResourceManager::collect_garbage(int keep_min, int keep_max, int index) {
 	requestMutex.lock();
-	center_page = (keep_min + keep_max) / 2;
+	if (index == 0) { // make a separate center_page for each index?
+		center_page = (keep_min + keep_max) / 2;
+	}
 	requestMutex.unlock();
 	// free distant pages
 	garbageMutex.lock();
-	for (set<int>::iterator it = garbage.begin(); it != garbage.end(); /* empty */) {
+	for (set<int>::iterator it = garbage[index].begin(); it != garbage[index].end(); /* empty */) {
 		int page = *it;
 		if (page >= keep_min && page <= keep_max) {
 			++it; // move on
 			continue;
 		}
-		garbage.erase(it++); // erase and move on (iterator becomes invalid)
+		garbage[index].erase(it++); // erase and move on (iterator becomes invalid)
 #ifdef DEBUG
 		cerr << "    removing page " << page << endl;
 #endif
 		k_page[page].mutex.lock();
-		for (int i = 0; i < 3; i++) {
-			k_page[page].img[i] = QImage();
-			k_page[page].img_other[i] = QImage();
-			k_page[page].status[i] = 0;
-			k_page[page].rotation[i] = 0;
-		}
+		k_page[page].img[index] = QImage();
+		k_page[page].img_other[index] = QImage();
+		k_page[page].status[index] = 0;
+		k_page[page].rotation[index] = 0;
 		k_page[page].mutex.unlock();
 	}
 	garbageMutex.unlock();
diff --git a/src/resourcemanager.h b/src/resourcemanager.h
index 6211aa363a3343a8c7b99ac381eaf94cd604b289..e83525f01b38edb8b77caf8294c0f4b7654e673b 100644
--- a/src/resourcemanager.h
+++ b/src/resourcemanager.h
@@ -60,7 +60,7 @@ public:
 	void invert_colors();
 	bool are_colors_inverted() const;
 
-	void collect_garbage(int keep_min, int keep_max);
+	void collect_garbage(int keep_min, int keep_max, int index);
 
 	void connect_canvas() const;
 
diff --git a/src/viewer.cpp b/src/viewer.cpp
index 328e1c5326cf04f957b8a3602652ddab67942c5e..1d12690e3954e88267e4f14df74cb7f900a2f2a4 100644
--- a/src/viewer.cpp
+++ b/src/viewer.cpp
@@ -444,6 +444,15 @@ void Viewer::toggle_toc() {
 	toc->setFocus(Qt::OtherFocusReason); // only works if shown
 }
 
+void Viewer::freeze_presentation() {
+	if (beamer->is_frozen()) {
+		beamer->freeze(false);
+		beamer->get_layout()->scroll_page(canvas->get_layout()->get_page(), false);
+	} else {
+		beamer->freeze(true);
+	}
+}
+
 void Viewer::update_info_widget() {
 	if (!res->is_valid() || !search_bar->is_valid()) {
 		QIcon icon;
@@ -499,7 +508,7 @@ BeamerWindow *Viewer::get_beamer() const {
 void Viewer::layout_updated(int new_page, bool page_changed) {
 	if (page_changed) {
 		canvas->get_layout()->scroll_page(new_page, false);
-		if (beamer->isVisible()) {
+		if (beamer->isVisible() && !beamer->is_frozen()) {
 			beamer->get_layout()->scroll_page(new_page, false);
 		}
 		// TODO unfold toc tree to show current entry?
@@ -584,5 +593,6 @@ void Viewer::setup_keys(QWidget *base) {
 	add_action(base, "Keys/open", SLOT(open()), this);
 	add_action(base, "Keys/save", SLOT(save()), this);
 	add_action(base, "Keys/toggle_toc", SLOT(toggle_toc()), this);
+	add_action(base, "Keys/freeze_presentation", SLOT(freeze_presentation()), this);
 }
 
diff --git a/src/viewer.h b/src/viewer.h
index cc71381223148ae2f2a216085811ca980891d495..0757477cc7ce0db154bb2c9837e9019793686347 100644
--- a/src/viewer.h
+++ b/src/viewer.h
@@ -83,6 +83,7 @@ private slots:
 	void open(); // ask user for filename
 	void save();
 	void toggle_toc();
+	void freeze_presentation();
 
 private:
 	void update_info_widget();
diff --git a/src/worker.cpp b/src/worker.cpp
index 48beafaadd1fe5ae293a1bd4acf04923e69a4414..d978121c1d0e6de81353456d23736bb61bd78f9d 100644
--- a/src/worker.cpp
+++ b/src/worker.cpp
@@ -84,7 +84,7 @@ void Worker::run() {
 
 		// open page
 #ifdef DEBUG
-		cerr << "    rendering page " << page << " for index " << index << endl;
+		cerr << "    rendering page " << page << " for index " << index << ", center: " << res->center_page << endl;
 #endif
 		Poppler::Page *p = NULL;
 		if (render_new) {
@@ -153,7 +153,7 @@ void Worker::run() {
 		kp.mutex.unlock();
 
 		res->garbageMutex.lock();
-		res->garbage.insert(page); // TODO add index information?
+		res->garbage[index].insert(page);
 		res->garbageMutex.unlock();
 
 		emit page_rendered(page);