source: trunk/third/nautilus/src/nautilus-desktop-window.c @ 18663

Revision 18663, 9.6 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18662, which included commits to RCS files with non-trunk default branches.
Line 
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
28#include <X11/Xatom.h>
29#include <gdk/gdkx.h>
30#include <gtk/gtklayout.h>
31#include <libgnome/gnome-macros.h>
32#include <libgnomevfs/gnome-vfs-utils.h>
33#include <libnautilus-private/nautilus-file-utilities.h>
34
35struct NautilusDesktopWindowDetails {
36        int dummy;
37};
38
39static void set_wmspec_desktop_hint (GdkWindow *window);
40
41GNOME_CLASS_BOILERPLATE (NautilusDesktopWindow, nautilus_desktop_window,
42                         NautilusWindow, NAUTILUS_TYPE_WINDOW)
43
44static void
45nautilus_desktop_window_instance_init (NautilusDesktopWindow *window)
46{
47        window->details = g_new0 (NautilusDesktopWindowDetails, 1);
48
49        gtk_window_move (GTK_WINDOW (window), 0, 0);
50
51        /* shouldn't really be needed given our semantic type
52         * of _NET_WM_TYPE_DESKTOP, but why not
53         */
54        gtk_window_set_resizable (GTK_WINDOW (window),
55                                  FALSE);
56}
57
58static gint
59nautilus_desktop_window_delete_event (NautilusDesktopWindow *window)
60{
61        /* Returning true tells GTK+ not to delete the window. */
62        return TRUE;
63}
64
65void
66nautilus_desktop_window_update_directory (NautilusDesktopWindow *window)
67{
68        char *desktop_directory_path;
69        char *desktop_directory_uri;
70
71        g_assert (NAUTILUS_IS_DESKTOP_WINDOW (window));
72
73        desktop_directory_path = nautilus_get_desktop_directory ();
74       
75        desktop_directory_uri = gnome_vfs_get_uri_from_local_path (desktop_directory_path);
76        g_free (desktop_directory_path);
77        window->affect_desktop_on_next_location_change = TRUE;
78        nautilus_window_go_to (NAUTILUS_WINDOW (window), desktop_directory_uri);
79        g_free (desktop_directory_uri);
80}
81
82static void
83nautilus_desktop_window_screen_size_changed (GdkScreen             *screen,
84                                             NautilusDesktopWindow *window)
85{
86        int width_request, height_request;
87
88        width_request = gdk_screen_get_width (screen);
89        height_request = gdk_screen_get_height (screen);
90       
91        g_object_set (window,
92                      "width_request", width_request,
93                      "height_request", height_request,
94                      NULL);
95}
96
97NautilusDesktopWindow *
98nautilus_desktop_window_new (NautilusApplication *application,
99                             GdkScreen           *screen)
100{
101        NautilusDesktopWindow *window;
102        int width_request, height_request;
103
104        width_request = gdk_screen_get_width (screen);
105        height_request = gdk_screen_get_height (screen);
106
107        window = NAUTILUS_DESKTOP_WINDOW
108                (gtk_widget_new (nautilus_desktop_window_get_type(),
109                                 "app", application,
110                                 "app_id", "nautilus",
111                                 "width_request", width_request,
112                                 "height_request", height_request,
113                                 "screen", screen,
114                                 NULL));
115
116        /* Special sawmill setting*/
117        gtk_window_set_wmclass (GTK_WINDOW (window), "desktop_window", "Nautilus");
118
119        g_signal_connect (window, "delete_event", G_CALLBACK (nautilus_desktop_window_delete_event), NULL);
120
121        /* Point window at the desktop folder.
122         * Note that nautilus_desktop_window_init is too early to do this.
123         */
124        nautilus_desktop_window_update_directory (window);
125
126        return window;
127}
128
129static void
130finalize (GObject *object)
131{
132        NautilusDesktopWindow *window;
133
134        window = NAUTILUS_DESKTOP_WINDOW (object);
135
136        g_free (window->details);
137
138        G_OBJECT_CLASS (parent_class)->finalize (object);
139}
140
141/* Disable this code for the time being, since its:
142 * a) not working
143 * b) crashes nautilus if the root window has a different
144 *    depth than the nautilus window
145 *
146 * The idea behind the code is to grab the old background pixmap
147 * and temporarily set it as the background for the nautilus window
148 * to avoid flashing before the correct background has been set.
149 */
150#if 0
151static void
152set_gdk_window_background (GdkWindow *window,
153                           gboolean   have_pixel,
154                           Pixmap     pixmap,
155                           gulong     pixel)
156{
157        Window w;
158
159        w = GDK_WINDOW_XWINDOW (window);
160
161        if (pixmap != None) {
162                XSetWindowBackgroundPixmap (GDK_DISPLAY (), w,
163                                            pixmap);
164        } else if (have_pixel) {
165                XSetWindowBackground (GDK_DISPLAY (), w,
166                                      pixel);
167        } else {
168                XSetWindowBackgroundPixmap (GDK_DISPLAY (), w,
169                                            None);
170        }
171}
172
173static void
174set_window_background (GtkWidget *widget,
175                       gboolean   already_have_root_bg,
176                       gboolean   have_pixel,
177                       Pixmap     pixmap,
178                       gulong     pixel)
179{
180        Atom type;
181        gulong nitems, bytes_after;
182        gint format;
183        guchar *data;
184       
185        /* Set the background to show the root window to avoid a flash that
186         * would otherwise occur.
187         */
188
189        if (GTK_IS_WINDOW (widget)) {
190                gtk_widget_set_app_paintable (widget, TRUE);
191        }
192       
193        if (!already_have_root_bg) {
194                have_pixel = FALSE;
195                already_have_root_bg = TRUE;
196               
197                /* We want to do this round-trip-to-server work only
198                 * for the first invocation, not on recursions
199                 */
200               
201                XGetWindowProperty (GDK_DISPLAY (), GDK_ROOT_WINDOW (),
202                                    gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"),
203                                    0L, 1L, False, XA_PIXMAP,
204                                    &type, &format, &nitems, &bytes_after,
205                                    &data);
206 
207                if (type == XA_PIXMAP) {
208                        if (format == 32 && nitems == 1 && bytes_after == 0) {
209                                pixmap = *(Pixmap *) data;
210                        }
211 
212                        XFree (data);
213                }
214
215                if (pixmap == None) {
216                        XGetWindowProperty (GDK_DISPLAY (), GDK_ROOT_WINDOW (),
217                                            gdk_x11_get_xatom_by_name ("_XROOTCOLOR_PIXEL"),
218                                            0L, 1L, False, AnyPropertyType,
219                                            &type, &format, &nitems, &bytes_after,
220                                            &data);
221                       
222                        if (type != None) {
223                                if (format == 32 && nitems == 1 && bytes_after == 0) {
224                                        pixel = *(gulong *) data;
225                                        have_pixel = TRUE;
226                                }
227                               
228                                XFree (data);
229                        }
230                }
231        }
232       
233        set_gdk_window_background (widget->window,
234                                   have_pixel, pixmap, pixel);
235       
236        if (GTK_IS_BIN (widget) &&
237            GTK_BIN (widget)->child) {
238                /* Ensure we're realized */
239                gtk_widget_realize (GTK_BIN (widget)->child);
240               
241                set_window_background (GTK_BIN (widget)->child,
242                                       already_have_root_bg, have_pixel,
243                                       pixmap, pixel);
244        }
245
246        /* For both parent and child, if it's a layout then set on the
247         * bin window as well.
248         */
249        if (GTK_IS_LAYOUT (widget)) {
250                set_gdk_window_background (GTK_LAYOUT (widget)->bin_window,
251                                           have_pixel,
252                                           pixmap, pixel);
253        }
254}
255#endif
256static void
257map (GtkWidget *widget)
258{
259        /* Disable for now, see above for comments */
260#if 0
261        set_window_background (widget, FALSE, FALSE, None, 0);
262#endif 
263        /* Chain up to realize our children */
264        GTK_WIDGET_CLASS (parent_class)->map (widget);
265        gdk_window_lower (widget->window);
266}
267
268
269static void
270unrealize (GtkWidget *widget)
271{
272        NautilusDesktopWindow *window;
273        GdkWindow *root_window;
274
275        window = NAUTILUS_DESKTOP_WINDOW (widget);
276
277        root_window = gdk_screen_get_root_window (
278                                gtk_window_get_screen (GTK_WINDOW (window)));
279
280        gdk_property_delete (root_window,
281                             gdk_atom_intern ("NAUTILUS_DESKTOP_WINDOW_ID", TRUE));
282
283        g_signal_handlers_disconnect_by_func (gtk_window_get_screen (GTK_WINDOW (window)),
284                                              G_CALLBACK (nautilus_desktop_window_screen_size_changed),
285                                              window);
286               
287        GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
288}
289
290static void
291set_wmspec_desktop_hint (GdkWindow *window)
292{
293        GdkAtom atom;
294
295        atom = gdk_atom_intern ("_NET_WM_WINDOW_TYPE_DESKTOP", FALSE);
296       
297        gdk_property_change (window,
298                             gdk_atom_intern ("_NET_WM_WINDOW_TYPE", FALSE),
299                             gdk_x11_xatom_to_atom (XA_ATOM), 32,
300                             GDK_PROP_MODE_REPLACE, (guchar *) &atom, 1);
301}
302
303static void
304set_desktop_window_id (NautilusDesktopWindow *window,
305                       GdkWindow             *gdkwindow)
306{
307        /* Tuck the desktop windows xid in the root to indicate we own the desktop.
308         */
309        Window window_xid;
310        GdkWindow *root_window;
311
312        root_window = gdk_screen_get_root_window (
313                                gtk_window_get_screen (GTK_WINDOW (window)));
314
315        window_xid = GDK_WINDOW_XWINDOW (gdkwindow);
316
317        gdk_property_change (root_window,
318                             gdk_atom_intern ("NAUTILUS_DESKTOP_WINDOW_ID", FALSE),
319                             gdk_x11_xatom_to_atom (XA_WINDOW), 32,
320                             GDK_PROP_MODE_REPLACE, (guchar *) &window_xid, 1);
321}
322
323static void
324realize (GtkWidget *widget)
325{
326        NautilusDesktopWindow *window;
327
328        window = NAUTILUS_DESKTOP_WINDOW (widget);
329
330        /* Make sure we get keyboard events */
331        gtk_widget_set_events (widget, gtk_widget_get_events (widget)
332                              | GDK_KEY_PRESS_MASK | GDK_KEY_PRESS_MASK);
333                             
334        /* Do the work of realizing. */
335        GTK_WIDGET_CLASS (parent_class)->realize (widget);
336
337        /* This is the new way to set up the desktop window */
338        set_wmspec_desktop_hint (widget->window);
339
340        set_desktop_window_id (window, widget->window);
341
342        g_signal_connect (gtk_window_get_screen (GTK_WINDOW (window)), "size_changed",
343                          G_CALLBACK (nautilus_desktop_window_screen_size_changed), window);
344}
345
346static void
347real_add_current_location_to_history_list (NautilusWindow *window)
348{
349        /* Do nothing. The desktop window's location should not
350         * show up in the history list.
351         */
352}
353
354static void
355nautilus_desktop_window_class_init (NautilusDesktopWindowClass *class)
356{
357        G_OBJECT_CLASS (class)->finalize = finalize;
358        GTK_WIDGET_CLASS (class)->realize = realize;
359        GTK_WIDGET_CLASS (class)->unrealize = unrealize;
360
361
362        GTK_WIDGET_CLASS (class)->map = map;
363
364        NAUTILUS_WINDOW_CLASS (class)->add_current_location_to_history_list
365                = real_add_current_location_to_history_list;
366}
Note: See TracBrowser for help on using the repository browser.