Index: src/wp-admin/css/list-tables.css
===================================================================
--- src/wp-admin/css/list-tables.css	(revision 29615)
+++ src/wp-admin/css/list-tables.css	(working copy)
@@ -595,6 +595,11 @@
 	padding: 2px 8px 0 0;
 }
 
+.wp-filter .actions {
+	display: inline-block;
+	vertical-align: middle;
+}
+
 .tablenav .delete {
 	margin-right: 20px;
 }
@@ -617,11 +622,18 @@
 	color: #2ea2cc;
 }
 
-.view-switch {
+tablenav .view-switch {
 	float: right;
 	margin: 5px 16px 0 8px;
 }
 
+.wp-filter .view-switch {
+	display: inline-block;
+	vertical-align: middle;
+	padding: 14px 0;
+	margin: 0 20px 0 0;
+}
+
 .view-switch a {
 	text-decoration: none;
 }
@@ -1437,7 +1449,8 @@
 		display: block;
 	}
 
-	.tablenav.top .actions, .view-switch {
+	.tablenav.top .actions,
+	.tablenav .view-switch {
 		display: none;
 	}
 
Index: src/wp-admin/css/media.css
===================================================================
--- src/wp-admin/css/media.css	(revision 29615)
+++ src/wp-admin/css/media.css	(working copy)
@@ -513,16 +513,6 @@
 	border: 4px dashed #bbb;
 }
 
-.media-frame.mode-grid .media-toolbar select {
-	margin-top: 1px;
-	font-size: inherit;
-}
-
-.media-frame.mode-grid .attachments-browser .bulk-select {
-	display: inline-block;
-	margin: 0 10px 0 0;
-}
-
 .media-frame.mode-grid .attachments,
 .media-frame.mode-select .attachments {
 	padding: 2px;
@@ -530,8 +520,8 @@
 
 .media-frame.mode-select .attachments-browser.fixed .attachments {
 	position: relative;
-	top: 80px; /* prevent jumping up when the toolbar becomes fixed */
-	padding-bottom: 80px; /* offset for above so the bottom doesn't get cut off */
+	top: 97px; /* prevent jumping up when the toolbar becomes fixed */
+	padding-bottom: 97px; /* offset for above so the bottom doesn't get cut off */
 }
 
 .media-frame.mode-grid .attachment:focus,
@@ -577,54 +567,29 @@
  *
  * This should be OOCSS'd so both use a shared selector.
  */
-.media-frame.mode-grid .attachments-browser .media-toolbar {
-	background: #fff;
-	-webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
-	box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
-	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;
-	box-sizing: border-box;
-	color: #555;
-	display: inline-block;
-	font-size: 13px;
-	margin: 20px 0;
-	padding: 0 20px;
-	position: relative;
-	width: 100%;
+
+.media-frame.mode-grid .media-toolbar {
+	margin: 20px 0 16px;
 	height: auto;
-	border: none;
 }
 
-.media-frame.mode-select .attachments-browser.fixed .media-toolbar {
-	position: fixed;
-	top: 32px;
-	left: auto;
-	right: 20px;
-	margin-top: 0;
+.media-frame.mode-grid .media-toolbar select {
+	margin: 0 10px 0 0;
+	font-size: inherit;
 }
 
-.media-frame.mode-grid input[type="search"] {
-	margin: 1px;
-	padding: 3px 5px;
-	position: absolute;
-	right: 10px;
-	top: 9px;
-	font-size: 16px;
-	font-weight: 300;
-	line-height: 1.5;
-	width: 280px;
+.media-frame.mode-grid .media-toolbar-secondary > .media-button {
+	margin-top: 10px;
+	margin-bottom: 10px;
 }
 
-.media-frame.mode-grid .view-switch {
+.media-frame.mode-grid .attachments-browser .bulk-select {
 	display: inline-block;
-	float: none;
-	vertical-align: middle;
-	padding: 15px 0;
-	margin: 0 20px 0 0;
+	margin: 0 10px 0 0;
 }
 
-.media-frame.mode-grid select {
-	margin: 0 10px 0 0;
+.media-frame.mode-grid .search {
+	margin-top: 0;
 }
 
 .media-frame.mode-grid .spinner {
@@ -635,6 +600,14 @@
 	margin-right: 10px;
 }
 
+.media-frame.mode-select .attachments-browser.fixed .media-toolbar {
+	position: fixed;
+	top: 32px;
+	left: auto;
+	right: 20px;
+	margin-top: 0;
+}
+
 .media-frame.mode-grid .attachments-browser {
 	padding: 0;
 }
@@ -1158,17 +1131,9 @@
  */
 
 @media only screen and (max-width: 1120px) {
-	.media-frame.mode-grid .attachments-browser .media-toolbar-primary,
 	.media-frame.mode-grid .attachments-browser .media-toolbar-secondary {
 		float: none;
 	}
-
-	.media-frame.mode-grid input[type="search"] {
-		margin: 20px 0;
-		position: static;
-		width: 100%;
-		max-width: 280px;
-	}
 }
 
 @media only screen and ( max-width: 782px ) {
Index: src/wp-admin/includes/class-wp-media-list-table.php
===================================================================
--- src/wp-admin/includes/class-wp-media-list-table.php	(revision 29615)
+++ src/wp-admin/includes/class-wp-media-list-table.php	(working copy)
@@ -60,23 +60,24 @@
 			foreach ( $reals as $real )
 				$num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
 
-		$class = ( empty($_GET['post_mime_type']) && !$this->detached && !isset($_GET['status']) ) ? ' class="current"' : '';
-		$type_links['all'] = "<a href='upload.php'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $_total_posts, 'uploaded files' ), number_format_i18n( $_total_posts ) ) . '</a>';
+		$selected = empty( $_GET['attachment-filter'] ) ? ' selected="selected"' : '';
+		$type_links['all'] = "<option value=''$selected>" . sprintf( _nx( 'All (%s)', 'All (%s)', $_total_posts, 'uploaded files' ), number_format_i18n( $_total_posts ) ) . '</option>';
 		foreach ( $post_mime_types as $mime_type => $label ) {
 			$class = '';
 
 			if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) )
 				continue;
 
-			if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) )
-				$class = ' class="current"';
+			$selected = '';
+			if ( !empty( $_GET['attachment-filter'] ) && strpos( $_GET['attachment-filter'], 'post_mime_type:' ) === 0 && wp_match_mime_types( $mime_type, str_replace( 'post_mime_type:', '', $_GET['attachment-filter'] ) ) )
+				$selected = ' selected="selected"';
 			if ( !empty( $num_posts[$mime_type] ) )
-				$type_links[$mime_type] = '<a href="upload.php?post_mime_type=' . urlencode( $mime_type ) . '"' . $class . '>' . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), number_format_i18n( $num_posts[$mime_type] )) . '</a>';
+				$type_links[$mime_type] = '<option value="post_mime_type:' . urlencode( $mime_type ) . '"' . $selected . '>' . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), number_format_i18n( $num_posts[$mime_type] )) . '</option>';
 		}
