diff --git a/config.def.h b/config.def.h
index b44fe17..b0bc752 100644
--- a/config.def.h
+++ b/config.def.h
@@ -74,7 +74,15 @@ static unsigned int defaultcs = 256;
 static unsigned int defaultitalic = 11;
 static unsigned int defaultunderline = 7;
 
-/* Internal shortcuts. */
+/* Internal mouse shortcuts. */
+/* Beware that overloading Button1 will disable the selection. */
+static Mousekey mshortcuts[] = {
+	/* keysym		mask		string */
+	{ Button4,		XK_ANY_MOD,	"\031"},
+	{ Button5,		XK_ANY_MOD,	"\005"},
+};
+
+/* Internal keyboard shortcuts. */
 #define MODKEY Mod1Mask
 
 static Shortcut shortcuts[] = {
diff --git a/st.c b/st.c
index 07940d2..aa2cd08 100644
--- a/st.c
+++ b/st.c
@@ -228,6 +228,12 @@ typedef struct {
 	char state; /* focus, redraw, visible */
 } XWindow;
 
+typedef struct {
+	int b;
+	uint mask;
+	char s[ESC_BUF_SIZ];
+} Mousekey;
+
 typedef struct {
 	KeySym k;
 	uint mask;
@@ -771,10 +777,24 @@ mousereport(XEvent *e) {
 void
 bpress(XEvent *e) {
 	struct timeval now;
+	Mousekey *mk;
 
 	if(IS_SET(MODE_MOUSE)) {
 		mousereport(e);
-	} else if(e->xbutton.button == Button1) {
+		return;
+	}
+
+	for(mk = mshortcuts; mk < mshortcuts + LEN(mshortcuts); mk++) {
+		if(e->xbutton.button == mk->b
+				&& match(mk->mask, e->xbutton.state)) {
+			ttywrite(mk->s, strlen(mk->s));
+			if(IS_SET(MODE_ECHO))
+				techo(mk->s, strlen(mk->s));
+			return;
+		}
+	}
+
+	if(e->xbutton.button == Button1) {
 		gettimeofday(&now, NULL);
 
 		/* Clear previous selection, logically and visually. */
@@ -817,10 +837,6 @@ bpress(XEvent *e) {
 		}
 		sel.tclick2 = sel.tclick1;
 		sel.tclick1 = now;
-	} else if(e->xbutton.button == Button4) {
-		ttywrite("\031", 1);
-	} else if(e->xbutton.button == Button5) {
-		ttywrite("\005", 1);
 	}
 }