summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2009-10-04 10:47:36 -0400
committerRay Strode <rstrode@redhat.com>2009-10-04 10:47:36 -0400
commita29f25bc6c67e87f38f323e8739f06249205d766 (patch)
tree6d648dbcc6f144e3d3436bc77436f629341cde90
parente73e8cadd6b2b28e448710cffd85e32eb2083c83 (diff)
parent08466deaf8203ddff508d492056d2e9f705724e9 (diff)
[branch-merge] Add x11 renderer plugin
This merges the "x11-renderer" branch to master. In order to make debugging splash plugins easier, and in order to make debugging multi-head renderering possible on single head displays, Charlie wrote an X11 rendering plugin. This plugin displays plymouth in a running X session, instead of on the console. It currently only supports graphical plugins. At some point it may grow support for text plugins, too, using vte. That will take some reworking of the plymouth daemon core. This could some day serve as a basis for providing a graphical theme chooser application (like gnome-screensaver-preferences), although it's not clear yet that's a good idea. Right now, it's a great debugging and development tool, though.
-rw-r--r--configure.ac1
-rw-r--r--src/libplybootsplash/ply-boot-splash.c10
-rw-r--r--src/libplybootsplash/ply-console.c12
-rw-r--r--src/libplybootsplash/ply-console.h4
-rw-r--r--src/libplybootsplash/ply-renderer.c5
-rw-r--r--src/main.c3
-rw-r--r--src/plugins/renderers/Makefile.am2
-rw-r--r--src/plugins/renderers/drm/plugin.c7
-rw-r--r--src/plugins/renderers/frame-buffer/plugin.c7
-rw-r--r--src/plugins/renderers/x11/Makefile.am20
-rw-r--r--src/plugins/renderers/x11/plugin.c523
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
74static bool ply_console_open_device (ply_console_t *console); 74static 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
126void 126void
127ply_console_force_text_mode (ply_console_t *console, 127ply_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
133static void 133static 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);
49void ply_console_set_mode (ply_console_t *console, 49void ply_console_set_mode (ply_console_t *console,
50 ply_console_mode_t mode); 50 ply_console_mode_t mode);
51 51
52void ply_console_force_text_mode (ply_console_t *console, 52void ply_console_ignore_mode_changes (ply_console_t *console,
53 bool should_force); 53 bool should_ignore);
54 54
55int ply_console_get_fd (ply_console_t *console); 55int ply_console_get_fd (ply_console_t *console);
56int ply_console_get_active_vt (ply_console_t *console); 56int 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
diff --git a/src/main.c b/src/main.c
index d79b816e..08ec1ae4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 @@
1SUBDIRS = frame-buffer drm 1SUBDIRS = frame-buffer drm x11
2MAINTAINERCLEANFILES = Makefile.in 2MAINTAINERCLEANFILES = 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 @@
1INCLUDES = -I$(top_srcdir) \
2 -I$(srcdir)/../../../libply \
3 -I$(srcdir)/../../../libplybootsplash \
4 -I$(srcdir)/../../.. \
5 -I$(srcdir)/../.. \
6 -I$(srcdir)/.. \
7 -I$(srcdir)
8
9plugindir = $(libdir)/plymouth/renderers
10plugin_LTLIBRARIES = x11.la
11
12x11_la_CFLAGS = $(GTK_CFLAGS) $(PLYMOUTH_CFLAGS)
13x11_la_LDFLAGS = -module -avoid-version -export-dynamic
14x11_la_LIBADD = $(PLYMOUTH_LIBS) \
15 $(GTK_LIBS) \
16 ../../../libply/libply.la \
17 ../../../libplybootsplash/libplybootsplash.la
18x11_la_SOURCES = $(srcdir)/plugin.c
19
20MAINTAINERCLEANFILES = 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
64struct _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
74struct _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
81struct _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
91ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
92static void ply_renderer_head_redraw (ply_renderer_backend_t *backend,
93 ply_renderer_head_t *head);
94
95static gboolean on_motion_notify_event (GtkWidget *widget,
96 GdkEventMotion *event,
97 gpointer user_data);
98static gboolean on_key_event (GtkWidget *widget,
99 GdkEventKey *event,
100 gpointer user_data);
101
102static ply_renderer_backend_t *
103create_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
119static void
120destroy_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
141static void
142on_display_event (ply_renderer_backend_t *backend)
143{
144 while (gtk_events_pending ())
145 gtk_main_iteration ();
146}
147
148static bool
149open_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
169static void
170close_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
177static bool
178query_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
217static gboolean
218on_window_destroy (GtkWidget *widget,
219 GdkEvent *event,
220 gpointer user_data)
221{
222 return TRUE;
223}
224
225static bool
226map_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
281static void
282unmap_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
309static void
310flush_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
328static void
329flush_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
375static void
376ply_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
388static ply_list_t *
389get_heads (ply_renderer_backend_t *backend)
390{
391 return backend->heads;
392}
393
394static ply_pixel_buffer_t *
395get_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
404static bool
405has_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
411static ply_renderer_input_source_t *
412get_input_source (ply_renderer_backend_t *backend)
413{
414 return &backend->input_source;
415}
416
417static gboolean
418on_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
429static gboolean
430on_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
468static bool
469open_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
479static void
480set_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
492static void
493close_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
500ply_renderer_plugin_interface_t *
501ply_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 */