diff --git a/libfm-qt/CMakeLists.txt b/libfm-qt/CMakeLists.txt
index 84c8049..c0cbc1e 100644
--- a/libfm-qt/CMakeLists.txt
+++ b/libfm-qt/CMakeLists.txt
@@ -63,6 +63,8 @@ set(libfm_SRCS
     appchoosercombobox.cpp
     appmenuview.cpp
     appchooserdialog.cpp
+    filesearchdialog.cpp
+    fm-search.c # might be moved to libfm later
 )
 
 set(libfm_UIS
@@ -73,6 +75,7 @@ set(libfm_UIS
     edit-bookmarks.ui
     exec-file.ui
     app-chooser-dialog.ui
+    filesearch.ui
 )
 
 qt5_wrap_ui(libfm_UIS_H ${libfm_UIS})
diff --git a/libfm-qt/filemenu.cpp b/libfm-qt/filemenu.cpp
index 9dbe7e0..15dcb38 100644
--- a/libfm-qt/filemenu.cpp
+++ b/libfm-qt/filemenu.cpp
@@ -62,6 +62,19 @@ void FileMenu::createMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd)
   confirmDelete_ = true;
   confirmTrash_ = false; // Confirm before moving files into "trash can"
 
+  openAction_ = NULL;
+  openWithMenuAction_ = NULL;
+  openWithAction_ = NULL;
+  separator1_ = NULL;
+  cutAction_ = NULL;
+  copyAction_ = NULL;
+  pasteAction_ = NULL;
+  deleteAction_ = NULL;
+  unTrashAction_ = NULL;
+  renameAction_ = NULL;
+  separator2_ = NULL;
+  propertiesAction_ = NULL;
+
   files_ = fm_file_info_list_ref(files);
   info_ = info ? fm_file_info_ref(info) : NULL;
   cwd_ = cwd ? fm_path_ref(cwd) : NULL;
