1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim:expandtab:shiftwidth=4:tabstop=4:
3 : */
4 : /* ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is mozilla.org code.
18 : *
19 : * The Initial Developer of the Original Code is Christopher Blizzard
20 : * <blizzard@mozilla.org>. Portions created by the Initial Developer
21 : * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include <sys/types.h>
40 : #include <unistd.h>
41 : #include <fcntl.h>
42 : #include <errno.h>
43 : #include <gdk/gdk.h>
44 : #include "nsAppShell.h"
45 : #include "nsWindow.h"
46 : #include "prlog.h"
47 : #include "prenv.h"
48 : #include "mozilla/HangMonitor.h"
49 :
50 : #define NOTIFY_TOKEN 0xFA
51 :
52 : #ifdef PR_LOGGING
53 : PRLogModuleInfo *gWidgetLog = nsnull;
54 : PRLogModuleInfo *gWidgetFocusLog = nsnull;
55 : PRLogModuleInfo *gWidgetDragLog = nsnull;
56 : PRLogModuleInfo *gWidgetDrawLog = nsnull;
57 : #endif
58 :
59 : static GPollFunc sPollFunc;
60 :
61 : // Wrapper function to disable hang monitoring while waiting in poll().
62 : static gint
63 271073 : PollWrapper(GPollFD *ufds, guint nfsd, gint timeout_)
64 : {
65 271073 : mozilla::HangMonitor::Suspend();
66 271073 : gint result = (*sPollFunc)(ufds, nfsd, timeout_);
67 271073 : mozilla::HangMonitor::NotifyActivity();
68 271073 : return result;
69 : }
70 :
71 : /*static*/ gboolean
72 81592 : nsAppShell::EventProcessorCallback(GIOChannel *source,
73 : GIOCondition condition,
74 : gpointer data)
75 : {
76 81592 : nsAppShell *self = static_cast<nsAppShell *>(data);
77 :
78 : unsigned char c;
79 81592 : read(self->mPipeFDs[0], &c, 1);
80 81592 : NS_ASSERTION(c == (unsigned char) NOTIFY_TOKEN, "wrong token");
81 :
82 81592 : self->NativeEventCallback();
83 81592 : return TRUE;
84 : }
85 :
86 4161 : nsAppShell::~nsAppShell()
87 : {
88 1387 : if (mTag)
89 1387 : g_source_remove(mTag);
90 1387 : if (mPipeFDs[0])
91 1387 : close(mPipeFDs[0]);
92 1387 : if (mPipeFDs[1])
93 1387 : close(mPipeFDs[1]);
94 5548 : }
95 :
96 : nsresult
97 1387 : nsAppShell::Init()
98 : {
99 : #ifdef PR_LOGGING
100 1387 : if (!gWidgetLog)
101 1387 : gWidgetLog = PR_NewLogModule("Widget");
102 1387 : if (!gWidgetFocusLog)
103 1387 : gWidgetFocusLog = PR_NewLogModule("WidgetFocus");
104 1387 : if (!gWidgetDragLog)
105 1387 : gWidgetDragLog = PR_NewLogModule("WidgetDrag");
106 1387 : if (!gWidgetDrawLog)
107 1387 : gWidgetDrawLog = PR_NewLogModule("WidgetDraw");
108 : #endif
109 :
110 1387 : if (!sPollFunc) {
111 1387 : sPollFunc = g_main_context_get_poll_func(NULL);
112 1387 : g_main_context_set_poll_func(NULL, &PollWrapper);
113 : }
114 :
115 : GIOChannel *ioc;
116 :
117 1387 : if (PR_GetEnv("MOZ_DEBUG_PAINTS"))
118 0 : gdk_window_set_debug_updates(TRUE);
119 :
120 1387 : int err = pipe(mPipeFDs);
121 1387 : if (err)
122 0 : return NS_ERROR_OUT_OF_MEMORY;
123 :
124 : // make the pipe nonblocking
125 :
126 1387 : int flags = fcntl(mPipeFDs[0], F_GETFL, 0);
127 1387 : if (flags == -1)
128 0 : goto failed;
129 1387 : err = fcntl(mPipeFDs[0], F_SETFL, flags | O_NONBLOCK);
130 1387 : if (err == -1)
131 0 : goto failed;
132 1387 : flags = fcntl(mPipeFDs[1], F_GETFL, 0);
133 1387 : if (flags == -1)
134 0 : goto failed;
135 1387 : err = fcntl(mPipeFDs[1], F_SETFL, flags | O_NONBLOCK);
136 1387 : if (err == -1)
137 0 : goto failed;
138 :
139 1387 : ioc = g_io_channel_unix_new(mPipeFDs[0]);
140 : mTag = g_io_add_watch_full(ioc, G_PRIORITY_DEFAULT, G_IO_IN,
141 1387 : EventProcessorCallback, this, nsnull);
142 1387 : g_io_channel_unref(ioc);
143 :
144 1387 : return nsBaseAppShell::Init();
145 : failed:
146 0 : close(mPipeFDs[0]);
147 0 : close(mPipeFDs[1]);
148 0 : mPipeFDs[0] = mPipeFDs[1] = 0;
149 0 : return NS_ERROR_FAILURE;
150 : }
151 :
152 : void
153 81592 : nsAppShell::ScheduleNativeEventCallback()
154 : {
155 81592 : unsigned char buf[] = { NOTIFY_TOKEN };
156 81592 : write(mPipeFDs[1], buf, 1);
157 81592 : }
158 :
159 : bool
160 271073 : nsAppShell::ProcessNextNativeEvent(bool mayWait)
161 : {
162 271073 : return g_main_context_iteration(NULL, mayWait);
163 : }
|