-		$type_links['detached'] = '<a href="upload.php?detached=1"' . ( $this->detached ? ' class="current"' : '' ) . '>' . sprintf( _nx( 'Unattached <span class="count">(%s)</span>', 'Unattached <span class="count">(%s)</span>', $total_orphans, 'detached files' ), number_format_i18n( $total_orphans ) ) . '</a>';
+		$type_links['detached'] = '<option value="detached"' . ( $this->detached ? ' selected="selected"' : '' ) . '>' . sprintf( _nx( 'Unattached (%s)', 'Unattached (%s)', $total_orphans, 'detached files' ), number_format_i18n( $total_orphans ) ) . '</option>';
 
 		if ( !empty($_num_posts['trash']) )
-			$type_links['trash'] = '<a href="upload.php?status=trash"' . ( (isset($_GET['status']) && $_GET['status'] == 'trash' ) ? ' class="current"' : '') . '>' . sprintf( _nx( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>', $_num_posts['trash'], 'uploaded files' ), number_format_i18n( $_num_posts['trash'] ) ) . '</a>';
+			$type_links['trash'] = '<option value="trash"' . ( (isset($_GET['attachment-filter']) && $_GET['attachment-filter'] == 'trash' ) ? ' selected="selected"' : '') . '>' . sprintf( _nx( 'Trash (%s)', 'Trash (%s)', $_num_posts['trash'], 'uploaded files' ), number_format_i18n( $_num_posts['trash'] ) ) . '</option>';
 
 		return $type_links;
 	}
@@ -91,10 +92,13 @@
 	}
 
 	protected function extra_tablenav( $which ) {
+		if ( 'bar' !== $which ) {
+			return;
+		}
 ?>
-		<div class="alignleft actions">
+		<div class="actions">
 <?php
-		if ( 'top' == $which && !is_singular() && !$this->detached && !$this->is_trash ) {
+		if ( ! is_singular() && ! $this->detached && ! $this->is_trash ) {
 			$this->months_dropdown( 'attachment' );
 
 			/** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */
@@ -131,8 +135,6 @@
 		global $mode;
 
 		parent::pagination( $which );
-
-		$this->view_switcher( $mode );
 	}
 
 	/**
@@ -167,6 +169,38 @@
 <?php
 	}
 
+	/**
+	 * Override parent views so we can use the filter bar display.
+	 */
+	public function views() {
+		global $mode;
+
+		$views = $this->get_views();
+
+		/** This filter is documented in wp-admin/inclues/class-wp-list-table.php */
+		$views = apply_filters( "views_{$this->screen->id}", $views );
+?>
+<div class="wp-filter">
+	<?php $this->view_switcher( $mode ); ?>
+
+	<select class="attachment-filters" name="attachment-filter">
+		<?php
+		if ( ! empty( $views ) ) {
+			foreach ( $views as $class => $view ) {
+				echo "\t$view\n";
+			}
+		}
+		?>
+	</select>
+
+	<?php $this->extra_tablenav( 'bar' ); ?>
+	<div class="media-toolbar-primary search-form">
+		<label for="media-search-input" class="screen-reader-text"><?php esc_html_e( 'Search Media' ); ?></label>
+		<input type="search" placeholder="Search" id="media-search-input" class="search" name="s" value="<?php _admin_search_query(); ?>"></div>
+	</div>
+	<?php
+	}
+
 	public function get_columns() {
 		$posts_columns = array();
 		$posts_columns['cb'] = '<input type="checkbox" />';
Index: src/wp-admin/includes/post.php
===================================================================
--- src/wp-admin/includes/post.php	(revision 29615)
+++ src/wp-admin/includes/post.php	(working copy)
@@ -1032,6 +1032,8 @@
 		$states .= ',private';
 
 	$q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : $states;
+	$q['post_status'] = isset( $q['attachment-filter'] ) && 'trash' == $q['attachment-filter'] ? 'trash' : $states;
+
 	$media_per_page = (int) get_user_option( 'upload_per_page' );
 	if ( empty( $media_per_page ) || $media_per_page < 1 )
 		$media_per_page = 20;
@@ -1051,8 +1053,16 @@
 	if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
 		unset($q['post_mime_type']);
 
-	if ( isset($q['detached']) )
+	foreach( array_keys( $post_mime_types ) as $type ) {
+		if ( isset( $q['attachment-filter'] ) && "post_mime_type:$type" == $q['attachment-filter'] ) {
+			$q['post_mime_type'] = $type;
+			break;
+		}
+	}
+
+	if ( isset( $q['detached'] ) || ( isset( $q['attachment-filter'] ) && 'detached' == $q['attachment-filter'] ) ) {
 		$q['post_parent'] = 0;
+	}
 
 	wp( $q );
 
Index: src/wp-admin/upload.php
===================================================================
--- src/wp-admin/upload.php	(revision 29615)
+++ src/wp-admin/upload.php	(working copy)
@@ -265,11 +265,9 @@
 <div id="message" class="updated"><p><?php echo $message; ?></p></div>
 <?php } ?>
 
-<?php $wp_list_table->views(); ?>
-
 <form id="posts-filter" action="" method="get">
 
-<?php $wp_list_table->search_box( __( 'Search Media' ), 'media' ); ?>
+<?php $wp_list_table->views(); ?>
 
 <?php $wp_list_table->display(); ?>
 
Index: src/wp-includes/js/media-grid.js
===================================================================
--- src/wp-includes/js/media-grid.js	(revision 29615)
+++ src/wp-includes/js/media-grid.js	(working copy)
@@ -179,7 +179,8 @@
 			$browser = this.$('.attachments-browser');
 			$toolbar = $browser.find('.media-toolbar');
 
-			if ( $browser.offset().top < this.$window.scrollTop() + this.$adminBar.height() ) {
+			// Offset doesn't appear to take top margin into account, hence +20
+			if ( ( $browser.offset().top + 20 ) < this.$window.scrollTop() + this.$adminBar.height() ) {
 				$browser.addClass( 'fixed' );
 				$toolbar.css('width', $browser.width() + 'px');
 			} else {
Index: src/wp-includes/js/media-views.js
===================================================================
--- src/wp-includes/js/media-views.js	(revision 29615)
+++ src/wp-includes/js/media-views.js	(working copy)
@@ -3911,7 +3911,7 @@
 	 */
 	media.view.Toolbar = media.View.extend({
 		tagName:   'div',
-		className: 'media-toolbar',
+		className: 'media-toolbar wp-filter',
 
 		initialize: function() {
 			var state = this.controller.state(),
@@ -3923,7 +3923,7 @@
 			// The toolbar is composed of two `PriorityList` views.
 			this.primary   = new media.view.PriorityList();
 			this.secondary = new media.view.PriorityList();
-			this.primary.$el.addClass('media-toolbar-primary');
+			this.primary.$el.addClass('media-toolbar-primary search-form');
 			this.secondary.$el.addClass('media-toolbar-secondary');
 
 			this.views.set([ this.secondary, this.primary ]);