@@ -346,8 +359,10 @@ void FileMenu::onRenameTriggered() {
 void FileMenu::setUseTrash(bool trash) {
   if(useTrash_ != trash) {
     useTrash_ = trash;
-    deleteAction_->setText(useTrash_ ? tr("&Move to Trash") : tr("&Delete"));
-    deleteAction_->setIcon(useTrash_ ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete"));
+    if(deleteAction_) {
+      deleteAction_->setText(useTrash_ ? tr("&Move to Trash") : tr("&Delete"));
+      deleteAction_->setIcon(useTrash_ ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete"));
+    }
   }
 }
 
diff --git a/libfm-qt/filesearch.ui b/libfm-qt/filesearch.ui
new file mode 100644
index 0000000..f5f6051
--- /dev/null
+++ b/libfm-qt/filesearch.ui
@@ -0,0 +1,449 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SearchDialog</class>
+ <widget class="QDialog" name="SearchDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>512</width>
+    <height>420</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Search Files</string>
+  </property>
+  <property name="windowIcon">
+   <iconset theme="system-search">
+    <normaloff/>
+   </iconset>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab">
+      <attribute name="title">
+       <string>Name/Location</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
+       <item>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>File Name Patterns:</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <widget class="QLineEdit" name="namePatterns">
+            <property name="text">
+             <string>*</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="nameCaseInsensitive">
+            <property name="text">
+             <string>Case insensitive</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="nameRegExp">
+            <property name="text">
+             <string>Use regular expression</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_2">
+         <property name="title">
+          <string>Places to Search:</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_5">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <widget class="QListWidget" name="listView"/>
+            </item>
+            <item>
+             <layout class="QVBoxLayout" name="verticalLayout_4">
+              <item>
+               <widget class="QPushButton" name="addPath">
+                <property name="text">
+                 <string>&amp;Add</string>
+                </property>
+                <property name="icon">
+                 <iconset theme="list-add">
+                  <normaloff/>
+                 </iconset>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QPushButton" name="removePath">
+                <property name="text">
+                 <string>&amp;Remove</string>
+                </property>
+                <property name="icon">
+                 <iconset theme="list-remove">
+                  <normaloff/>
+                 </iconset>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <spacer name="verticalSpacer">
+                <property name="orientation">
+                 <enum>Qt::Vertical</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>20</width>
+                  <height>40</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="recursiveSearch">
+            <property name="text">
+             <string>Search in sub directories</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="searchHidden">
+            <property name="text">
+             <string>Search for hidden files</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_2">
+      <attribute name="title">
+       <string>File Type</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_7">
+       <item>
+        <widget class="QGroupBox" name="groupBox_3">
+         <property name="title">
+          <string>Only search for files of following types:</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_6">
+          <item>
+           <widget class="QCheckBox" name="searchTextFiles">
+            <property name="text">
+             <string>Text files</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="searchImages">
+            <property name="text">
+             <string>Image files</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="searchAudio">
+            <property name="text">
+             <string>Audio files</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="searchVideo">
+            <property name="text">
+             <string>Video files</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="searchDocuments">
+            <property name="text">
+             <string>Documents</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="searchFolders">
+            <property name="text">
+             <string>Folders</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_3">
+      <attribute name="title">
+       <string>Content</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_9">
+       <item>
+        <widget class="QGroupBox" name="groupBox_4">
+         <property name="title">
+          <string>File contains:</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_8">
+          <item>
+           <widget class="QLineEdit" name="contentPattern"/>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="contentCaseInsensitive">
+            <property name="text">
+             <string>Case insensiti&amp;ve</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="contentRegExp">
+            <property name="text">
+             <string>&amp;Use regular expression</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_3">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>186</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_4">
+      <attribute name="title">
+       <string>Properties</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_10">
+       <item>
+        <widget class="QGroupBox" name="groupBox_5">
+         <property name="title">
+          <string>File Size:</string>
+         </property>
+         <layout class="QFormLayout" name="formLayout">
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="largerThan">
+            <property name="text">
+             <string>Larger than:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <item>
+             <widget class="QSpinBox" name="minSize"/>
+            </item>
+            <item>
+             <widget class="QComboBox" name="minSizeUnit">
+              <property name="currentIndex">
+               <number>2</number>
+              </property>
+              <item>
+               <property name="text">
+                <string>Bytes</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>KiB</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>MiB</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>GiB</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="1" column="0">
+           <widget class="QCheckBox" name="smallerThan">
+            <property name="text">
+             <string>Smaller than:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <layout class="QHBoxLayout" name="horizontalLayout_3">
+            <item>
+             <widget class="QSpinBox" name="maxSize"/>
+            </item>
+            <item>
+             <widget class="QComboBox" name="maxSizeUnit">
+              <property name="currentIndex">
+               <number>2</number>
+              </property>
+              <item>
+               <property name="text">
+                <string>Bytes</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>KiB</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>MiB</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>GiB</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_6">
+         <property name="title">
+          <string>Last Modified Time:</string>
+         </property>
+         <layout class="QFormLayout" name="formLayout_2">
+          <item row="0" column="0">
+           <widget class="QCheckBox" name="earlierThan">
+            <property name="text">
+             <string>Earlier than:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QCheckBox" name="laterThan">
+            <property name="text">
+             <string>Later than:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QDateEdit" name="maxTime">
+            <property name="calendarPopup">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QDateEdit" name="minTime">
+            <property name="calendarPopup">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>SearchDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>SearchDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/libfm-qt/filesearchdialog.cpp b/libfm-qt/filesearchdialog.cpp
new file mode 100644
index 0000000..eeaeaa3
--- /dev/null
+++ b/libfm-qt/filesearchdialog.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015  Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "filesearchdialog.h"
+#include <QMessageBox>
+#include "fm-search.h"
+#include "ui_filesearch.h"
+#include <limits>
+#include <QFileDialog>
+
+namespace Fm {
+
+FileSearchDialog::FileSearchDialog(QStringList paths, QWidget* parent, Qt::WindowFlags f):
+  QDialog(parent, f),
+  ui(new Ui::SearchDialog()) {
+  ui->setupUi(this);
+  ui->minSize->setMaximum(std::numeric_limits<int>().max());
+  ui->maxSize->setMaximum(std::numeric_limits<int>().max());
+  Q_FOREACH(const QString& path, paths) {
+    ui->listView->addItem(path);
+  }
+
+  ui->maxTime->setDate(QDate::currentDate());
+  ui->minTime->setDate(QDate::currentDate());
+
+  connect(ui->addPath, &QPushButton::clicked, this, &FileSearchDialog::onAddPath);
+  connect(ui->removePath, &QPushButton::clicked, this, &FileSearchDialog::onRemovePath);
+}
+
+FileSearchDialog::~FileSearchDialog() {
+  delete ui;
+}
+
+void FileSearchDialog::accept() {
+  // build the search:/// uri
+  int n = ui->listView->count();
+  if(n > 0) {
+    FmSearch* search = fm_search_new();
+    int i;
+    for(i = 0; i < n; ++i) { // add directories
+      QListWidgetItem* item = ui->listView->item(i);
+      fm_search_add_dir(search, item->text().toLocal8Bit().constData());
+    }
+
+    fm_search_set_recursive(search, ui->recursiveSearch->isChecked());
+    fm_search_set_show_hidden(search, ui->searchHidden->isChecked());
+    fm_search_set_name_patterns(search, ui->namePatterns->text().toUtf8().constData());
+    fm_search_set_name_ci(search, ui->nameCaseInsensitive->isChecked());
+    fm_search_set_name_regex(search, ui->nameRegExp->isChecked());
+
+    fm_search_set_content_pattern(search, ui->contentPattern->text().toUtf8().constData());
+    fm_search_set_content_ci(search, ui->contentCaseInsensitive->isChecked());
+    fm_search_set_content_regex(search, ui->contentRegExp->isChecked());
+
+    // search for the files of specific mime-types
+    if(ui->searchTextFiles->isChecked())
+      fm_search_add_mime_type(search, "text/plain");
+    if(ui->searchImages->isChecked())
+      fm_search_add_mime_type(search, "image/*");
+    if(ui->searchAudio->isChecked())
+      fm_search_add_mime_type(search, "audio/*");
+    if(ui->searchVideo->isChecked())
+      fm_search_add_mime_type(search, "video/*");
+    if(ui->searchFolders->isChecked())
+      fm_search_add_mime_type(search, "inode/directory");
+    if(ui->searchDocuments->isChecked()) {
+      const char* doc_types[] = {
+        "application/pdf",
+        /* "text/html;" */
+        "application/vnd.oasis.opendocument.*",
+        "application/vnd.openxmlformats-officedocument.*",
+        "application/msword;application/vnd.ms-word",
+        "application/msexcel;application/vnd.ms-excel"
+      };
+      for(i = 0; i < sizeof(doc_types)/sizeof(char*); ++i)
+        fm_search_add_mime_type(search, doc_types[i]);
+    }
+
+    // search based on file size
+    const unsigned int unit_bytes[] = {1, (1024), (1024*1024), (1024*1024*1024)};
+    if(ui->largerThan->isChecked()) {
+      guint64 size = ui->minSize->value() * unit_bytes[ui->minSizeUnit->currentIndex()];
+      fm_search_set_min_size(search, size);
+    }
+
+    if(ui->smallerThan->isChecked()) {
+      guint64 size = ui->maxSize->value() * unit_bytes[ui->maxSizeUnit->currentIndex()];
+      fm_search_set_min_size(search, size);
+    }
+
+    // search based on file mtime (we only support date in YYYY-MM-DD format)
+    if(ui->earlierThan->isChecked()) {
+      fm_search_set_max_mtime(search, ui->maxTime->date().toString(QStringLiteral("yyyy-MM-dd")).toUtf8().constData());
+    }
+    if(ui->laterThan->isChecked()) {
+      fm_search_set_min_mtime(search, ui->minTime->date().toString(QStringLiteral("yyyy-MM-dd")).toUtf8().constData());
+    }
+
+    searchUri_.take(fm_search_dup_path(search));
+
+    fm_search_free(search);
+  }
+  else {
+    QMessageBox::critical(this, tr("Error"), tr("You should add at least add one directory to search."));
+    return;
+  }
+  QDialog::accept();
+}
+
+void FileSearchDialog::onAddPath() {
+  QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder"));
+  if(dir.isEmpty())
+    return;
+  // avoid adding duplicated items
+  if(ui->listView->findItems(dir, Qt::MatchFixedString|Qt::MatchCaseSensitive).isEmpty()) {
+    ui->listView->addItem(dir);
+  }
+}
+
+void FileSearchDialog::onRemovePath() {
+  // remove selected items
+  Q_FOREACH(QListWidgetItem* item, ui->listView->selectedItems()) {
+    delete item;
+  }
+}
+
+}
diff --git a/libfm-qt/filesearchdialog.h b/libfm-qt/filesearchdialog.h
new file mode 100644
index 0000000..dc6dc08
--- /dev/null
+++ b/libfm-qt/filesearchdialog.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015  Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#ifndef FM_FILESEARCHDIALOG_H
+#define FM_FILESEARCHDIALOG_H
+
+#include "libfmqtglobals.h"
+#include <QDialog>
+#include "path.h"
+
+namespace Ui {
+  class SearchDialog;
+}
+
+namespace Fm {
+
+class LIBFM_QT_API FileSearchDialog : public QDialog
+{
+public:
+  FileSearchDialog(QStringList paths = QStringList(), QWidget * parent = 0, Qt::WindowFlags f = 0);
+  ~FileSearchDialog();
+
+  Path searchUri() const {
+    return searchUri_;
+  }
+
+  virtual void accept();
+
+private Q_SLOTS:
+  void onAddPath();
+  void onRemovePath();
+
+private:
+  Ui::SearchDialog* ui;
+  Path searchUri_;
+};
+
+}
+
+#endif // FM_FILESEARCHDIALOG_H
diff --git a/libfm-qt/fm-search.c b/libfm-qt/fm-search.c
new file mode 100644
index 0000000..b8e26ca
--- /dev/null
+++ b/libfm-qt/fm-search.c
@@ -0,0 +1,317 @@
+/*
+ * fm-search-uri.c
+ * 
+ * Copyright 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
+ * Copyright 2012-2014 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "fm-search.h"
+#include <string.h>
+
+struct _FmSearch
+{
+    gboolean recursive;
+    gboolean show_hidden;
+    char* name_patterns;
+    gboolean name_ci;
+    gboolean name_regex;
+    char* content_pattern;
+    gboolean content_ci;
+    gboolean content_regex;
+    GList* mime_types;
+    GList* search_path_list;
+    guint64 max_size;
+    guint64 min_size;
+    char* max_mtime;
+    char* min_mtime;
+};
+
+FmSearch* fm_search_new (void)
+{
+    FmSearch* search = (FmSearch*)g_slice_new0(FmSearch);
+    return search;
+}
+
+void fm_search_free(FmSearch* search)
+{
+    g_list_free_full(search->mime_types, (GDestroyNotify)g_free);
+    g_list_free_full(search->search_path_list, (GDestroyNotify)g_free);
+    g_free(search->name_patterns);
+    g_free(search->content_pattern);
+    g_free(search->max_mtime);
+    g_free(search->min_mtime);
+    g_slice_free(FmSearch, search);
+}
+
+gboolean fm_search_get_recursive(FmSearch* search)
+{
+    return search->recursive;
+}
+
+void fm_search_set_recursive(FmSearch* search, gboolean recursive)
+{
+    search->recursive = recursive;
+}
+
+gboolean fm_search_get_show_hidden(FmSearch* search)
+{
+    return search->show_hidden;
+}
+
+void fm_search_set_show_hidden(FmSearch* search, gboolean show_hidden)
+{
+    search->show_hidden = show_hidden;
+}
+
+const char* fm_search_get_name_patterns(FmSearch* search)
+{
+    return search->name_patterns;
+}
+
+void fm_search_set_name_patterns(FmSearch* search, const char* name_patterns)
+{
+    g_free(search->name_patterns);
+    search->name_patterns = g_strdup(name_patterns);
+}
+
+gboolean fm_search_get_name_ci(FmSearch* search)
+{
+    return search->name_ci;
+}
+
+void fm_search_set_name_ci(FmSearch* search, gboolean name_ci)
+{
+    search->name_ci = name_ci;
+}
+
+gboolean fm_search_get_name_regex(FmSearch* search)
+{
+    return search->name_regex;
+}
+
+void fm_search_set_name_regex(FmSearch* search, gboolean name_regex)
+{
+    search->name_regex = name_regex;
+}
+
+const char* fm_search_get_content_pattern(FmSearch* search)
+{
+    return search->content_pattern;
+}
+
+void fm_search_set_content_pattern(FmSearch* search, const char* content_pattern)
+{
+    g_free(search->content_pattern);
+    search->content_pattern = g_strdup(content_pattern);
+}
+
+gboolean fm_search_get_content_ci(FmSearch* search)
+{
+    return search->content_ci;
+}
+
+void fm_search_set_content_ci(FmSearch* search, gboolean content_ci)
+{
+    search->content_ci = content_ci;
+}
+
+gboolean fm_search_get_content_regex(FmSearch* search)
+{
+    return search->content_regex;
+}
+
+void fm_search_set_content_regex(FmSearch* search, gboolean content_regex)
+{
+    search->content_regex = content_regex;
+}
+
+void fm_search_add_dir(FmSearch* search, const char* dir)
+{
+    GList* l = g_list_find_custom(search->search_path_list, dir, (GCompareFunc)strcmp);
+    if(!l)
+        search->search_path_list = g_list_prepend(search->search_path_list, g_strdup(dir));
+}
+
+void fm_search_remove_dir(FmSearch* search, const char* dir)
+{
+    GList* l = g_list_find_custom(search->search_path_list, dir, (GCompareFunc)strcmp);
+    if(G_LIKELY(l))
+    {
+        g_free(l->data);
+        search->search_path_list = g_list_delete_link(search->search_path_list, l);
+    }
+}
+
+GList* fm_search_get_dirs(FmSearch* search)
+{
+    return search->search_path_list;
+}
+
+void fm_search_add_mime_type(FmSearch* search, const char* mime_type)
+{
+    GList* l = g_list_find_custom(search->mime_types, mime_type, (GCompareFunc)strcmp);
+    if(!l)
+        search->mime_types = g_list_prepend(search->mime_types, g_strdup(mime_type));
+}
+
+void fm_search_remove_mime_type(FmSearch* search, const char* mime_type)
+{
+    GList* l = g_list_find_custom(search->mime_types, mime_type, (GCompareFunc)strcmp);
+    if(G_LIKELY(l))
+    {
+        g_free(l->data);
+        search->mime_types = g_list_delete_link(search->mime_types, l);
+    }
+}
+
+GList* fm_search_get_mime_types(FmSearch* search)
+{
+    return search->mime_types;
+}
+
+guint64 fm_search_get_max_size(FmSearch* search)
+{
+    return search->max_size;
+}
+
+void fm_search_set_max_size(FmSearch* search, guint64 size)
+{
+    search->max_size = size;
+}
+
+guint64 fm_search_get_min_size(FmSearch* search)
+{
+    return search->min_size;
+}
+
+void fm_search_set_min_size(FmSearch* search, guint64 size)
+{
+    search->min_size = size;
+}
+
+/* format of mtime: YYYY-MM-DD */
+const char* fm_search_get_max_mtime(FmSearch* search)
+{
+    return search->max_mtime;
+}
+
+void fm_search_set_max_mtime(FmSearch* search, const char* mtime)
+{
+    g_free(search->max_mtime);
+    search->max_mtime = g_strdup(mtime);
+}
+
+/* format of mtime: YYYY-MM-DD */
+const char* fm_search_get_min_mtime(FmSearch* search)
+{
+    return search->min_mtime;
+}
+
+void fm_search_set_min_mtime(FmSearch* search, const char* mtime)
+{
+    g_free(search->min_mtime);
+    search->min_mtime = g_strdup(mtime);
+}
+
+/* really build the path */
+FmPath* fm_search_dup_path(FmSearch* search)
+{
+    FmPath* search_path = NULL;
+    GString* search_str = g_string_sized_new(1024);
+    /* build the search:// URI to perform the search */
+    g_string_append(search_str, "search://");
+
+    if(search->search_path_list) /* we need to have at least one dir path */
+    {
+        char *escaped;
+        /* add paths */
+        GList* l;
+        for(l = search->search_path_list; ; )
+        {
+            char *path_str = (char*)l->data;
+            /* escape possible '?' and ',' */
+            escaped = g_uri_escape_string(path_str, "!$&'()*+:;=/@", TRUE);
+            g_string_append(search_str, escaped);
+            g_free(escaped);
+
+            l = l->next;
+            if(!l) /* no more items */
+                break;
+            g_string_append_c(search_str, ','); /* separator for paths */
+        }
+
+        g_string_append_c(search_str, '?');
+        g_string_append_printf(search_str, "recursive=%c", search->recursive ? '1' : '0');
+        g_string_append_printf(search_str, "&show_hidden=%c", search->show_hidden ? '1' : '0');
+        if(search->name_patterns && *search->name_patterns)
+        {
+            /* escape ampersands in pattern */
+            escaped = g_uri_escape_string(search->name_patterns, ":/?#[]@!$'()*+,;", TRUE);
+            if(search->name_regex)
+                g_string_append_printf(search_str, "&name_regex=%s", escaped);
+            else
+                g_string_append_printf(search_str, "&name=%s", escaped);
+            if(search->name_ci)
+                g_string_append_printf(search_str, "&name_ci=%c", search->name_ci ? '1' : '0');
+            g_free(escaped);
+        }
+
+        if(search->content_pattern && *search->content_pattern)
+        {
+            /* escape ampersands in pattern */
+            escaped = g_uri_escape_string(search->content_pattern, ":/?#[]@!$'()*+,;^<>{}", TRUE);
+            if(search->content_regex)
+                g_string_append_printf(search_str, "&content_regex=%s", escaped);
+            else
+                g_string_append_printf(search_str, "&content=%s", escaped);
+            g_free(escaped);
+            if(search->content_ci)
+                g_string_append_printf(search_str, "&content_ci=%c", search->content_ci ? '1' : '0');
+        }
+
+        /* search for the files of specific mime-types */
+        if(search->mime_types)
+        {
+            GList* l;
+            g_string_append(search_str, "&mime_types=");
+            for(l = search->mime_types; l; l=l->next)
+            {
+                const char* mime_type = (const char*)l->data;
+                g_string_append(search_str, mime_type);
+                if(l->next)
+                    g_string_append_c(search_str, ';');
+            }
+        }
+
+        if(search->min_size)
+            g_string_append_printf(search_str, "&min_size=%llu", search->min_size);
+
+        if(search->max_size)
+            g_string_append_printf(search_str, "&max_size=%llu", search->max_size);
+
+        if(search->min_mtime)
+            g_string_append_printf(search_str, "&min_mtime=%s", search->min_mtime);
+
+        if(search->max_mtime)
+            g_string_append_printf(search_str, "&max_mtime=%s", search->max_mtime);
+
+        search_path = fm_path_new_for_uri(search_str->str);
+        g_string_free(search_str, TRUE);
+    }
+    return search_path;
+}
diff --git a/libfm-qt/fm-search.h b/libfm-qt/fm-search.h
new file mode 100644
index 0000000..1ae397e
--- /dev/null
+++ b/libfm-qt/fm-search.h
@@ -0,0 +1,88 @@
+/*
+ * fm-search-uri.h
+ * 
+ * Copyright 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/* FmSearch implements a tool used to generate a search:// URI used by libfm to search for files.
+ * This API might become part of libfm in the future.
+ */
+
+#ifndef _FM_SEARCH_H_
+#define _FM_SEARCH_H_
+
+#include <libfm/fm.h>
+
+G_BEGIN_DECLS
+
+typedef struct _FmSearch         FmSearch;
+
+FmSearch* fm_search_new(void);
+void fm_search_free(FmSearch* search);
+
+FmPath* fm_search_dup_path(FmSearch* search);
+
+gboolean fm_search_get_recursive(FmSearch* search);
+void fm_search_set_recursive(FmSearch* search, gboolean recursive);
+
+gboolean fm_search_get_show_hidden(FmSearch* search);
+void fm_search_set_show_hidden(FmSearch* search, gboolean show_hidden);
+
+const char* fm_search_get_name_patterns(FmSearch* search);
+void fm_search_set_name_patterns(FmSearch* search, const char* name_patterns);
+
+gboolean fm_search_get_name_ci(FmSearch* search);
+void fm_search_set_name_ci(FmSearch* search, gboolean name_ci);
+
+gboolean fm_search_get_name_regex(FmSearch* search);
+void fm_search_set_name_regex(FmSearch* search, gboolean name_regex);
+
+const char* fm_search_get_content_pattern(FmSearch* search);
+void fm_search_set_content_pattern(FmSearch* search, const char* content_pattern);
+
+gboolean fm_search_get_content_ci(FmSearch* search);
+void fm_search_set_content_ci(FmSearch* search, gboolean content_ci);
+
+gboolean fm_search_get_content_regex(FmSearch* search);
+void fm_search_set_content_regex(FmSearch* search, gboolean content_regex);
+
+void fm_search_add_dir(FmSearch* search, const char* dir);
+void fm_search_remove_dir(FmSearch* search, const char* dir);
+GList* fm_search_get_dirs(FmSearch* search);
+
+void fm_search_add_mime_type(FmSearch* search, const char* mime_type);
+void fm_search_remove_mime_type(FmSearch* search, const char* mime_type);
+GList* fm_search_get_mime_types(FmSearch* search);
+
+guint64 fm_search_get_max_size(FmSearch* search);
+void fm_search_set_max_size(FmSearch* search, guint64 size);
+
+guint64 fm_search_get_min_size(FmSearch* search);
+void fm_search_set_min_size(FmSearch* search, guint64 size);
+
+/* format of mtime: YYYY-MM-DD */
+const char* fm_search_get_max_mtime(FmSearch* search);
+void fm_search_set_max_mtime(FmSearch* search, const char* mtime);
+
+/* format of mtime: YYYY-MM-DD */
+const char* fm_search_get_min_mtime(FmSearch* search);
+void fm_search_set_min_mtime(FmSearch* search, const char* mtime);
+
+G_END_DECLS
+
+#endif /* _FM_SEARCH_H_ */
diff --git a/libfm-qt/path.h b/libfm-qt/path.h
index de6b53c..06238f0 100644
--- a/libfm-qt/path.h
+++ b/libfm-qt/path.h
@@ -188,6 +188,12 @@ public:
     return fm_path_hash(data_);
   }
 
+  void take(FmPath* path) { // take the ownership of the "path"
+    if(data_)
+      fm_path_unref(data_);
+    data_ = path;
+  }
+
   Path& operator = (const Path& other) {
     if(data_)
       fm_path_unref(data_);
diff --git a/libfm-qt/placesview.cpp b/libfm-qt/placesview.cpp
index fc2f99a..9ea93a9 100644
--- a/libfm-qt/placesview.cpp
+++ b/libfm-qt/placesview.cpp
@@ -322,6 +322,8 @@ void PlacesView::onEjectVolume() {
 void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
   QModelIndex index = indexAt(event->pos());
   if(index.isValid() && index.parent().isValid()) {
+    if(index.column() != 0) // the real item is at column 0
+      index = index.sibling(index.row(), 0);
     QMenu* menu = new QMenu(this);
     QAction* action;
     PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(index));
diff --git a/libfm-qt/proxyfoldermodel.cpp b/libfm-qt/proxyfoldermodel.cpp
index 963e870..ce815c6 100644
--- a/libfm-qt/proxyfoldermodel.cpp
+++ b/libfm-qt/proxyfoldermodel.cpp
@@ -118,6 +118,12 @@ bool ProxyFolderModel::lessThan(const QModelIndex& left, const QModelIndex& righ
     FmFileInfo* leftInfo = srcModel->fileInfoFromIndex(left);
     FmFileInfo* rightInfo = srcModel->fileInfoFromIndex(right);
 
+    if(Q_UNLIKELY(!leftInfo || !rightInfo)) {
+      // In theory, this should not happen, but it's safer to add the null check.
+      // This is reported in https://github.com/lxde/pcmanfm-qt/issues/205
+      return false;
+    }
+
     if(folderFirst_) {
       bool leftIsFolder = (bool)fm_file_info_is_dir(leftInfo);
       bool rightIsFolder = (bool)fm_file_info_is_dir(rightInfo);
diff --git a/pcmanfm-qt.kdev4 b/pcmanfm-qt.kdev4
deleted file mode 100644
index 4588e29..0000000
--- a/pcmanfm-qt.kdev4
+++ /dev/null
@@ -1,4 +0,0 @@
-[Project]
-Manager=KDevCMakeManager
-Name=pcmanfm-qt
-VersionControl=
diff --git a/pcmanfm/application.cpp b/pcmanfm/application.cpp
index ffedfcd..0595b9d 100644
--- a/pcmanfm/application.cpp
+++ b/pcmanfm/application.cpp
@@ -42,6 +42,7 @@
 #include "mountoperation.h"
 #include "autorundialog.h"
 #include "launcher.h"
+#include "filesearchdialog.h"
 
 #include <QScreen>
 #include <QWindow>
@@ -113,8 +114,8 @@ Application::~Application() {
     g_object_unref(volumeMonitor_);
   }
 
-  if(enableDesktopManager_)
-    removeNativeEventFilter(this);
+  // if(enableDesktopManager_)
+  //   removeNativeEventFilter(this);
 }
 
 bool Application::parseCommandLineArgs() {
@@ -311,7 +312,7 @@ void Application::desktopManager(bool enabled) {
   QDesktopWidget* desktopWidget = desktop();
   if(enabled) {
     if(!enableDesktopManager_) {
-      installNativeEventFilter(this);
+      // installNativeEventFilter(this);
       Q_FOREACH(QScreen* screen, screens()) {
         connect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged);
         connect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed);
@@ -352,7 +353,7 @@ void Application::desktopManager(bool enabled) {
         disconnect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed);
       }
       disconnect(this, &QApplication::screenAdded, this, &Application::onScreenAdded);
-      removeNativeEventFilter(this);
+      // removeNativeEventFilter(this);
     }
   }
   enableDesktopManager_ = enabled;
@@ -369,9 +370,22 @@ void Application::desktopPrefrences(QString page) {
   desktopPreferencesDialog_.data()->activateWindow();
 }
 
+void Application::onFindFileAccepted() {
+  Fm::FileSearchDialog* dlg = static_cast<Fm::FileSearchDialog*>(sender());
+  Fm::Path uri = dlg->searchUri();
+  // FIXME: we should be able to open it in an existing window
+  FmPathList* paths = fm_path_list_new();
+  fm_path_list_push_tail(paths, uri.data());
+  Launcher(NULL).launchPaths(NULL, paths);
+  fm_path_list_unref(paths);
+}
+
 void Application::findFiles(QStringList paths) {
-  // TODO: add a file searching utility here.
-  qDebug("findFiles");
+  // launch file searching utility.
+  Fm::FileSearchDialog* dlg = new Fm::FileSearchDialog(paths);
+  connect(dlg, &QDialog::accepted, this, &Application::onFindFileAccepted);
+  dlg->setAttribute(Qt::WA_DeleteOnClose);
+  dlg->show();
 }
 
 void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) {
@@ -635,17 +649,18 @@ void Application::onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Applic
     pThis->autoMountVolume(volume, true);
 }
 
+#if 0
 bool Application::nativeEventFilter(const QByteArray & eventType, void * message, long * result) {
   if(eventType == "xcb_generic_event_t") { // XCB event
     // filter all native X11 events (xcb)
     xcb_generic_event_t* generic_event = reinterpret_cast<xcb_generic_event_t*>(message);
     // qDebug("XCB event: %d", generic_event->response_type & ~0x80);
     Q_FOREACH(DesktopWindow * window, desktopWindows_) {
-      window->xcbEvent(generic_event);
     }
   }
   return false;
 }
+#endif
 
 void Application::onScreenAdded(QScreen* newScreen) {
   if(enableDesktopManager_) {
diff --git a/pcmanfm/application.h b/pcmanfm/application.h
index c0dc727..ccc80e4 100644
--- a/pcmanfm/application.h
+++ b/pcmanfm/application.h
@@ -25,7 +25,6 @@
 #include "settings.h"
 #include "libfmqt.h"
 #include "editbookmarksdialog.h"
-#include <QAbstractNativeEventFilter>
 #include <QVector>
 #include <QPointer>
 #include <QProxyStyle>
@@ -49,7 +48,7 @@ public:
   virtual int styleHint(StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0) const;
 };
 
-class Application : public QApplication, public QAbstractNativeEventFilter {
+class Application : public QApplication {
   Q_OBJECT
   Q_PROPERTY(bool desktopManagerEnabled READ desktopManagerEnabled)
 
@@ -75,7 +74,7 @@ public:
   void desktopPrefrences(QString page);
   void editBookmarks();
   void desktopManager(bool enabled);
-  void findFiles(QStringList paths);
+  void findFiles(QStringList paths = QStringList());
 
   bool desktopManagerEnabled() {
     return enableDesktopManager_;
@@ -91,8 +90,6 @@ public:
     return profileName_;
   }
 
-  virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
-
 protected Q_SLOTS:
   void onAboutToQuit();
   void onSigtermNotified();
@@ -108,6 +105,8 @@ protected Q_SLOTS:
   void onScreenAdded(QScreen* newScreen);
   void reloadDesktopsAsNeeded();
 
+  void onFindFileAccepted();
+
 protected:
   virtual bool eventFilter(QObject* watched, QEvent* event);
   bool parseCommandLineArgs();
diff --git a/pcmanfm/desktop-preferences.ui b/pcmanfm/desktop-preferences.ui
index 7182bd5..258cd95 100644
--- a/pcmanfm/desktop-preferences.ui
+++ b/pcmanfm/desktop-preferences.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>473</width>
-    <height>428</height>
+    <width>501</width>
+    <height>376</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -200,6 +200,19 @@
          </layout>
         </widget>
        </item>
+       <item>
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>10</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
       </layout>
      </widget>
      <widget class="QWidget" name="advancedPage">
diff --git a/pcmanfm/desktopwindow.cpp b/pcmanfm/desktopwindow.cpp
index 8c3260e..effb80d 100644
--- a/pcmanfm/desktopwindow.cpp
+++ b/pcmanfm/desktopwindow.cpp
@@ -389,49 +389,6 @@ void DesktopWindow::prepareFolderMenu(Fm::FolderMenu* menu) {
   connect(action, &QAction::triggered, this, &DesktopWindow::onDesktopPreferences);
 }
 
-void DesktopWindow::xcbEvent(xcb_generic_event_t* generic_event) {
-  int event_type = generic_event->response_type & ~0x80;
-  if(showWmMenu_) {
-    // If we want to show the desktop menus provided by the window manager instead of ours,
-    // we have to forward the mouse events we received to the root window.
-    switch(event_type) {
-      case XCB_BUTTON_PRESS: {
-        xcb_button_press_event_t* event = reinterpret_cast<xcb_button_press_event_t*>(generic_event);
-        if(event->event == effectiveWinId()) {
-          // check if the user click on blank area
-          QModelIndex index = listView_->indexAt(QPoint(event->event_x, event->event_y));
-          if(!index.isValid()) {
-            xcb_ungrab_pointer(QX11Info::connection(), event->time);
-            // forward the event to the root window
-            xcb_button_press_event_t event2 = *event;
-            WId root = QX11Info::appRootWindow(QX11Info::appScreen());
-            event2.event = root;
-            xcb_send_event(QX11Info::connection(), 0, root, XCB_EVENT_MASK_BUTTON_PRESS, (char*)&event2);
-          }
-        }
-        break;
-      }
-      case XCB_BUTTON_RELEASE: {
-        xcb_button_release_event_t* event = reinterpret_cast<xcb_button_release_event_t*>(generic_event);
-        if(event->event == effectiveWinId()) {
-          // check if the user click on blank area
-          QModelIndex index = listView_->indexAt(QPoint(event->event_x, event->event_y));
-          if(!index.isValid()) {
-            // forward the event to the root window
-            xcb_button_release_event_t event2 = *event;
-            WId root = QX11Info::appRootWindow(QX11Info::appScreen());
-            event2.event = root;
-            xcb_send_event(QX11Info::connection(), 0, root, XCB_EVENT_MASK_BUTTON_RELEASE, (char*)&event2);
-          }
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  }
-}
-
 void DesktopWindow::onDesktopPreferences() {
   static_cast<Application* >(qApp)->desktopPrefrences(QString());
 }
@@ -675,6 +632,69 @@ void DesktopWindow::onFilePropertiesActivated() {
   }
 }
 
+static void forwardMouseEventToRoot(QMouseEvent* event) {
+  xcb_ungrab_pointer(QX11Info::connection(), event->timestamp());
+  // forward the event to the root window
+  xcb_button_press_event_t xcb_event;
+  uint32_t mask = 0;
+  xcb_event.state = 0;
+  switch(event->type()) {
+  case QEvent::MouseButtonPress:
+    xcb_event.response_type = XCB_BUTTON_PRESS;
+    mask = XCB_EVENT_MASK_BUTTON_PRESS;
+    break;
+  case QEvent::MouseButtonRelease:
+      xcb_event.response_type = XCB_BUTTON_RELEASE;
+      mask = XCB_EVENT_MASK_BUTTON_RELEASE;
+    break;
+  default:
+    return;
+  }
+
+  // convert Qt button to XCB button
+  switch(event->button()) {
+  case Qt::LeftButton:
+    xcb_event.detail = 1;
+    xcb_event.state |= XCB_BUTTON_MASK_1;
+    break;
+  case Qt::MiddleButton:
+    xcb_event.detail = 2;
+    xcb_event.state |= XCB_BUTTON_MASK_2;
+    break;
+  case Qt::RightButton:
+    xcb_event.detail = 3;
+    xcb_event.state |= XCB_BUTTON_MASK_3;
+    break;
+  default:
+    xcb_event.detail = 0;
+  }
+
+  // convert Qt modifiers to XCB states
+  if(event->modifiers() & Qt::ShiftModifier)
+    xcb_event.state |= XCB_MOD_MASK_SHIFT;
+  if(event->modifiers() & Qt::ControlModifier)
+    xcb_event.state |= XCB_MOD_MASK_SHIFT;
+  if(event->modifiers() & Qt::AltModifier)
+    xcb_event.state |= XCB_MOD_MASK_1;
+
+  xcb_event.sequence = 0;
+  xcb_event.time = event->timestamp();
+
+  WId root = QX11Info::appRootWindow(QX11Info::appScreen());
+  xcb_event.event = root;
+  xcb_event.root = root;
+  xcb_event.child = 0;
+
+  xcb_event.root_x = event->globalX();
+  xcb_event.root_y = event->globalY();
+  xcb_event.event_x = event->x();
+  xcb_event.event_y = event->y();
+  xcb_event.same_screen = 1;
+
+  xcb_send_event(QX11Info::connection(), 0, root, mask, (char*)&xcb_event);
+  xcb_flush(QX11Info::connection());
+}
+
 bool DesktopWindow::event(QEvent* event)
 {
   switch(event->type()) {
@@ -721,6 +741,25 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
       break;
     }
   }
+  else if(watched == listView_->viewport()) {
+    switch(event->type()) {
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+        if(showWmMenu_) {
+          QMouseEvent* e = static_cast<QMouseEvent*>(event);
+          // If we want to show the desktop menus provided by the window manager instead of ours,
+          // we have to forward the mouse events we received to the root window.
+          // check if the user click on blank area
+          QModelIndex index = listView_->indexAt(e->pos());
+          if(!index.isValid() && e->button() != Qt::LeftButton) {
+            forwardMouseEventToRoot(e);
+          }
+      }
+      break;
+    default:
+      break;
+    }
+  }
   return false;
 }
 
diff --git a/pcmanfm/desktopwindow.h b/pcmanfm/desktopwindow.h
index f1ad12b..c28e322 100644
--- a/pcmanfm/desktopwindow.h
+++ b/pcmanfm/desktopwindow.h
@@ -66,8 +66,6 @@ public:
   void updateWallpaper();
   void updateFromSettings(Settings& settings);
 
-  void xcbEvent(xcb_generic_event_t* generic_event);
-
   void queueRelayout(int delay = 0);
 
   int screenNum() const {
diff --git a/pcmanfm/file-search.ui b/pcmanfm/file-search.ui
index a698eae..20dc03c 100644
--- a/pcmanfm/file-search.ui
+++ b/pcmanfm/file-search.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>431</width>
-    <height>359</height>
+    <height>416</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -76,7 +76,9 @@
                  <string>Add</string>
                 </property>
                 <property name="icon">
-                 <iconset theme="list-add"/>
+                 <iconset theme="list-add">
+                  <normaloff/>
+                 </iconset>
                 </property>
                </widget>
               </item>
@@ -86,7 +88,9 @@
                  <string>Remove</string>
                 </property>
                 <property name="icon">
-                 <iconset theme="list-remove"/>
+                 <iconset theme="list-remove">
+                  <normaloff/>
+                 </iconset>
                 </property>
                </widget>
               </item>
@@ -125,9 +129,6 @@
         </widget>
        </item>
       </layout>
-      <zorder>buttonBox</zorder>
-      <zorder>groupBox</zorder>
-      <zorder>groupBox_2</zorder>
      </widget>
      <widget class="QWidget" name="tab_2">
       <attribute name="title">
@@ -256,7 +257,7 @@
          <property name="title">
           <string>File Size</string>
          </property>
-         <layout class="QGridLayout" name="gridLayout">
+         <layout class="QFormLayout" name="formLayout_3">
           <item row="0" column="0">
            <widget class="QCheckBox" name="checkBox_12">
             <property name="text">
@@ -265,18 +266,22 @@
            </widget>
           </item>
           <item row="0" column="1">
-           <widget class="QSpinBox" name="spinBox">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="2">
-           <widget class="QComboBox" name="comboBox">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <item>
+             <widget class="QSpinBox" name="spinBox">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="comboBox">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
           </item>
           <item row="1" column="0">
            <widget class="QCheckBox" name="checkBox_13">
@@ -286,18 +291,22 @@
            </widget>
           </item>
           <item row="1" column="1">
-           <widget class="QSpinBox" name="spinBox_2">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="2">
-           <widget class="QComboBox" name="comboBox_2">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
+           <layout class="QHBoxLayout" name="horizontalLayout_3">
+            <item>
+             <widget class="QSpinBox" name="spinBox_2">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="comboBox_2">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
           </item>
          </layout>
         </widget>
@@ -307,7 +316,7 @@
          <property name="title">
           <string>Last Modified Time</string>
          </property>
-         <layout class="QGridLayout" name="gridLayout_2">
+         <layout class="QFormLayout" name="formLayout_2">
           <item row="0" column="0">
            <widget class="QCheckBox" name="checkBox_14">
             <property name="text">
@@ -315,6 +324,16 @@
             </property>
            </widget>
           </item>
+          <item row="0" column="1">
+           <widget class="QDateTimeEdit" name="dateTimeEdit">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="calendarPopup">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
           <item row="1" column="0">
            <widget class="QCheckBox" name="checkBox_15">
             <property name="text">
@@ -332,16 +351,6 @@
             </property>
            </widget>
           </item>
-          <item row="0" column="1">
-           <widget class="QDateTimeEdit" name="dateTimeEdit">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="calendarPopup">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
          </layout>
         </widget>
        </item>
diff --git a/pcmanfm/main-win.ui b/pcmanfm/main-win.ui
index 13740b1..408c4a6 100644
--- a/pcmanfm/main-win.ui
+++ b/pcmanfm/main-win.ui
@@ -20,7 +20,16 @@
   </property>
   <widget class="QWidget" name="centralwidget">
    <layout class="QVBoxLayout" name="verticalLayout">
-    <property name="margin">
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
      <number>0</number>
     </property>
     <item>
@@ -67,7 +76,7 @@
      <x>0</x>
      <y>0</y>
      <width>460</width>
-     <height>27</height>
+     <height>23</height>
     </rect>
    </property>
    <widget class="QMenu" name="menu_File">
@@ -171,6 +180,7 @@
     </property>
     <addaction name="actionOpenTerminal"/>
     <addaction name="actionOpenAsRoot"/>
+    <addaction name="actionFindFiles"/>
    </widget>
    <addaction name="menu_File"/>
    <addaction name="menu_Editw"/>
@@ -227,7 +237,7 @@
     </iconset>
    </property>
    <property name="text">
-    <string>Home</string>
+    <string>&amp;Home</string>
    </property>
    <property name="shortcut">
     <string>Alt+Home</string>
@@ -447,7 +457,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>Ascending</string>
+    <string>&amp;Ascending</string>
    </property>
   </action>
   <action name="actionDescending">
@@ -455,7 +465,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>Descending</string>
+    <string>&amp;Descending</string>
    </property>
   </action>
   <action name="actionByFileName">
@@ -463,7 +473,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>By File Name</string>
+    <string>&amp;By File Name</string>
    </property>
   </action>
   <action name="actionByMTime">
@@ -471,7 +481,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>By Modification Time</string>
+    <string>By &amp;Modification Time</string>
    </property>
   </action>
   <action name="actionByFileType">
@@ -479,7 +489,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>By File Type</string>
+    <string>By File &amp;Type</string>
    </property>
   </action>
   <action name="actionByOwner">
@@ -487,7 +497,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>By Owner</string>
+    <string>By &amp;Owner</string>
    </property>
   </action>
   <action name="actionFolderFirst">
@@ -495,7 +505,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>Folder First</string>
+    <string>&amp;Folder First</string>
    </property>
   </action>
   <action name="actionNewTab">
@@ -598,7 +608,7 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>Case Sensitive</string>
+    <string>&amp;Case Sensitive</string>
    </property>
   </action>
   <action name="actionByFileSize">
@@ -606,12 +616,12 @@
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>By File Size</string>
+    <string>By File &amp;Size</string>
    </property>
   </action>
   <action name="actionCloseWindow">
    <property name="text">
-    <string>Close Window</string>
+    <string>&amp;Close Window</string>
    </property>
   </action>
   <action name="actionEdit_Bookmarks">
@@ -639,10 +649,12 @@
   </action>
   <action name="actionNewFolder">
    <property name="icon">
-    <iconset theme="folder-new"/>
+    <iconset theme="folder-new">
+     <normaloff/>
+    </iconset>
    </property>
    <property name="text">
-    <string>Folder</string>
+    <string>&amp;Folder</string>
    </property>
    <property name="shortcut">
     <string>Ctrl+Shift+N</string>
@@ -650,15 +662,25 @@
   </action>
   <action name="actionNewBlankFile">
    <property name="icon">
-    <iconset theme="document-new"/>
+    <iconset theme="document-new">
+     <normaloff/>
+    </iconset>
    </property>
    <property name="text">
-    <string>Blank File</string>
+    <string>&amp;Blank File</string>
    </property>
    <property name="shortcut">
     <string>Ctrl+Alt+N</string>
    </property>
   </action>
+  <action name="actionFindFiles">
+   <property name="text">
+    <string>&amp;Find Files</string>
+   </property>
+   <property name="shortcut">
+    <string>F3</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
diff --git a/pcmanfm/mainwindow.cpp b/pcmanfm/mainwindow.cpp
index 19c22f9..1276d30 100644
--- a/pcmanfm/mainwindow.cpp
+++ b/pcmanfm/mainwindow.cpp
@@ -949,6 +949,25 @@ void MainWindow::on_actionOpenAsRoot_triggered() {
   }
 }
 
+void MainWindow::on_actionFindFiles_triggered() {
+  Application* app = static_cast<Application*>(qApp);
+  FmPathList* selectedPaths = currentPage()->selectedFilePaths();
+  QStringList paths;
+  if(selectedPaths) {
+    for(GList* l = fm_path_list_peek_head_link(selectedPaths); l; l = l->next) {
+      // FIXME: is it ok to use display name here?
+      // This might be broken on filesystems with non-UTF-8 filenames.
+      Fm::Path path(FM_PATH(l->data));
+      paths.append(path.displayName(false));
+    }
+    fm_path_list_unref(selectedPaths);
+  }
+  else {
+    paths.append(currentPage()->pathName());
+  }
+  app->findFiles(paths);
+}
+
 void MainWindow::on_actionOpenTerminal_triggered() {
   TabPage* page = currentPage();
   if(page) {
diff --git a/pcmanfm/mainwindow.h b/pcmanfm/mainwindow.h
index 58b6aa6..a36ec93 100644
--- a/pcmanfm/mainwindow.h
+++ b/pcmanfm/mainwindow.h
@@ -109,6 +109,7 @@ protected Q_SLOTS:
 
   void on_actionOpenTerminal_triggered();
   void on_actionOpenAsRoot_triggered();
+  void on_actionFindFiles_triggered();
 
   void on_actionAbout_triggered();