No issues found
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /*
4 * Nautilus
5 *
6 * Copyright (C) 2000 Eazel, Inc.
7 *
8 * Nautilus is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * Nautilus is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * Authors: Darin Adler <darin@bentspoon.com>
23 */
24
25 #include <config.h>
26 #include "nautilus-desktop-window.h"
27 #include "nautilus-window-private.h"
28 #include "nautilus-actions.h"
29
30 #include <X11/Xatom.h>
31 #include <gdk/gdkx.h>
32 #include <gtk/gtk.h>
33 #include <gio/gio.h>
34 #include <glib/gi18n.h>
35
36 #include <eel/eel-vfs-extensions.h>
37 #include <libnautilus-private/nautilus-file-utilities.h>
38 #include <libnautilus-private/nautilus-icon-names.h>
39 #include <libnautilus-private/nautilus-global-preferences.h>
40
41 struct NautilusDesktopWindowDetails {
42 gulong size_changed_id;
43
44 gboolean loaded;
45 };
46
47 G_DEFINE_TYPE (NautilusDesktopWindow, nautilus_desktop_window,
48 NAUTILUS_TYPE_WINDOW);
49
50 static void
51 nautilus_desktop_window_update_directory (NautilusDesktopWindow *window)
52 {
53 GFile *location;
54
55 g_assert (NAUTILUS_IS_DESKTOP_WINDOW (window));
56
57 window->details->loaded = FALSE;
58 location = g_file_new_for_uri (EEL_DESKTOP_URI);
59 nautilus_window_go_to (NAUTILUS_WINDOW (window), location);
60 window->details->loaded = TRUE;
61
62 g_object_unref (location);
63 }
64
65 static void
66 nautilus_desktop_window_constructed (GObject *obj)
67 {
68 GtkActionGroup *action_group;
69 GtkAction *action;
70 AtkObject *accessible;
71 NautilusDesktopWindow *window = NAUTILUS_DESKTOP_WINDOW (obj);
72 NautilusWindow *nwindow = NAUTILUS_WINDOW (obj);
73
74 G_OBJECT_CLASS (nautilus_desktop_window_parent_class)->constructed (obj);
75
76 action_group = nautilus_window_get_main_action_group (nwindow);
77
78 /* Don't allow close action on desktop */
79 action = gtk_action_group_get_action (action_group,
80 NAUTILUS_ACTION_CLOSE);
81 gtk_action_set_sensitive (action, FALSE);
82
83 /* Don't allow new tab on desktop */
84 action = gtk_action_group_get_action (action_group,
85 NAUTILUS_ACTION_NEW_TAB);
86 gtk_action_set_sensitive (action, FALSE);
87
88 /* Set the accessible name so that it doesn't inherit the cryptic desktop URI. */
89 accessible = gtk_widget_get_accessible (GTK_WIDGET (window));
90
91 if (accessible) {
92 atk_object_set_name (accessible, _("Desktop"));
93 }
94 }
95
96 static void
97 nautilus_desktop_window_init (NautilusDesktopWindow *window)
98 {
99 window->details = G_TYPE_INSTANCE_GET_PRIVATE (window, NAUTILUS_TYPE_DESKTOP_WINDOW,
100 NautilusDesktopWindowDetails);
101
102 gtk_window_move (GTK_WINDOW (window), 0, 0);
103
104 /* shouldn't really be needed given our semantic type
105 * of _NET_WM_TYPE_DESKTOP, but why not
106 */
107 gtk_window_set_resizable (GTK_WINDOW (window),
108 FALSE);
109
110 g_object_set_data (G_OBJECT (window), "is_desktop_window",
111 GINT_TO_POINTER (1));
112 }
113
114 static void
115 nautilus_desktop_window_screen_size_changed (GdkScreen *screen,
116 NautilusDesktopWindow *window)
117 {
118 int width_request, height_request;
119
120 width_request = gdk_screen_get_width (screen);
121 height_request = gdk_screen_get_height (screen);
122
123 g_object_set (window,
124 "width_request", width_request,
125 "height_request", height_request,
126 NULL);
127 }
128
129 NautilusDesktopWindow *
130 nautilus_desktop_window_new (GtkApplication *application,
131 GdkScreen *screen)
132 {
133 NautilusDesktopWindow *window;
134 int width_request, height_request;
135
136 width_request = gdk_screen_get_width (screen);
137 height_request = gdk_screen_get_height (screen);
138
139 window = g_object_new (NAUTILUS_TYPE_DESKTOP_WINDOW,
140 "application", application,
141 "disable-chrome", TRUE,
142 "width_request", width_request,
143 "height_request", height_request,
144 "screen", screen,
145 NULL);
146
147 /* Special sawmill setting*/
148 gtk_window_set_wmclass (GTK_WINDOW (window), "desktop_window", "Nautilus");
149
150 /* Point window at the desktop folder.
151 * Note that nautilus_desktop_window_init is too early to do this.
152 */
153 nautilus_desktop_window_update_directory (window);
154
155 return window;
156 }
157
158 static gboolean
159 nautilus_desktop_window_delete_event (GtkWidget *widget,
160 GdkEventAny *event)
161 {
162 /* Returning true tells GTK+ not to delete the window. */
163 return TRUE;
164 }
165
166 static void
167 map (GtkWidget *widget)
168 {
169 /* Chain up to realize our children */
170 GTK_WIDGET_CLASS (nautilus_desktop_window_parent_class)->map (widget);
171 gdk_window_lower (gtk_widget_get_window (widget));
172 }
173
174 static void
175 unrealize (GtkWidget *widget)
176 {
177 NautilusDesktopWindow *window;
178 NautilusDesktopWindowDetails *details;
179 GdkWindow *root_window;
180
181 window = NAUTILUS_DESKTOP_WINDOW (widget);
182 details = window->details;
183
184 root_window = gdk_screen_get_root_window (
185 gtk_window_get_screen (GTK_WINDOW (window)));
186
187 gdk_property_delete (root_window,
188 gdk_atom_intern ("NAUTILUS_DESKTOP_WINDOW_ID", TRUE));
189
190 if (details->size_changed_id != 0) {
191 g_signal_handler_disconnect (gtk_window_get_screen (GTK_WINDOW (window)),
192 details->size_changed_id);
193 details->size_changed_id = 0;
194 }
195
196 GTK_WIDGET_CLASS (nautilus_desktop_window_parent_class)->unrealize (widget);
197 }
198
199 static void
200 set_wmspec_desktop_hint (GdkWindow *window)
201 {
202 GdkAtom atom;
203
204 atom = gdk_atom_intern ("_NET_WM_WINDOW_TYPE_DESKTOP", FALSE);
205
206 gdk_property_change (window,
207 gdk_atom_intern ("_NET_WM_WINDOW_TYPE", FALSE),
208 gdk_x11_xatom_to_atom (XA_ATOM), 32,
209 GDK_PROP_MODE_REPLACE, (guchar *) &atom, 1);
210 }
211
212 static void
213 set_desktop_window_id (NautilusDesktopWindow *window,
214 GdkWindow *gdkwindow)
215 {
216 /* Tuck the desktop windows xid in the root to indicate we own the desktop.
217 */
218 Window window_xid;
219 GdkWindow *root_window;
220
221 root_window = gdk_screen_get_root_window (
222 gtk_window_get_screen (GTK_WINDOW (window)));
223
224 window_xid = GDK_WINDOW_XID (gdkwindow);
225
226 gdk_property_change (root_window,
227 gdk_atom_intern ("NAUTILUS_DESKTOP_WINDOW_ID", FALSE),
228 gdk_x11_xatom_to_atom (XA_WINDOW), 32,
229 GDK_PROP_MODE_REPLACE, (guchar *) &window_xid, 1);
230 }
231
232 static void
233 realize (GtkWidget *widget)
234 {
235 NautilusDesktopWindow *window;
236 NautilusDesktopWindowDetails *details;
237
238 window = NAUTILUS_DESKTOP_WINDOW (widget);
239 details = window->details;
240
241 /* Make sure we get keyboard events */
242 gtk_widget_set_events (widget, gtk_widget_get_events (widget)
243 | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
244
245 /* Do the work of realizing. */
246 GTK_WIDGET_CLASS (nautilus_desktop_window_parent_class)->realize (widget);
247
248 /* This is the new way to set up the desktop window */
249 set_wmspec_desktop_hint (gtk_widget_get_window (widget));
250
251 set_desktop_window_id (window, gtk_widget_get_window (widget));
252
253 details->size_changed_id =
254 g_signal_connect (gtk_window_get_screen (GTK_WINDOW (window)), "size_changed",
255 G_CALLBACK (nautilus_desktop_window_screen_size_changed), window);
256 }
257
258 static NautilusIconInfo *
259 real_get_icon (NautilusWindow *window,
260 NautilusWindowSlot *slot)
261 {
262 return nautilus_icon_info_lookup_from_name (NAUTILUS_DESKTOP_ICON_DESKTOP, 48);
263 }
264
265 static void
266 real_sync_title (NautilusWindow *window,
267 NautilusWindowSlot *slot)
268 {
269 /* hardcode "Desktop" */
270 gtk_window_set_title (GTK_WINDOW (window), _("Desktop"));
271 }
272
273 static void
274 real_window_close (NautilusWindow *window)
275 {
276 /* stub, does nothing */
277 return;
278 }
279
280 static void
281 real_sync_view_as_menus (NautilusWindow *window)
282 {
283 /* stub, does nothing */
284 return;
285 }
286
287 static void
288 nautilus_desktop_window_class_init (NautilusDesktopWindowClass *klass)
289 {
290 GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
291 NautilusWindowClass *nclass = NAUTILUS_WINDOW_CLASS (klass);
292 GObjectClass *oclass = G_OBJECT_CLASS (klass);
293
294 oclass->constructed = nautilus_desktop_window_constructed;
295
296 wclass->realize = realize;
297 wclass->unrealize = unrealize;
298 wclass->map = map;
299 wclass->delete_event = nautilus_desktop_window_delete_event;
300
301 nclass->sync_title = real_sync_title;
302 nclass->sync_view_as_menus = real_sync_view_as_menus;
303 nclass->get_icon = real_get_icon;
304 nclass->close = real_window_close;
305
306 g_type_class_add_private (klass, sizeof (NautilusDesktopWindowDetails));
307 }
308
309 gboolean
310 nautilus_desktop_window_loaded (NautilusDesktopWindow *window)
311 {
312 return window->details->loaded;
313 }