1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gtk/nsAppShell.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,142 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim:expandtab:shiftwidth=4:tabstop=4: 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include <sys/types.h> 1.12 +#include <unistd.h> 1.13 +#include <fcntl.h> 1.14 +#include <errno.h> 1.15 +#include <gdk/gdk.h> 1.16 +#include "nsAppShell.h" 1.17 +#include "nsWindow.h" 1.18 +#include "prlog.h" 1.19 +#include "prenv.h" 1.20 +#include "mozilla/HangMonitor.h" 1.21 +#include "mozilla/unused.h" 1.22 +#include "GeckoProfiler.h" 1.23 + 1.24 +using mozilla::unused; 1.25 + 1.26 +#define NOTIFY_TOKEN 0xFA 1.27 + 1.28 +#ifdef PR_LOGGING 1.29 +PRLogModuleInfo *gWidgetLog = nullptr; 1.30 +PRLogModuleInfo *gWidgetFocusLog = nullptr; 1.31 +PRLogModuleInfo *gWidgetDragLog = nullptr; 1.32 +PRLogModuleInfo *gWidgetDrawLog = nullptr; 1.33 +#endif 1.34 + 1.35 +static GPollFunc sPollFunc; 1.36 + 1.37 +// Wrapper function to disable hang monitoring while waiting in poll(). 1.38 +static gint 1.39 +PollWrapper(GPollFD *ufds, guint nfsd, gint timeout_) 1.40 +{ 1.41 + mozilla::HangMonitor::Suspend(); 1.42 + profiler_sleep_start(); 1.43 + gint result = (*sPollFunc)(ufds, nfsd, timeout_); 1.44 + profiler_sleep_end(); 1.45 + mozilla::HangMonitor::NotifyActivity(); 1.46 + return result; 1.47 +} 1.48 + 1.49 +/*static*/ gboolean 1.50 +nsAppShell::EventProcessorCallback(GIOChannel *source, 1.51 + GIOCondition condition, 1.52 + gpointer data) 1.53 +{ 1.54 + nsAppShell *self = static_cast<nsAppShell *>(data); 1.55 + 1.56 + unsigned char c; 1.57 + unused << read(self->mPipeFDs[0], &c, 1); 1.58 + NS_ASSERTION(c == (unsigned char) NOTIFY_TOKEN, "wrong token"); 1.59 + 1.60 + self->NativeEventCallback(); 1.61 + return TRUE; 1.62 +} 1.63 + 1.64 +nsAppShell::~nsAppShell() 1.65 +{ 1.66 + if (mTag) 1.67 + g_source_remove(mTag); 1.68 + if (mPipeFDs[0]) 1.69 + close(mPipeFDs[0]); 1.70 + if (mPipeFDs[1]) 1.71 + close(mPipeFDs[1]); 1.72 +} 1.73 + 1.74 +nsresult 1.75 +nsAppShell::Init() 1.76 +{ 1.77 +#ifdef PR_LOGGING 1.78 + if (!gWidgetLog) 1.79 + gWidgetLog = PR_NewLogModule("Widget"); 1.80 + if (!gWidgetFocusLog) 1.81 + gWidgetFocusLog = PR_NewLogModule("WidgetFocus"); 1.82 + if (!gWidgetDragLog) 1.83 + gWidgetDragLog = PR_NewLogModule("WidgetDrag"); 1.84 + if (!gWidgetDrawLog) 1.85 + gWidgetDrawLog = PR_NewLogModule("WidgetDraw"); 1.86 +#endif 1.87 + 1.88 + if (!sPollFunc) { 1.89 + sPollFunc = g_main_context_get_poll_func(nullptr); 1.90 + g_main_context_set_poll_func(nullptr, &PollWrapper); 1.91 + } 1.92 + 1.93 + if (PR_GetEnv("MOZ_DEBUG_PAINTS")) 1.94 + gdk_window_set_debug_updates(TRUE); 1.95 + 1.96 + int err = pipe(mPipeFDs); 1.97 + if (err) 1.98 + return NS_ERROR_OUT_OF_MEMORY; 1.99 + 1.100 + GIOChannel *ioc; 1.101 + GSource *source; 1.102 + 1.103 + // make the pipe nonblocking 1.104 + 1.105 + int flags = fcntl(mPipeFDs[0], F_GETFL, 0); 1.106 + if (flags == -1) 1.107 + goto failed; 1.108 + err = fcntl(mPipeFDs[0], F_SETFL, flags | O_NONBLOCK); 1.109 + if (err == -1) 1.110 + goto failed; 1.111 + flags = fcntl(mPipeFDs[1], F_GETFL, 0); 1.112 + if (flags == -1) 1.113 + goto failed; 1.114 + err = fcntl(mPipeFDs[1], F_SETFL, flags | O_NONBLOCK); 1.115 + if (err == -1) 1.116 + goto failed; 1.117 + 1.118 + ioc = g_io_channel_unix_new(mPipeFDs[0]); 1.119 + source = g_io_create_watch(ioc, G_IO_IN); 1.120 + g_io_channel_unref(ioc); 1.121 + g_source_set_callback(source, (GSourceFunc)EventProcessorCallback, this, nullptr); 1.122 + g_source_set_can_recurse(source, TRUE); 1.123 + mTag = g_source_attach(source, nullptr); 1.124 + g_source_unref(source); 1.125 + 1.126 + return nsBaseAppShell::Init(); 1.127 +failed: 1.128 + close(mPipeFDs[0]); 1.129 + close(mPipeFDs[1]); 1.130 + mPipeFDs[0] = mPipeFDs[1] = 0; 1.131 + return NS_ERROR_FAILURE; 1.132 +} 1.133 + 1.134 +void 1.135 +nsAppShell::ScheduleNativeEventCallback() 1.136 +{ 1.137 + unsigned char buf[] = { NOTIFY_TOKEN }; 1.138 + unused << write(mPipeFDs[1], buf, 1); 1.139 +} 1.140 + 1.141 +bool 1.142 +nsAppShell::ProcessNextNativeEvent(bool mayWait) 1.143 +{ 1.144 + return g_main_context_iteration(nullptr, mayWait); 1.145 +}