diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/libplybootsplash/ply-boot-splash.c | 10 | ||||
-rw-r--r-- | src/libplybootsplash/ply-console.c | 12 | ||||
-rw-r--r-- | src/libplybootsplash/ply-console.h | 4 | ||||
-rw-r--r-- | src/libplybootsplash/ply-renderer.c | 5 | ||||
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/plugins/renderers/Makefile.am | 2 | ||||
-rw-r--r-- | src/plugins/renderers/drm/plugin.c | 7 | ||||
-rw-r--r-- | src/plugins/renderers/frame-buffer/plugin.c | 7 | ||||
-rw-r--r-- | src/plugins/renderers/x11/Makefile.am | 20 | ||||
-rw-r--r-- | src/plugins/renderers/x11/plugin.c | 523 |
11 files changed, 576 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac index 318c80e2..e257b9d0 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -216,6 +216,7 @@ AC_OUTPUT([Makefile | |||
216 | src/plugins/renderers/Makefile | 216 | src/plugins/renderers/Makefile |
217 | src/plugins/renderers/frame-buffer/Makefile | 217 | src/plugins/renderers/frame-buffer/Makefile |
218 | src/plugins/renderers/drm/Makefile | 218 | src/plugins/renderers/drm/Makefile |
219 | src/plugins/renderers/x11/Makefile | ||
219 | src/plugins/splash/Makefile | 220 | src/plugins/splash/Makefile |
220 | src/plugins/splash/throbgress/Makefile | 221 | src/plugins/splash/throbgress/Makefile |
221 | src/plugins/splash/fade-throbber/Makefile | 222 | src/plugins/splash/fade-throbber/Makefile |
diff --git a/src/libplybootsplash/ply-boot-splash.c b/src/libplybootsplash/ply-boot-splash.c index 72ee7f02..5ba1bc1d 100644 --- a/src/libplybootsplash/ply-boot-splash.c +++ b/src/libplybootsplash/ply-boot-splash.c | |||
@@ -169,8 +169,14 @@ on_keyboard_input (ply_boot_splash_t *splash, | |||
169 | case KEY_CTRL_T: | 169 | case KEY_CTRL_T: |
170 | ply_trace ("toggle text mode!"); | 170 | ply_trace ("toggle text mode!"); |
171 | splash->should_force_text_mode = !splash->should_force_text_mode; | 171 | splash->should_force_text_mode = !splash->should_force_text_mode; |
172 | ply_console_force_text_mode (splash->console, | 172 | |
173 | splash->should_force_text_mode); | 173 | if (splash->should_force_text_mode) |
174 | { | ||
175 | ply_console_set_mode (splash->console, PLY_CONSOLE_MODE_TEXT); | ||
176 | ply_console_ignore_mode_changes (splash->console, true); | ||
177 | } | ||
178 | else | ||
179 | ply_console_ignore_mode_changes (splash->console, false); | ||
174 | ply_trace ("text mode toggled!"); | 180 | ply_trace ("text mode toggled!"); |
175 | return; | 181 | return; |
176 | 182 | ||
diff --git a/src/libplybootsplash/ply-console.c b/src/libplybootsplash/ply-console.c index 7fb92980..fb5a86db 100644 --- a/src/libplybootsplash/ply-console.c +++ b/src/libplybootsplash/ply-console.c | |||
@@ -68,7 +68,7 @@ struct _ply_console | |||
68 | 68 | ||
69 | uint32_t is_open : 1; | 69 | uint32_t is_open : 1; |
70 | uint32_t is_watching_for_vt_changes : 1; | 70 | uint32_t is_watching_for_vt_changes : 1; |
71 | uint32_t should_force_text_mode : 1; | 71 | uint32_t should_ignore_mode_changes : 1; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static bool ply_console_open_device (ply_console_t *console); | 74 | static bool ply_console_open_device (ply_console_t *console); |
@@ -106,8 +106,8 @@ ply_console_set_mode (ply_console_t *console, | |||
106 | assert (console != NULL); | 106 | assert (console != NULL); |
107 | assert (mode == PLY_CONSOLE_MODE_TEXT || mode == PLY_CONSOLE_MODE_GRAPHICS); | 107 | assert (mode == PLY_CONSOLE_MODE_TEXT || mode == PLY_CONSOLE_MODE_GRAPHICS); |
108 | 108 | ||
109 | if (console->should_force_text_mode) | 109 | if (console->should_ignore_mode_changes) |
110 | mode = PLY_CONSOLE_MODE_TEXT; | 110 | return; |
111 | 111 | ||
112 | switch (mode) | 112 | switch (mode) |
113 | { | 113 | { |
@@ -124,10 +124,10 @@ ply_console_set_mode (ply_console_t *console, | |||
124 | } | 124 | } |
125 | 125 | ||
126 | void | 126 | void |
127 | ply_console_force_text_mode (ply_console_t *console, | 127 | ply_console_ignore_mode_changes (ply_console_t *console, |
128 | bool should_force) | 128 | bool should_ignore) |
129 | { | 129 | { |
130 | console->should_force_text_mode = should_force; | 130 | console->should_ignore_mode_changes = should_ignore; |
131 | } | 131 | } |
132 | 132 | ||
133 | static void | 133 | static void |
diff --git a/src/libplybootsplash/ply-console.h b/src/libplybootsplash/ply-console.h index 36263bbc..4b45c86e 100644 --- a/src/libplybootsplash/ply-console.h +++ b/src/libplybootsplash/ply-console.h | |||
@@ -49,8 +49,8 @@ void ply_console_close (ply_console_t *console); | |||
49 | void ply_console_set_mode (ply_console_t *console, | 49 | void ply_console_set_mode (ply_console_t *console, |
50 | ply_console_mode_t mode); | 50 | ply_console_mode_t mode); |
51 | 51 | ||
52 | void ply_console_force_text_mode (ply_console_t *console, | 52 | void ply_console_ignore_mode_changes (ply_console_t *console, |
53 | bool should_force); | 53 | bool should_ignore); |
54 | 54 | ||
55 | int ply_console_get_fd (ply_console_t *console); | 55 | int ply_console_get_fd (ply_console_t *console); |
56 | int ply_console_get_active_vt (ply_console_t *console); | 56 | int ply_console_get_active_vt (ply_console_t *console); |
diff --git a/src/libplybootsplash/ply-renderer.c b/src/libplybootsplash/ply-renderer.c index 5410feb8..08a246ba 100644 --- a/src/libplybootsplash/ply-renderer.c +++ b/src/libplybootsplash/ply-renderer.c | |||
@@ -220,6 +220,7 @@ ply_renderer_open (ply_renderer_t *renderer) | |||
220 | */ | 220 | */ |
221 | const char *known_plugins[] = | 221 | const char *known_plugins[] = |
222 | { | 222 | { |
223 | PLYMOUTH_PLUGIN_PATH "renderers/x11.so", | ||
223 | PLYMOUTH_PLUGIN_PATH "renderers/drm.so", | 224 | PLYMOUTH_PLUGIN_PATH "renderers/drm.so", |
224 | PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", | 225 | PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", |
225 | NULL | 226 | NULL |
@@ -299,10 +300,6 @@ ply_renderer_flush_head (ply_renderer_t *renderer, | |||
299 | assert (renderer->plugin_interface != NULL); | 300 | assert (renderer->plugin_interface != NULL); |
300 | assert (head != NULL); | 301 | assert (head != NULL); |
301 | 302 | ||
302 | if (ply_console_get_active_vt (renderer->console) != | ||
303 | ply_terminal_get_vt_number (renderer->terminal)) | ||
304 | return; | ||
305 | |||
306 | renderer->plugin_interface->flush_head (renderer->backend, head); | 303 | renderer->plugin_interface->flush_head (renderer->backend, head); |
307 | } | 304 | } |
308 | 305 | ||
@@ -989,9 +989,6 @@ add_default_displays_and_keyboard (state_t *state) | |||
989 | return; | 989 | return; |
990 | } | 990 | } |
991 | 991 | ||
992 | ply_console_set_active_vt (state->console, | ||
993 | ply_terminal_get_vt_number (terminal)); | ||
994 | |||
995 | renderer = ply_renderer_new (NULL, terminal, state->console); | 992 | renderer = ply_renderer_new (NULL, terminal, state->console); |
996 | 993 | ||
997 | if (!ply_renderer_open (renderer)) | 994 | if (!ply_renderer_open (renderer)) |
diff --git a/src/plugins/renderers/Makefile.am b/src/plugins/renderers/Makefile.am index 2fadbf40..5a449a79 100644 --- a/src/plugins/renderers/Makefile.am +++ b/src/plugins/renderers/Makefile.am | |||
@@ -1,2 +1,2 @@ | |||
1 | SUBDIRS = frame-buffer drm | 1 | SUBDIRS = frame-buffer drm x11 |
2 | MAINTAINERCLEANFILES = Makefile.in | 2 | MAINTAINERCLEANFILES = Makefile.in |
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 2c5e1aa9..05e36fa2 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c | |||
@@ -783,6 +783,9 @@ map_to_device (ply_renderer_backend_t *backend) | |||
783 | node = next_node; | 783 | node = next_node; |
784 | } | 784 | } |
785 | 785 | ||
786 | ply_console_set_active_vt (backend->console, | ||
787 | ply_terminal_get_vt_number (backend->terminal)); | ||
788 | |||
786 | return head_mapped; | 789 | return head_mapped; |
787 | } | 790 | } |
788 | 791 | ||
@@ -922,6 +925,10 @@ flush_head (ply_renderer_backend_t *backend, | |||
922 | 925 | ||
923 | assert (backend != NULL); | 926 | assert (backend != NULL); |
924 | 927 | ||
928 | if (ply_console_get_active_vt (backend->console) != | ||
929 | ply_terminal_get_vt_number (backend->terminal)) | ||
930 | return; | ||
931 | |||
925 | ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); | 932 | ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); |
926 | ply_terminal_set_unbuffered_input (backend->terminal); | 933 | ply_terminal_set_unbuffered_input (backend->terminal); |
927 | pixel_buffer = head->pixel_buffer; | 934 | pixel_buffer = head->pixel_buffer; |
diff --git a/src/plugins/renderers/frame-buffer/plugin.c b/src/plugins/renderers/frame-buffer/plugin.c index 6f45b8f4..0163daa0 100644 --- a/src/plugins/renderers/frame-buffer/plugin.c +++ b/src/plugins/renderers/frame-buffer/plugin.c | |||
@@ -491,6 +491,9 @@ map_to_device (ply_renderer_backend_t *backend) | |||
491 | 491 | ||
492 | initialize_head (backend, head); | 492 | initialize_head (backend, head); |
493 | 493 | ||
494 | ply_console_set_active_vt (backend->console, | ||
495 | ply_terminal_get_vt_number (backend->terminal)); | ||
496 | |||
494 | return true; | 497 | return true; |
495 | } | 498 | } |
496 | 499 | ||
@@ -522,6 +525,10 @@ flush_head (ply_renderer_backend_t *backend, | |||
522 | assert (backend != NULL); | 525 | assert (backend != NULL); |
523 | assert (&backend->head == head); | 526 | assert (&backend->head == head); |
524 | 527 | ||
528 | if (ply_console_get_active_vt (backend->console) != | ||
529 | ply_terminal_get_vt_number (backend->terminal)) | ||
530 | return; | ||
531 | |||
525 | ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); | 532 | ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS); |
526 | ply_terminal_set_unbuffered_input (backend->terminal); | 533 | ply_terminal_set_unbuffered_input (backend->terminal); |
527 | pixel_buffer = head->pixel_buffer; | 534 | pixel_buffer = head->pixel_buffer; |
diff --git a/src/plugins/renderers/x11/Makefile.am b/src/plugins/renderers/x11/Makefile.am new file mode 100644 index 00000000..2bf85d27 --- /dev/null +++ b/src/plugins/renderers/x11/Makefile.am | |||
@@ -0,0 +1,20 @@ | |||
1 | INCLUDES = -I$(top_srcdir) \ | ||
2 | -I$(srcdir)/../../../libply \ | ||
3 | -I$(srcdir)/../../../libplybootsplash \ | ||
4 | -I$(srcdir)/../../.. \ | ||
5 | -I$(srcdir)/../.. \ | ||
6 | -I$(srcdir)/.. \ | ||
7 | -I$(srcdir) | ||
8 | |||
9 | plugindir = $(libdir)/plymouth/renderers | ||
10 | plugin_LTLIBRARIES = x11.la | ||
11 | |||
12 | x11_la_CFLAGS = $(GTK_CFLAGS) $(PLYMOUTH_CFLAGS) | ||
13 | x11_la_LDFLAGS = -module -avoid-version -export-dynamic | ||
14 | x11_la_LIBADD = $(PLYMOUTH_LIBS) \ | ||
15 | $(GTK_LIBS) \ | ||
16 | ../../../libply/libply.la \ | ||
17 | ../../../libplybootsplash/libplybootsplash.la | ||
18 | x11_la_SOURCES = $(srcdir)/plugin.c | ||
19 | |||
20 | MAINTAINERCLEANFILES = Makefile.in | ||
diff --git a/src/plugins/renderers/x11/plugin.c b/src/plugins/renderers/x11/plugin.c new file mode 100644 index 00000000..a2b61c0b --- /dev/null +++ b/src/plugins/renderers/x11/plugin.c | |||
@@ -0,0 +1,523 @@ | |||
1 | /* plugin.c - frame-backend renderer plugin | ||
2 | * | ||
3 | * Copyright (C) 2006-2009 Red Hat, Inc. | ||
4 | * 2009 Charlie Brej <cbrej@cs.man.ac.uk> | ||
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, or (at your option) | ||
9 | * 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., 59 Temple Place - Suite 330, Boston, MA | ||
19 | * 02111-1307, USA. | ||
20 | * | ||
21 | * Written by: Charlie Brej <cbrej@cs.man.ac.uk> | ||
22 | * Kristian Høgsberg <krh@redhat.com> | ||
23 | * Peter Jones <pjones@redhat.com> | ||
24 | * Ray Strode <rstrode@redhat.com> | ||
25 | */ | ||
26 | #include "config.h" | ||
27 | |||
28 | #include <arpa/inet.h> | ||
29 | #include <assert.h> | ||
30 | #include <errno.h> | ||
31 | #include <fcntl.h> | ||
32 | #include <signal.h> | ||
33 | #include <string.h> | ||
34 | #include <stdbool.h> | ||
35 | #include <stdint.h> | ||
36 | #include <stdio.h> | ||
37 | #include <stdlib.h> | ||
38 | #include <sys/ioctl.h> | ||
39 | #include <sys/mman.h> | ||
40 | #include <sys/stat.h> | ||
41 | #include <sys/types.h> | ||
42 | #include <sys/ipc.h> | ||
43 | #include <sys/shm.h> | ||
44 | |||
45 | #include <values.h> | ||
46 | #include <unistd.h> | ||
47 | |||
48 | #include <linux/fb.h> | ||
49 | #include <gtk/gtk.h> | ||
50 | #include <gdk/gdkkeysyms.h> | ||
51 | #include <gdk/gdkx.h> | ||
52 | |||
53 | #include "ply-buffer.h" | ||
54 | #include "ply-event-loop.h" | ||
55 | #include "ply-list.h" | ||
56 | #include "ply-logger.h" | ||
57 | #include "ply-rectangle.h" | ||
58 | #include "ply-region.h" | ||
59 | #include "ply-terminal.h" | ||
60 | |||
61 | #include "ply-renderer.h" | ||
62 | #include "ply-renderer-plugin.h" | ||
63 | |||
64 | struct _ply_renderer_head | ||
65 | { | ||
66 | ply_renderer_backend_t *backend; | ||
67 | ply_pixel_buffer_t *pixel_buffer; | ||
68 | ply_rectangle_t area; | ||
69 | GtkWidget *window; | ||
70 | GdkPixmap *pixmap; | ||
71 | cairo_surface_t *image; | ||
72 | }; | ||
73 | |||
74 | struct _ply_renderer_input_source | ||
75 | { | ||
76 | ply_buffer_t *key_buffer; | ||
77 | ply_renderer_input_source_handler_t handler; | ||
78 | void *user_data; | ||
79 | }; | ||
80 | |||
81 | struct _ply_renderer_backend | ||
82 | { | ||
83 | ply_event_loop_t *loop; | ||
84 | ply_renderer_input_source_t input_source; | ||
85 | ply_list_t *heads; | ||
86 | ply_console_t *console; | ||
87 | |||
88 | ply_fd_watch_t *display_watch; | ||
89 | }; | ||
90 | |||
91 | ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void); | ||
92 | static void ply_renderer_head_redraw (ply_renderer_backend_t *backend, | ||
93 | ply_renderer_head_t *head); | ||
94 | |||
95 | static gboolean on_motion_notify_event (GtkWidget *widget, | ||
96 | GdkEventMotion *event, | ||
97 | gpointer user_data); | ||
98 | static gboolean on_key_event (GtkWidget *widget, | ||
99 | GdkEventKey *event, | ||
100 | gpointer user_data); | ||
101 | |||
102 | static ply_renderer_backend_t * | ||
103 | create_backend (const char *device_name, | ||
104 | ply_terminal_t *terminal, | ||
105 | ply_console_t *console) | ||
106 | { | ||
107 | ply_renderer_backend_t *backend; | ||
108 | |||
109 | backend = calloc (1, sizeof (ply_renderer_backend_t)); | ||
110 | |||
111 | backend->loop = ply_event_loop_get_default (); | ||
112 | backend->heads = ply_list_new (); | ||
113 | backend->input_source.key_buffer = ply_buffer_new (); | ||
114 | backend->console = console; | ||
115 | |||
116 | return backend; | ||
117 | } | ||
118 | |||
119 | static void | ||
120 | destroy_backend (ply_renderer_backend_t *backend) | ||
121 | { | ||
122 | ply_list_node_t *node; | ||
123 | node = ply_list_get_first_node (backend->heads); | ||
124 | while (node != NULL) | ||
125 | { | ||
126 | ply_list_node_t *next_node; | ||
127 | ply_renderer_head_t *head; | ||
128 | |||
129 | head = (ply_renderer_head_t *) ply_list_node_get_data (node); | ||
130 | next_node = ply_list_get_next_node (backend->heads, node); | ||
131 | |||
132 | free (head); | ||
133 | node = next_node; | ||
134 | } | ||
135 | |||
136 | ply_list_free (backend->heads); | ||
137 | ply_buffer_free (backend->input_source.key_buffer); | ||
138 | free (backend); | ||
139 | } | ||
140 | |||
141 | static void | ||
142 | on_display_event (ply_renderer_backend_t *backend) | ||
143 | { | ||
144 | while (gtk_events_pending ()) | ||
145 | gtk_main_iteration (); | ||
146 | } | ||
147 | |||
148 | static bool | ||
149 | open_device (ply_renderer_backend_t *backend) | ||
150 | { | ||
151 | Display *display; | ||
152 | int display_fd; | ||
153 | |||
154 | if (!gtk_init_check (0, NULL)) | ||
155 | return false; | ||
156 | |||
157 | display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); | ||
158 | display_fd = ConnectionNumber (display); | ||
159 | backend->display_watch = ply_event_loop_watch_fd (backend->loop, | ||
160 | display_fd, | ||
161 | PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, | ||
162 | (ply_event_handler_t) on_display_event, | ||
163 | NULL, | ||
164 | backend); | ||
165 | |||
166 | return true; | ||
167 | } | ||
168 | |||
169 | static void | ||
170 | close_device (ply_renderer_backend_t *backend) | ||
171 | { | ||
172 | ply_event_loop_stop_watching_fd (backend->loop, backend->display_watch); | ||
173 | backend->display_watch = NULL; | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | static bool | ||
178 | query_device (ply_renderer_backend_t *backend) | ||
179 | { | ||
180 | ply_renderer_head_t *head; | ||
181 | assert (backend != NULL); | ||
182 | |||
183 | if (ply_list_get_first_node (backend->heads) == NULL) | ||
184 | { | ||
185 | head = calloc (1, sizeof (ply_renderer_head_t)); | ||
186 | |||
187 | head->backend = backend; | ||
188 | head->area.x = 0; | ||
189 | head->area.y = 0; | ||
190 | head->area.width = 800; /* FIXME hardcoded */ | ||
191 | head->area.height = 600; | ||
192 | head->pixmap = gdk_pixmap_new (NULL, | ||
193 | head->area.width, | ||
194 | head->area.height, | ||
195 | 24); | ||
196 | |||
197 | ply_list_append_data (backend->heads, head); | ||
198 | |||
199 | head = calloc (1, sizeof (ply_renderer_head_t)); | ||
200 | |||
201 | head->backend = backend; | ||
202 | head->area.x = 800; | ||
203 | head->area.y = 0; | ||
204 | head->area.width = 640; /* FIXME hardcoded */ | ||
205 | head->area.height = 480; | ||
206 | head->pixmap = gdk_pixmap_new (NULL, | ||
207 | head->area.width, | ||
208 | head->area.height, | ||
209 | 24); | ||
210 | |||
211 | ply_list_append_data (backend->heads, head); | ||
212 | } | ||
213 | |||
214 | return true; | ||
215 | } | ||
216 | |||
217 | static gboolean | ||
218 | on_window_destroy (GtkWidget *widget, | ||
219 | GdkEvent *event, | ||
220 | gpointer user_data) | ||
221 | { | ||
222 | return TRUE; | ||
223 | } | ||
224 | |||
225 | static bool | ||
226 | map_to_device (ply_renderer_backend_t *backend) | ||
227 | { | ||
228 | ply_list_node_t *node; | ||
229 | assert (backend != NULL); | ||
230 | |||
231 | /* Prevent other parts of plymouth from trying to use | ||
232 | * the console, since X draws to it. | ||
233 | */ | ||
234 | ply_console_ignore_mode_changes (backend->console, true); | ||
235 | |||
236 | node = ply_list_get_first_node (backend->heads); | ||
237 | while (node != NULL) | ||
238 | { | ||
239 | ply_list_node_t *next_node; | ||
240 | ply_renderer_head_t *head; | ||
241 | uint32_t *shadow_buffer; | ||
242 | |||
243 | head = (ply_renderer_head_t *) ply_list_node_get_data (node); | ||
244 | next_node = ply_list_get_next_node (backend->heads, node); | ||
245 | |||
246 | head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height); | ||
247 | head->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | ||
248 | gtk_window_set_resizable (GTK_WINDOW (head->window), FALSE); | ||
249 | gtk_widget_set_size_request (head->window, | ||
250 | head->area.width, | ||
251 | head->area.height); | ||
252 | shadow_buffer = ply_pixel_buffer_get_argb32_data (head->pixel_buffer); | ||
253 | head->image = cairo_image_surface_create_for_data ((unsigned char *) shadow_buffer, | ||
254 | CAIRO_FORMAT_ARGB32, | ||
255 | head->area.width, head->area.height, | ||
256 | head->area.width * 4); | ||
257 | gtk_widget_set_app_paintable (head->window, TRUE); | ||
258 | gtk_widget_show_all (head->window); | ||
259 | gdk_window_set_back_pixmap (head->window->window, head->pixmap, FALSE); | ||
260 | gdk_window_set_decorations (head->window->window, GDK_DECOR_BORDER); | ||
261 | gtk_window_move (GTK_WINDOW (head->window), head->area.x, head->area.y); | ||
262 | |||
263 | gtk_widget_add_events (head->window, GDK_BUTTON1_MOTION_MASK); | ||
264 | |||
265 | g_signal_connect (head->window, "motion-notify-event", | ||
266 | G_CALLBACK (on_motion_notify_event), | ||
267 | head); | ||
268 | g_signal_connect (head->window, "key-press-event", | ||
269 | G_CALLBACK (on_key_event), | ||
270 | &backend->input_source); | ||
271 | g_signal_connect (head->window, "delete-event", | ||
272 | G_CALLBACK (on_window_destroy), | ||
273 | NULL); | ||
274 | |||
275 | ply_renderer_head_redraw (backend, head); | ||
276 | node = next_node; | ||
277 | } | ||
278 | return true; | ||
279 | } | ||
280 | |||
281 | static void | ||
282 | unmap_from_device (ply_renderer_backend_t *backend) | ||
283 | { | ||
284 | ply_list_node_t *node; | ||
285 | assert (backend != NULL); | ||
286 | |||
287 | node = ply_list_get_first_node (backend->heads); | ||
288 | while (node != NULL) | ||
289 | { | ||
290 | ply_list_node_t *next_node; | ||
291 | ply_renderer_head_t *head; | ||
292 | |||
293 | head = (ply_renderer_head_t *) ply_list_node_get_data (node); | ||
294 | next_node = ply_list_get_next_node (backend->heads, node); | ||
295 | |||
296 | gtk_widget_destroy (head->window); | ||
297 | head->window = NULL; | ||
298 | ply_pixel_buffer_free (head->pixel_buffer); | ||
299 | head->pixel_buffer = NULL; | ||
300 | cairo_surface_destroy (head->image); | ||
301 | head->image = NULL; | ||
302 | |||
303 | node = next_node; | ||
304 | } | ||
305 | |||
306 | ply_console_ignore_mode_changes (backend->console, false); | ||
307 | } | ||
308 | |||
309 | static void | ||
310 | flush_area_to_device (ply_renderer_backend_t *backend, | ||
311 | ply_renderer_head_t *head, | ||
312 | ply_rectangle_t *area_to_flush, | ||
313 | cairo_t *cr) | ||
314 | { | ||
315 | cairo_save (cr); | ||
316 | cairo_rectangle (cr, | ||
317 | area_to_flush->x, | ||
318 | area_to_flush->y, | ||
319 | area_to_flush->width, | ||
320 | area_to_flush->height); | ||
321 | cairo_clip (cr); | ||
322 | |||
323 | cairo_set_source_surface (cr, head->image, 0, 0); | ||
324 | cairo_paint (cr); | ||
325 | cairo_restore (cr); | ||
326 | } | ||
327 | |||
328 | static void | ||
329 | flush_head (ply_renderer_backend_t *backend, | ||
330 | ply_renderer_head_t *head) | ||
331 | { | ||
332 | ply_region_t *updated_region; | ||
333 | ply_list_t *areas_to_flush; | ||
334 | ply_list_node_t *node; | ||
335 | ply_pixel_buffer_t *pixel_buffer; | ||
336 | cairo_t *cr; | ||
337 | |||
338 | assert (backend != NULL); | ||
339 | |||
340 | pixel_buffer = head->pixel_buffer; | ||
341 | updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer); | ||
342 | areas_to_flush = ply_region_get_rectangle_list (updated_region); | ||
343 | |||
344 | cr = gdk_cairo_create (head->pixmap); | ||
345 | |||
346 | node = ply_list_get_first_node (areas_to_flush); | ||
347 | while (node != NULL) | ||
348 | { | ||
349 | ply_list_node_t *next_node; | ||
350 | ply_rectangle_t *area_to_flush; | ||
351 | |||
352 | area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node); | ||
353 | |||
354 | next_node = ply_list_get_next_node (areas_to_flush, node); | ||
355 | |||
356 | flush_area_to_device (backend, head, area_to_flush, cr); | ||
357 | gdk_window_clear_area (head->window->window, | ||
358 | area_to_flush->x, | ||
359 | area_to_flush->y, | ||
360 | area_to_flush->width, | ||
361 | area_to_flush->height); | ||
362 | node = next_node; | ||
363 | } | ||
364 | ply_region_clear (updated_region); | ||
365 | |||
366 | cairo_destroy (cr); | ||
367 | |||
368 | /* Force read-back to make sure plymouth isn't saturating the | ||
369 | * X server with requests | ||
370 | */ | ||
371 | g_object_unref (gdk_drawable_get_image (GDK_DRAWABLE (head->pixmap), | ||
372 | 0, 0, 1, 1)); | ||
373 | } | ||
374 | |||
375 | static void | ||
376 | ply_renderer_head_redraw (ply_renderer_backend_t *backend, | ||
377 | ply_renderer_head_t *head) | ||
378 | { | ||
379 | ply_region_t *region; | ||
380 | |||
381 | region = ply_pixel_buffer_get_updated_areas (head->pixel_buffer); | ||
382 | |||
383 | ply_region_add_rectangle (region, &head->area); | ||
384 | |||
385 | flush_head (backend, head); | ||
386 | } | ||
387 | |||
388 | static ply_list_t * | ||
389 | get_heads (ply_renderer_backend_t *backend) | ||
390 | { | ||
391 | return backend->heads; | ||
392 | } | ||
393 | |||
394 | static ply_pixel_buffer_t * | ||
395 | get_buffer_for_head (ply_renderer_backend_t *backend, | ||
396 | ply_renderer_head_t *head) | ||
397 | { | ||
398 | if (head->backend != backend) | ||
399 | return NULL; | ||
400 | |||
401 | return head->pixel_buffer; | ||
402 | } | ||
403 | |||
404 | static bool | ||
405 | has_input_source (ply_renderer_backend_t *backend, | ||
406 | ply_renderer_input_source_t *input_source) | ||
407 | { | ||
408 | return input_source == &backend->input_source; | ||
409 | } | ||
410 | |||
411 | static ply_renderer_input_source_t * | ||
412 | get_input_source (ply_renderer_backend_t *backend) | ||
413 | { | ||
414 | return &backend->input_source; | ||
415 | } | ||
416 | |||
417 | static gboolean | ||
418 | on_motion_notify_event (GtkWidget *widget, | ||
419 | GdkEventMotion *event, | ||
420 | gpointer user_data) | ||
421 | { | ||
422 | ply_renderer_head_t *head = user_data; | ||
423 | |||
424 | gtk_window_begin_move_drag (GTK_WINDOW (head->window), 1, | ||
425 | event->x_root, event->y_root, event->time); | ||
426 | return FALSE; | ||
427 | } | ||
428 | |||
429 | static gboolean | ||
430 | on_key_event (GtkWidget *widget, | ||
431 | GdkEventKey *event, | ||
432 | gpointer user_data) | ||
433 | { | ||
434 | ply_renderer_input_source_t *input_source = user_data; | ||
435 | |||
436 | if (event->keyval == GDK_Return) /* Enter */ | ||
437 | { | ||
438 | ply_buffer_append_bytes (input_source->key_buffer, "\r", 1); | ||
439 | } | ||
440 | else if (event->keyval == GDK_Escape) /* Esc */ | ||
441 | { | ||
442 | ply_buffer_append_bytes (input_source->key_buffer, "\033", 1); | ||
443 | } | ||
444 | else if (event->keyval == GDK_BackSpace) /* Backspace */ | ||
445 | { | ||
446 | ply_buffer_append_bytes (input_source->key_buffer, "\177", 1); | ||
447 | } | ||
448 | else | ||
449 | { | ||
450 | gchar bytes[7]; | ||
451 | int byte_count; | ||
452 | guint32 unichar; | ||
453 | unichar = gdk_keyval_to_unicode (event->keyval); | ||
454 | byte_count = g_unichar_to_utf8 (unichar, bytes); | ||
455 | if (bytes[0] != 0) | ||
456 | ply_buffer_append_bytes (input_source->key_buffer, bytes, byte_count); | ||
457 | else | ||
458 | ply_trace ("unknown GDK key: 0x%X \"%s\"", | ||
459 | event->keyval, | ||
460 | gdk_keyval_name (event->keyval)); | ||
461 | } | ||
462 | |||
463 | if (input_source->handler != NULL) | ||
464 | input_source->handler (input_source->user_data, input_source->key_buffer, input_source); | ||
465 | return FALSE; | ||
466 | } | ||
467 | |||
468 | static bool | ||
469 | open_input_source (ply_renderer_backend_t *backend, | ||
470 | ply_renderer_input_source_t *input_source) | ||
471 | { | ||
472 | |||
473 | assert (backend != NULL); | ||
474 | assert (has_input_source (backend, input_source)); | ||
475 | |||
476 | return true; | ||
477 | } | ||
478 | |||
479 | static void | ||
480 | set_handler_for_input_source (ply_renderer_backend_t *backend, | ||
481 | ply_renderer_input_source_t *input_source, | ||
482 | ply_renderer_input_source_handler_t handler, | ||
483 | void *user_data) | ||
484 | { | ||
485 | assert (backend != NULL); | ||
486 | assert (has_input_source (backend, input_source)); | ||
487 | |||
488 | input_source->handler = handler; | ||
489 | input_source->user_data = user_data; | ||
490 | } | ||
491 | |||
492 | static void | ||
493 | close_input_source (ply_renderer_backend_t *backend, | ||
494 | ply_renderer_input_source_t *input_source) | ||
495 | { | ||
496 | assert (backend != NULL); | ||
497 | assert (has_input_source (backend, input_source)); | ||
498 | } | ||
499 | |||
500 | ply_renderer_plugin_interface_t * | ||
501 | ply_renderer_backend_get_interface (void) | ||
502 | { | ||
503 | static ply_renderer_plugin_interface_t plugin_interface = | ||
504 | { | ||
505 | .create_backend = create_backend, | ||
506 | .destroy_backend = destroy_backend, | ||
507 | .open_device = open_device, | ||
508 | .close_device = close_device, | ||
509 | .query_device = query_device, | ||
510 | .map_to_device = map_to_device, | ||
511 | .unmap_from_device = unmap_from_device, | ||
512 | .flush_head = flush_head, | ||
513 | .get_heads = get_heads, | ||
514 | .get_buffer_for_head = get_buffer_for_head, | ||
515 | .get_input_source = get_input_source, | ||
516 | .open_input_source = open_input_source, | ||
517 | .set_handler_for_input_source = set_handler_for_input_source, | ||
518 | .close_input_source = close_input_source | ||
519 | }; | ||
520 | return &plugin_interface; | ||
521 | } | ||
522 | |||
523 | /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ | ||