16
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
/* $Id: fullscreen.c,v 1.42 2005/02/12 13:37:07 mschimek Exp $ */
20
22
* Fullscreen mode handling
21
* $Id: fullscreen.c,v 1.21 2002/03/21 18:08:23 mschimek Exp $
24
* I wonder if we shouldn't simply switch the main window to
24
28
#ifdef HAVE_CONFIG_H
28
32
#include <gtk/gtk.h>
29
33
#include <gdk/gdkx.h>
34
#define ZCONF_DOMAIN "/zapping/options/main/"
32
38
#include "x11stuff.h"
33
#define ZCONF_DOMAIN "/zapping/options/main/"
36
39
#include "interface.h"
37
#include "callbacks.h"
38
40
#include "v4linterface.h"
39
41
#include "fullscreen.h"
41
43
#include "plugins.h"
43
static GtkWidget * black_window = NULL; /* The black window when you go
45
extern GtkWidget * main_window;
47
extern tveng_tuned_channel *global_channel_list;
49
extern enum tveng_capture_mode last_mode;
51
extern tveng_device_info *main_info;
53
/* Comment out the next line if you don't want to mess with the
55
#define MESS_WITH_XSS 1
58
on_fullscreen_event (GtkWidget * widget,
62
GtkWidget * window = GTK_WIDGET(user_data);
63
GtkMenuItem * exit2 = GTK_MENU_ITEM(lookup_widget(window, "quit1"));
65
if (event->type == GDK_KEY_PRESS)
67
GdkEventKey *kevent = (GdkEventKey *) event;
69
if (kevent->keyval == GDK_q && (kevent->state & GDK_CONTROL_MASK))
71
extern gboolean was_fullscreen;
73
was_fullscreen = TRUE;
74
zmisc_switch_mode(last_mode, main_info);
75
cmd_execute (GTK_WIDGET (exit2), "quit");
81
return on_user_key_press (widget, kevent, user_data)
82
|| on_channel_key_press (widget, kevent, user_data);
85
else if (event->type == GDK_BUTTON_PRESS)
87
zmisc_switch_mode(last_mode, main_info);
91
return FALSE; /* We aren't interested in this event, pass it on */
48
extern gboolean was_fullscreen;
50
static x11_vidmode_info * svidmodes;
51
static GtkWidget * drawing_area;
52
static GtkWidget * black_window; /* The black window when you go
54
static x11_vidmode_state old_vidmode;
55
static const tv_screen * screen;
61
on_key_press (GtkWidget * widget,
64
if (GDK_q == event->keyval
65
&& (event->state & GDK_CONTROL_MASK))
67
was_fullscreen = TRUE;
69
python_command (widget, "zapping.switch_mode('window'); zapping.quit()");
73
else if (GDK_Escape == event->keyval)
75
python_command (widget, "zapping.switch_mode('window')");
81
if (CAPTURE_MODE_TELETEXT == tv_get_capture_mode (zapping->info))
85
view = (TeletextView *) drawing_area;
86
if (view->key_press (view, event))
91
return on_user_key_press (widget, event, NULL)
92
|| on_channel_key_press (widget, event, NULL);
96
on_button_press (GtkWidget * widget,
97
GdkEventButton * event)
99
switch (event->button)
101
case 2: /* Middle button */
102
python_command (widget, "zapping.switch_mode('window')");
103
return TRUE; /* handled */
105
case 3: /* Right button */
106
zapping_create_popup (zapping, event);
107
return TRUE; /* handled */
113
return FALSE; /* pass on */
117
on_scroll_event (GtkWidget * widget,
118
GdkEventScroll * event)
120
switch (event->direction)
123
case GDK_SCROLL_LEFT:
124
python_command (widget, "zapping.channel_up()");
125
return TRUE; /* handled */
127
case GDK_SCROLL_DOWN:
128
case GDK_SCROLL_RIGHT:
129
python_command (widget, "zapping.channel_down()");
130
return TRUE; /* handled */
136
return FALSE; /* pass on */
94
139
/* Called when OSD changes the geometry of the pieces */
96
osd_model_changed (ZModel *ignored1,
141
osd_model_changed (ZModel * ignored1 _unused_,
97
142
tveng_device_info *info)
99
struct tveng_window window;
100
struct tveng_clip *clips;
145
tv_clip_vector clip_vector;
146
GdkWindow *gdk_window;
102
if (info->current_controller == TVENG_CONTROLLER_XV ||
148
if (tv_get_controller (info) == TVENG_CONTROLLER_XV ||
103
149
!black_window || !black_window->window)
106
/* save for later use */
107
memcpy(&window, &info->window, sizeof(struct tveng_window));
109
tveng_set_preview_off(info);
110
memcpy(&info->window, &window, sizeof(struct tveng_window));
111
clips = info->window.clips =
112
x11_get_clips(GTK_BIN(black_window)->child->window,
117
info->window.clipcount = window.clipcount;
118
tveng_set_preview_window(info);
119
tveng_set_preview_on(info);
125
fullscreen_start(tveng_device_info * info)
127
GtkWidget * da; /* Drawing area */
128
GdkColor chroma = {0, 0, 0, 0};
130
/* Add a black background */
131
black_window = gtk_window_new( GTK_WINDOW_POPUP );
132
da = gtk_fixed_new();
136
gtk_container_add(GTK_CONTAINER(black_window), da);
137
gtk_widget_set_usize(black_window, gdk_screen_width(),
138
gdk_screen_height());
140
gtk_widget_realize(black_window);
141
gtk_widget_realize(da);
142
gdk_window_set_events(black_window->window, GDK_ALL_EVENTS_MASK);
143
gdk_window_set_events(da->window, GDK_ALL_EVENTS_MASK);
144
gtk_window_set_modal(GTK_WINDOW(black_window), TRUE);
145
gdk_window_set_decorations(black_window->window, 0);
147
/* hide the cursor in fullscreen mode */
148
z_set_cursor(da->window, 0);
150
if (info->current_controller != TVENG_CONTROLLER_XV &&
151
(info->caps.flags & TVENG_CAPS_CHROMAKEY))
153
chroma.red = chroma.green = 0;
154
chroma.blue = 0xffff;
156
if (gdk_colormap_alloc_color(gdk_colormap_get_system(), &chroma,
158
tveng_set_chromakey(chroma.red >> 8, chroma.green >> 8,
159
chroma.blue >> 8, info);
161
ShowBox("Couldn't allocate chromakey, chroma won't work",
162
GNOME_MESSAGE_BOX_WARNING);
165
gdk_window_set_background(da->window, &chroma);
167
if (chroma.pixel != 0)
168
gdk_colormap_free_colors(gdk_colormap_get_system(), &chroma,
171
/* Needed for XV fullscreen */
172
info->window.win = GDK_WINDOW_XWINDOW(da->window);
173
info->window.gc = GDK_GC_XGC(da->style->white_gc);
175
if (tveng_start_previewing(info, 1-zcg_int(NULL, "change_mode")) == -1)
177
ShowBox(_("Sorry, but cannot go fullscreen:\n%s"),
178
GNOME_MESSAGE_BOX_ERROR, info->error);
179
gtk_widget_destroy(black_window);
180
zmisc_switch_mode(TVENG_CAPTURE_READ, info);
184
gtk_widget_show(black_window);
186
if (info -> current_mode != TVENG_CAPTURE_PREVIEW)
187
g_warning("Setting preview succeeded, but the mode is not set");
190
/* Set the blank screensaver */
191
x11_set_screensaver(OFF);
194
gtk_widget_grab_focus(black_window);
196
gtk_signal_connect(GTK_OBJECT(black_window), "event",
197
GTK_SIGNAL_FUNC(on_fullscreen_event),
200
if (info->current_controller != TVENG_CONTROLLER_XV)
202
info->window.x, info->window.y, info->window.width,
203
info->window.height);
205
osd_set_coords(da, 0, 0, info->window.width,
206
info->window.height);
208
gtk_signal_connect(GTK_OBJECT(osd_model), "changed",
209
GTK_SIGNAL_FUNC(osd_model_changed), info);
216
fullscreen_stop(tveng_device_info * info)
219
/* Restore the normal screensaver */
220
x11_set_screensaver(ON);
152
tv_enable_overlay (info, FALSE);
154
tv_clip_vector_init (&clip_vector);
156
gdk_window = GTK_BIN (black_window)->child->window;
158
w = tv_cur_overlay_window (info);
160
x11_window_clip_vector (&clip_vector,
161
GDK_WINDOW_XDISPLAY (gdk_window),
162
GDK_WINDOW_XID (gdk_window),
168
tv_set_overlay_window_clipvec (info, w, &clip_vector);
170
tv_clip_vector_destroy (&clip_vector);
172
tv_enable_overlay (info, TRUE);
176
on_cursor_blanked (ZVideo * video _unused_,
177
gpointer user_data _unused_)
179
/* Recenter the viewport */
180
x11_vidmode_switch (svidmodes, screens, NULL, NULL);
184
set_blank_timeout (ZVideo * video)
188
timeout = 0; /* disabled */
189
z_gconf_get_int (&timeout, "/apps/zapping/blank_cursor_timeout");
191
z_video_blank_cursor (video, timeout);
194
static const x11_vidmode_info *
195
find_vidmode (const x11_vidmode_info *vidmodes,
199
const x11_vidmode_info *v;
200
const x11_vidmode_info *vmin;
204
amin = ((gint64) 1) << 62;
206
for (v = vidmodes; v; v = v->next)
212
fprintf (stderr, "width=%d height=%d cur %ux%u@%u best %ux%u@%u\n",
214
v->width, v->height, (guint)(v->vfreq + 0.5),
215
vmin->width, vmin->height, (guint)(vmin->vfreq + 0.5));
218
dw = (gint64) v->width - width;
219
dh = (gint64) v->height - height;
220
a = dw * dw + dh * dh;
223
|| (a == amin && v->vfreq > vmin->vfreq))
233
fprintf (stderr, "Using mode %ux%u@%u for video %ux%u\n",
234
v->width, v->height, (guint)(v->vfreq + 0.5),
240
static const tv_screen *
250
window = GTK_WIDGET (zapping)->window;
252
/* Root window relative position. */
253
gdk_window_get_origin (window, &x, &y);
255
gdk_window_get_geometry (window,
262
xs = tv_screen_list_find (screens,
273
stop_fullscreen (void)
275
g_assert (DISPLAY_MODE_FULLSCREEN == zapping->display_mode
276
|| DISPLAY_MODE_BACKGROUND == zapping->display_mode);
278
switch (tv_get_capture_mode (zapping->info))
280
case CAPTURE_MODE_OVERLAY:
282
tv_enable_overlay (zapping->info, FALSE);
284
g_signal_handlers_disconnect_matched
285
(G_OBJECT (osd_model), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
286
0, 0, NULL, G_CALLBACK (osd_model_changed), zapping->info);
290
case CAPTURE_MODE_READ:
291
if (!capture_stop ())
295
case CAPTURE_MODE_TELETEXT:
300
g_assert_not_reached ();
303
zapping->display_mode = DISPLAY_MODE_WINDOW;
304
tv_set_capture_mode (zapping->info, CAPTURE_MODE_NONE);
306
x11_vidmode_restore (svidmodes, &old_vidmode);
227
310
/* Remove the black window */
228
gtk_widget_destroy(black_window);
229
x11_force_expose(0, 0, gdk_screen_width(), gdk_screen_height());
232
gtk_signal_disconnect_by_func(GTK_OBJECT(osd_model),
233
GTK_SIGNAL_FUNC(osd_model_changed),
311
gtk_widget_destroy (black_window);
314
x11_force_expose ((gint) screen->x,
319
x11_vidmode_list_delete (svidmodes);
322
gtk_widget_show (GTK_WIDGET (zapping));
324
/* Undo "smart" placement by the WM. */
325
gtk_window_move (GTK_WINDOW (zapping),
333
start_fullscreen (display_mode dmode,
339
const gchar *vm_name;
340
const x11_vidmode_info *vm;
348
if (CAPTURE_MODE_TELETEXT == cmode)
349
if (!_teletext_view_new
350
|| !zvbi_get_object ())
353
if (CAPTURE_MODE_TELETEXT == cmode)
360
/* VidModes available on this screen. */
361
svidmodes = x11_vidmode_list_new (NULL, xs->screen_number);
365
black_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
366
window = GTK_WINDOW (black_window);
368
gtk_widget_realize (black_window);
369
gdk_window_set_decorations (black_window->window, 0);
371
gtk_widget_set_size_request (black_window,
375
gtk_widget_modify_bg (black_window, GTK_STATE_NORMAL, &chroma);
377
gtk_window_add_accel_group
378
(window, gtk_ui_manager_get_accel_group (zapping->ui_manager));
381
fixed = gtk_fixed_new ();
382
gtk_widget_show (fixed);
383
gtk_container_add (GTK_CONTAINER (black_window), fixed);
386
if (CAPTURE_MODE_TELETEXT == cmode)
389
/* Welcome to the magic world of encapsulation. */
390
drawing_area = _teletext_view_new ();
393
/* Gdk scaling routines hang if we start with the default 1, 1. */
394
gtk_widget_set_size_request (drawing_area, 400, 300);
396
/* For Python bindings. */
397
g_object_set_data (G_OBJECT (black_window),
398
"TeletextView", drawing_area);
402
drawing_area = z_video_new ();
403
Z_VIDEO (drawing_area)->size_magic = FALSE;
405
set_blank_timeout (Z_VIDEO (drawing_area));
407
g_signal_connect (G_OBJECT (drawing_area), "cursor-blanked",
408
G_CALLBACK (on_cursor_blanked), zapping->info);
411
gtk_widget_show (drawing_area);
412
gtk_fixed_put (GTK_FIXED (fixed), drawing_area, 0, 0);
414
gtk_widget_add_events (drawing_area,
415
GDK_BUTTON_PRESS_MASK |
416
GDK_BUTTON_RELEASE_MASK |
420
gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &chroma);
422
gtk_widget_show (black_window);
424
if (CAPTURE_MODE_TELETEXT == cmode)
426
/* XXX TeletextView should already do this on realize, doesn't work??? */
427
gdk_window_set_back_pixmap (drawing_area->window, NULL, FALSE);
430
/* Make sure we're on the right screen. */
432
gtk_window_move (window, (gint) xs->x, (gint) xs->y);
434
gtk_window_move (window, 700, 600);
436
if (DISPLAY_MODE_BACKGROUND == dmode)
438
x11_window_below (window, TRUE);
442
/* This should span only one screen, with or without Xinerama,
443
if the WM has proper Xinerama support. */
444
x11_window_fullscreen (window, TRUE);
447
gtk_window_present (window);
452
case CAPTURE_MODE_OVERLAY:
453
/* Make sure we use an Xv adaptor which can render into da->window.
454
(Won't help with X.org but it's the right thing to do.) */
455
tveng_close_device(zapping->info);
457
if (-1 == tveng_attach_device (zcg_char (NULL, "video_device"),
458
GDK_WINDOW_XWINDOW (drawing_area->window),
462
ShowBox("Overlay mode not available:\n%s",
463
GTK_MESSAGE_ERROR, tv_get_errstr (zapping->info));
467
if (tv_get_controller (zapping->info) != TVENG_CONTROLLER_XV &&
468
(tv_get_caps (zapping->info)->flags & TVENG_CAPS_CHROMAKEY))
470
chroma.blue = 0xffff;
472
if (gdk_colormap_alloc_color(gdk_colormap_get_system(), &chroma,
475
z_set_window_bg (drawing_area, &chroma);
477
gdk_colormap_free_colors (gdk_colormap_get_system(), &chroma, 1);
481
ShowBox("Couldn't allocate chromakey, chroma won't work",
482
GTK_MESSAGE_WARNING);
485
else if (tv_get_controller (zapping->info) == TVENG_CONTROLLER_XV)
488
unsigned int chromakey;
492
if (tv_get_overlay_chromakey (zapping->info, &chromakey))
494
chroma.pixel = chromakey;
495
z_set_window_bg (drawing_area, &chroma);
499
/* Disable double buffering just in case, will help when a
500
XV driver doesn't provide XV_COLORKEY but requires the colorkey
501
not to be overwritten */
502
gtk_widget_set_double_buffered (drawing_area, FALSE);
506
case CAPTURE_MODE_READ:
507
tveng_close_device(zapping->info);
509
if (-1 == tveng_attach_device (zcg_char (NULL, "video_device"),
510
GDK_WINDOW_XWINDOW (drawing_area->window),
514
ShowBox("Capture mode not available:\n%s",
515
GTK_MESSAGE_ERROR, tv_get_errstr (zapping->info));
521
case CAPTURE_MODE_TELETEXT:
522
/* Bktr driver needs special programming for VBI-only mode. */
523
tveng_close_device (zapping->info);
525
if (-1 == tveng_attach_device (zcg_char (NULL, "video_device"),
526
GDK_WINDOW_XWINDOW (drawing_area->window),
530
ShowBox ("Teletext mode not available.",
541
/* Determine video size. XXX improve me. */
542
if (CAPTURE_MODE_TELETEXT == cmode)
544
if ((vm_name = zcg_char (NULL, "fullscreen/vidmode"))
545
&& 0 != strcmp (vm_name, "auto"))
547
vm = x11_vidmode_by_name (svidmodes, vm_name);
554
if (vm && x11_vidmode_switch (svidmodes, screens, vm, &old_vidmode))
556
/* xs->width, height >= vm->width, height */
559
vheight = vm->height;
563
x11_vidmode_clear_state (&old_vidmode);
566
vheight = xs->height;
571
const tv_video_standard *vs;
572
const struct tveng_caps *caps;
574
if ((vs = tv_cur_video_standard (zapping->info)))
576
vwidth = vs->frame_width;
577
vheight = vs->frame_height;
586
caps = tv_get_caps (zapping->info);
587
vwidth = MIN ((guint) caps->maxwidth, vwidth);
588
vheight = MIN ((guint) caps->maxheight, vheight);
590
/* Screen limit. XXX should try to scale captured images down. */
591
vwidth = MIN (xs->width, vwidth);
592
vheight = MIN (xs->height, vheight);
594
if ((vm_name = zcg_char (NULL, "fullscreen/vidmode")))
596
if (0 == strcmp (vm_name, "auto"))
598
vm = find_vidmode (svidmodes, vwidth, vheight);
602
vm = x11_vidmode_by_name (svidmodes, vm_name);
610
if (vm && x11_vidmode_switch (svidmodes, screens, vm, &old_vidmode))
612
/* xs->width, height >= vm->width, height <=> vwidth, vheight */
616
x11_vidmode_clear_state (&old_vidmode);
618
if (CAPTURE_MODE_READ == cmode)
620
/* XXX should check scaling abilities. */
622
vheight = xs->height;
626
/* xs->width, height >= vwidth, vheight */
631
vx = (xs->width - vwidth) >> 1;
632
vy = (xs->height - vheight) >> 1;
635
fprintf (stderr, "vx=%u,%u vwidth=%u,%u xswidth=%u,%u\n",
636
vx, vy, vwidth, vheight, xs->width, xs->height);
638
gtk_widget_set_size_request (drawing_area, (gint) vwidth, (gint) vheight);
639
gtk_fixed_move (GTK_FIXED (fixed), drawing_area, vx, vy);
643
case CAPTURE_MODE_OVERLAY:
645
if (tv_get_controller (zapping->info) == TVENG_CONTROLLER_XV)
647
/* Wait until da has the desired size. */
648
while (gtk_events_pending ())
649
gtk_main_iteration ();
651
if (!tv_set_overlay_xwindow (zapping->info,
652
GDK_WINDOW_XWINDOW (drawing_area->window),
653
GDK_GC_XGC (drawing_area->style->white_gc)))
657
tv_overlay_hack (zapping->info, vx, vy, (int) vwidth, (int) vheight);
664
if (!z_set_overlay_buffer (zapping->info, xs, drawing_area->window))
671
window.width = vwidth;
672
window.height = vheight;
674
/* Set new capture dimensions */
675
if (!tv_set_overlay_window_clipvec (zapping->info, &window, NULL))
678
w = tv_cur_overlay_window (zapping->info);
679
if (w->width != vwidth
680
|| w->height != vheight)
682
window.x = (xs->width - w->width) >> 1;
683
window.y = (xs->height - w->height) >> 1;
685
if (!tv_set_overlay_window_clipvec
686
(zapping->info, &window, NULL))
692
if (!tv_enable_overlay (zapping->info, TRUE))
697
case CAPTURE_MODE_READ:
699
tveng_set_capture_size (vwidth, vheight, zapping->info);
701
if (!capture_start (zapping->info, GTK_WIDGET (drawing_area)))
706
case CAPTURE_MODE_TELETEXT:
714
gdk_window_get_origin (GTK_WIDGET (zapping)->window,
718
gtk_widget_hide (GTK_WIDGET (zapping));
720
zapping->display_mode = DISPLAY_MODE_FULLSCREEN;
721
tv_set_capture_mode (zapping->info, cmode);
723
gtk_widget_grab_focus (black_window);
725
g_signal_connect (G_OBJECT (black_window), "key_press_event",
726
G_CALLBACK (on_key_press),
727
GTK_WIDGET (zapping));
729
g_signal_connect (G_OBJECT (black_window), "button_press_event",
730
G_CALLBACK (on_button_press),
731
GTK_WIDGET (zapping));
733
g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
734
G_CALLBACK (on_button_press),
735
GTK_WIDGET (zapping));
737
g_signal_connect (G_OBJECT (drawing_area), "scroll_event",
738
G_CALLBACK (on_scroll_event),
739
GTK_WIDGET (zapping));
745
case CAPTURE_MODE_OVERLAY:
746
w = tv_cur_overlay_window (zapping->info);
748
if (tv_get_controller (zapping->info) != TVENG_CONTROLLER_XV)
750
osd_set_coords (drawing_area,
751
w->x, w->y, (gint) w->width, (gint) w->height);
755
/* wrong because Xv may pad to this size (DMA hw limit) */
756
osd_set_coords (drawing_area,
757
w->x, w->y, (gint) w->width, (gint) w->height);
760
g_signal_connect (G_OBJECT (osd_model), "changed",
761
G_CALLBACK (osd_model_changed), zapping->info);
765
case CAPTURE_MODE_READ:
766
osd_set_window (GTK_WIDGET (drawing_area));
769
case CAPTURE_MODE_TELETEXT:
780
x11_vidmode_list_delete (svidmodes);
782
gtk_widget_destroy (black_window);