Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:expandtab:shiftwidth=2:tabstop=8:
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "nsGTKRemoteService.h"
9 :
10 : #include <gtk/gtk.h>
11 : #include <gdk/gdk.h>
12 : #include <gdk/gdkx.h>
13 :
14 : #include "nsIBaseWindow.h"
15 : #include "nsIDocShell.h"
16 : #include "nsPIDOMWindow.h"
17 : #include "mozilla/ModuleUtils.h"
18 : #include "nsIServiceManager.h"
19 : #include "nsIWeakReference.h"
20 : #include "nsIWidget.h"
21 : #include "nsIAppShellService.h"
22 : #include "nsAppShellCID.h"
23 :
24 : #include "nsCOMPtr.h"
25 :
26 : #include "nsGTKToolkit.h"
27 :
28 0 : NS_IMPL_ISUPPORTS(nsGTKRemoteService,
29 : nsIRemoteService,
30 : nsIObserver)
31 :
32 : NS_IMETHODIMP
33 0 : nsGTKRemoteService::Startup(const char* aAppName, const char* aProfileName)
34 : {
35 0 : NS_ASSERTION(aAppName, "Don't pass a null appname!");
36 0 : sRemoteImplementation = this;
37 :
38 0 : if (mServerWindow) return NS_ERROR_ALREADY_INITIALIZED;
39 :
40 0 : XRemoteBaseStartup(aAppName, aProfileName);
41 :
42 0 : mServerWindow = gtk_invisible_new();
43 0 : gtk_widget_realize(mServerWindow);
44 0 : HandleCommandsFor(mServerWindow, nullptr);
45 :
46 0 : for (auto iter = mWindows.Iter(); !iter.Done(); iter.Next()) {
47 0 : HandleCommandsFor(iter.Key(), iter.UserData());
48 : }
49 :
50 0 : return NS_OK;
51 : }
52 :
53 0 : static nsIWidget* GetMainWidget(nsPIDOMWindowInner* aWindow)
54 : {
55 : // get the native window for this instance
56 : nsCOMPtr<nsIBaseWindow> baseWindow
57 0 : (do_QueryInterface(aWindow->GetDocShell()));
58 0 : NS_ENSURE_TRUE(baseWindow, nullptr);
59 :
60 0 : nsCOMPtr<nsIWidget> mainWidget;
61 0 : baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
62 0 : return mainWidget;
63 : }
64 :
65 : NS_IMETHODIMP
66 0 : nsGTKRemoteService::RegisterWindow(mozIDOMWindow* aWindow)
67 : {
68 0 : nsIWidget* mainWidget = GetMainWidget(nsPIDOMWindowInner::From(aWindow));
69 0 : NS_ENSURE_TRUE(mainWidget, NS_ERROR_FAILURE);
70 :
71 : GtkWidget* widget =
72 0 : (GtkWidget*) mainWidget->GetNativeData(NS_NATIVE_SHELLWIDGET);
73 0 : NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
74 :
75 0 : nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aWindow);
76 0 : NS_ENSURE_TRUE(weak, NS_ERROR_FAILURE);
77 :
78 0 : mWindows.Put(widget, weak);
79 :
80 : // If Startup() has already been called, immediately register this window.
81 0 : if (mServerWindow) {
82 0 : HandleCommandsFor(widget, weak);
83 : }
84 :
85 0 : return NS_OK;
86 : }
87 :
88 : NS_IMETHODIMP
89 0 : nsGTKRemoteService::Shutdown()
90 : {
91 0 : if (!mServerWindow)
92 0 : return NS_ERROR_NOT_INITIALIZED;
93 :
94 0 : gtk_widget_destroy(mServerWindow);
95 0 : mServerWindow = nullptr;
96 0 : return NS_OK;
97 : }
98 :
99 : // Set desktop startup ID to the passed ID, if there is one, so that any created
100 : // windows get created with the right window manager metadata, and any windows
101 : // that get new tabs and are activated also get the right WM metadata.
102 : // The timestamp will be used if there is no desktop startup ID, or if we're
103 : // raising an existing window rather than showing a new window for the first time.
104 : void
105 0 : nsGTKRemoteService::SetDesktopStartupIDOrTimestamp(const nsACString& aDesktopStartupID,
106 : uint32_t aTimestamp) {
107 0 : nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
108 0 : if (!toolkit)
109 0 : return;
110 :
111 0 : if (!aDesktopStartupID.IsEmpty()) {
112 0 : toolkit->SetDesktopStartupID(aDesktopStartupID);
113 : }
114 :
115 0 : toolkit->SetFocusTimestamp(aTimestamp);
116 : }
117 :
118 :
119 : void
120 0 : nsGTKRemoteService::HandleCommandsFor(GtkWidget* widget,
121 : nsIWeakReference* aWindow)
122 : {
123 0 : g_signal_connect(G_OBJECT(widget), "property_notify_event",
124 0 : G_CALLBACK(HandlePropertyChange), aWindow);
125 :
126 0 : gtk_widget_add_events(widget, GDK_PROPERTY_CHANGE_MASK);
127 :
128 : #if (MOZ_WIDGET_GTK == 2)
129 : Window window = GDK_WINDOW_XWINDOW(widget->window);
130 : #else
131 0 : Window window = gdk_x11_window_get_xid(gtk_widget_get_window(widget));
132 : #endif
133 0 : nsXRemoteService::HandleCommandsFor(window);
134 :
135 0 : }
136 :
137 : gboolean
138 0 : nsGTKRemoteService::HandlePropertyChange(GtkWidget *aWidget,
139 : GdkEventProperty *pevent,
140 : nsIWeakReference *aThis)
141 : {
142 0 : if (pevent->state == GDK_PROPERTY_NEW_VALUE) {
143 0 : Atom changedAtom = gdk_x11_atom_to_xatom(pevent->atom);
144 :
145 : #if (MOZ_WIDGET_GTK == 2)
146 : XID window = GDK_WINDOW_XWINDOW(pevent->window);
147 : #else
148 0 : XID window = gdk_x11_window_get_xid(gtk_widget_get_window(aWidget));
149 : #endif
150 0 : return HandleNewProperty(window,
151 : GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
152 0 : pevent->time, changedAtom, aThis);
153 : }
154 0 : return FALSE;
155 : }
156 :
157 :
158 : // {C0773E90-5799-4eff-AD03-3EBCD85624AC}
159 : #define NS_REMOTESERVICE_CID \
160 : { 0xc0773e90, 0x5799, 0x4eff, { 0xad, 0x3, 0x3e, 0xbc, 0xd8, 0x56, 0x24, 0xac } }
161 :
162 0 : NS_GENERIC_FACTORY_CONSTRUCTOR(nsGTKRemoteService)
163 : NS_DEFINE_NAMED_CID(NS_REMOTESERVICE_CID);
164 :
165 : static const mozilla::Module::CIDEntry kRemoteCIDs[] = {
166 : { &kNS_REMOTESERVICE_CID, false, nullptr, nsGTKRemoteServiceConstructor },
167 : { nullptr }
168 : };
169 :
170 : static const mozilla::Module::ContractIDEntry kRemoteContracts[] = {
171 : { "@mozilla.org/toolkit/remote-service;1", &kNS_REMOTESERVICE_CID },
172 : { nullptr }
173 : };
174 :
175 : static const mozilla::Module kRemoteModule = {
176 : mozilla::Module::kVersion,
177 : kRemoteCIDs,
178 : kRemoteContracts
179 : };
180 :
181 : NSMODULE_DEFN(RemoteServiceModule) = &kRemoteModule;
|