Add a Keywords line into lxappearance.desktop file.
[lxde/lxappearance.git] / src / cursor-theme.c
1 /*
2 * cursor-theme.c
3 *
4 * Copyright 2010 PCMan <pcman.tw@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "cursor-theme.h"
23 #include "icon-theme.h"
24 #include "lxappearance.h"
25 #include <gdk/gdkx.h>
26
27 static void update_cursor_demo()
28 {
29 GtkListStore* store = gtk_list_store_new(1, GDK_TYPE_PIXBUF);
30 GdkCursor* cursor;
31 GdkCursorType types[] = {
32 GDK_LEFT_PTR,
33 GDK_HAND2,
34 GDK_WATCH,
35 GDK_FLEUR,
36 GDK_XTERM,
37 GDK_LEFT_SIDE,
38 GDK_TOP_LEFT_CORNER,
39 GDK_SB_H_DOUBLE_ARROW};
40 int i;
41 for(i = 0; i < (int)G_N_ELEMENTS(types); ++i)
42 {
43 GtkTreeIter it;
44 cursor = gdk_cursor_new(types[i]);
45 GdkPixbuf* pix = gdk_cursor_get_image(cursor);
46 gdk_cursor_unref(cursor);
47 if (pix != NULL)
48 {
49 gtk_list_store_insert_with_values(store, &it, -1, 0, pix, -1);
50 g_object_unref(pix);
51 }
52 }
53 gtk_icon_view_set_model(GTK_ICON_VIEW(app.cursor_demo_view), GTK_TREE_MODEL(store));
54 g_object_unref(store);
55
56 /* gtk+ programs should reload named cursors correctly.
57 * However, if the cursor is inherited from the root window,
58 * gtk+ won't change it. So we need to update the cursor of root window.
59 * Unfortunately, this doesn't work for non-gtk+ programs.
60 * KDE programs seem to require special handling with XFixes */
61 cursor = gdk_cursor_new(GDK_LEFT_PTR);
62 i = gdk_display_get_n_screens(gdk_display_get_default());
63 while(--i >= 0)
64 {
65 GdkScreen* screen = gdk_display_get_screen(gdk_display_get_default(), i);
66 gdk_window_set_cursor(gdk_screen_get_root_window(screen), cursor);
67 }
68 gdk_cursor_unref(cursor);
69 }
70
71 static void on_cursor_theme_sel_changed(GtkTreeSelection* tree_sel, gpointer user_data)
72 {
73 GtkTreeModel* model;
74 GtkTreeIter it;
75 if(gtk_tree_selection_get_selected(tree_sel, &model, &it))
76 {
77 IconTheme* theme;
78 gtk_tree_model_get(model, &it, 1, &theme, -1);
79 if(g_strcmp0(theme->name, app.cursor_theme))
80 {
81 g_free(app.cursor_theme);
82 app.cursor_theme = g_strdup(theme->name);
83 g_object_set(gtk_settings_get_default(), "gtk-cursor-theme-name", app.cursor_theme, NULL);
84
85 update_cursor_demo();
86 lxappearance_changed();
87 }
88
89 gtk_widget_set_sensitive(app.cursor_theme_remove_btn, theme->is_removable);
90 }
91 }
92
93 static void on_cursor_theme_size_changed(GtkRange* range, gpointer user_data)
94 {
95 int size = (int)gtk_range_get_value(range);
96 if(size != app.cursor_theme_size)
97 {
98 app.cursor_theme_size = size;
99 g_object_set(gtk_settings_get_default(), "gtk-cursor-theme-size", size, NULL);
100
101 update_cursor_demo();
102 lxappearance_changed();
103 }
104 }
105
106 void cursor_theme_init(GtkBuilder* b)
107 {
108 guint max_cursor_w, max_cursor_h, max_size;
109 GtkTreeSelection* sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(app.cursor_theme_view));
110 /* treeview and model are already set up in icon_theme_init() */
111 g_signal_connect(sel, "changed", G_CALLBACK(on_cursor_theme_sel_changed), NULL);
112
113 gdk_display_get_maximal_cursor_size(gdk_display_get_default(), &max_cursor_w, &max_cursor_h);
114 max_size = MAX(max_cursor_w, max_cursor_h);
115
116 /* FIXME: this isn't fully working... */
117 app.cursor_size_range = GTK_WIDGET(gtk_builder_get_object(b, "cursor_size"));
118 if(max_size < 128)
119 gtk_range_set_range(GTK_RANGE(app.cursor_size_range), 1, max_size + 10); /* 10 is page size */
120 gtk_range_set_value(GTK_RANGE(app.cursor_size_range), app.cursor_theme_size);
121 g_signal_connect(app.cursor_size_range, "value-changed", G_CALLBACK(on_cursor_theme_size_changed), NULL);
122
123 /* set up demo for cursors */
124 app.cursor_demo_view = GTK_WIDGET(gtk_builder_get_object(b, "cursor_demo_view"));
125 gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(app.cursor_demo_view), 0);
126 update_cursor_demo();
127
128 /* install and remove */
129 /* this part is already done in icon-theme.c */
130 }