1 /**
2  * \file gnome_frame.c
3  *
4  * This file contains functions needed for creation and maintenance of the
5  * frame enclosing the area to capture.
6  */
7 
8 /*
9  * Copyright (C) 2003-07 Karl H. Beckers, Frankfurt
10  * EMail: khb@jarre-de-the.net
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  *
27  * This file contains routines for setting up and handling the selection
28  * rectangle. Both Xt and GTK2 versions are in here now.
29  *
30  */
31 
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36 
37 #define DEBUGFILE "gnome_frame.c"
38 #endif     // DOXYGEN_SHOULD_SKIP_THIS
39 
40 #include <X11/Intrinsic.h>
41 #include <gtk/gtk.h>
42 #include <gdk/gdkx.h>
43 #include <glade/glade.h>
44 #include <stdlib.h>
45 #include <sys/time.h>                  // for timeval struct and related
46 #include <pthread.h>
47 
48 #include "app_data.h"
49 #include "job.h"
50 #include "frame.h"
51 #include "gnome_frame.h"
52 #include "gnome_ui.h"
53 
54 #define XVC_FRAME_DIM_SHOW_TIME 2
55 
56 /*
57  * file globals (static)
58  *
59  */
60 /**
61  * \brief remember the Display if already retrieved
62  *
63  * This assumes that the Display to capture from cannot change once xvidcap
64  * has been started. We reuse any Display we once retrieved to avoid
65  * potential X server roundtrip
66  */
67 static Display *xvc_dpy = NULL;
68 
69 /** \brief make the frame parts available everywhere in this file */
70 static GtkWidget *gtk_frame_top,
71     *gtk_frame_left, *gtk_frame_right, *gtk_frame_bottom, *gtk_frame_center;
72 static GtkWidget *xvc_frame_dimensions_window;
73 static gboolean button_pressed = FALSE;
74 static int button_press_rel_x = 0;
75 static int button_press_rel_y = 0;
76 static gint frame_drag_cursor = GDK_X_CURSOR;
77 static long frame_dimensions_hide_time = 0;
78 static GdkDisplay *gdpy;
79 
80 /**
81  * \brief gets the Display to capture from
82  *
83  * If the frame has been created we retrieve the Display from GDK. Otherwise,
84  * (either we're running without GUI or we're doing this before the frame
85  * has been created, which is the case if we pass --window) we use
86  * XOpenDisplay if xvc_dpy is not already set.
87  *
88  * @return a pointer to the Display to capture from. This Display can be
89  *      expected to be always open and only closed on program exit.
90  * @see xvc_frame_drop_capture_display
91  */
92 Display *
xvc_frame_get_capture_display()93 xvc_frame_get_capture_display ()
94 {
95 #define DEBUGFUNCTION "xvc_frame_get_capure_display()"
96     XVC_AppData *app = xvc_appdata_ptr ();
97 
98     if (!(app->flags & FLG_NOGUI) && !(app->flags & FLG_NOFRAME)
99         && gtk_frame_top) {
100         xvc_dpy = GDK_DRAWABLE_XDISPLAY (GTK_WIDGET (gtk_frame_top)->window);
101     } else {
102         if (!xvc_dpy)
103             gdpy = gdk_display_get_default ();
104         xvc_dpy = gdk_x11_display_get_xdisplay (gdpy);
105     }
106     g_assert (xvc_dpy);
107     return xvc_dpy;
108 #undef DEBUGFUNCTION
109 }
110 
111 /**
112  * \brief cleans up the Display to capture from, i. e. close and set to NULL
113  */
114 void
xvc_frame_drop_capture_display()115 xvc_frame_drop_capture_display ()
116 {
117 #define DEBUGFUNCTION "xvc_frame_drop_capture_display()"
118     XVC_AppData *app = xvc_appdata_ptr ();
119 
120     if ((app->flags & FLG_NOGUI || app->flags & FLG_NOFRAME) && xvc_dpy) {
121         gdk_display_close (gdpy);
122         gdpy = NULL;
123         xvc_dpy = NULL;
124     }
125 #undef DEBUGFUNCTION
126 }
127 
128 /**
129  * \brief repositions the main control according to the frame's current
130  *      position
131  *
132  * @param toplevel a pointer to the main control
133  */
134 void
do_reposition_control(GtkWidget * toplevel)135 do_reposition_control (GtkWidget * toplevel)
136 {
137 #define DEBUGFUNCTION "do_reposition_control()"
138     int max_width = 0, max_height = 0;
139     int pwidth = 0, pheight = 0;
140     XRectangle *x_rect = xvc_get_capture_area ();
141     int x = x_rect->x, y = x_rect->y;
142     int width = x_rect->width, height = x_rect->height;
143     GdkScreen *myscreen;
144     GdkRectangle rect;
145 
146     myscreen = GTK_WINDOW (toplevel)->screen;
147     g_assert (myscreen);
148 
149     max_width = gdk_screen_get_width (GDK_SCREEN (myscreen));
150     max_height = gdk_screen_get_height (GDK_SCREEN (myscreen));
151 
152     xvc_get_ctrl_frame_extents (GDK_WINDOW (toplevel->window), &rect);
153 //    gdk_window_get_frame_extents (GDK_WINDOW (toplevel->window), &rect);
154     pwidth = rect.width + FRAME_OFFSET;
155     pheight = rect.height + FRAME_OFFSET;
156 
157 #ifdef DEBUG
158     printf ("%s %s: x %i y %i pwidth %i pheight %i width %i height %i\n",
159             DEBUGFILE, DEBUGFUNCTION, x, y, pwidth, pheight, width, height);
160 #endif     // DEBUG
161     if ((y - pheight - FRAME_WIDTH) >= 0) {
162         gtk_window_move (GTK_WINDOW (toplevel), x, (y - pheight - FRAME_WIDTH));
163     } else {
164         GladeXML *xml = NULL;
165         GtkWidget *w = NULL;
166 
167         xml = glade_get_widget_tree (GTK_WIDGET (toplevel));
168         g_assert (xml);
169 
170         w = glade_xml_get_widget (xml, "xvc_ctrl_lock_toggle");
171         g_assert (w);
172 
173         gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (w), FALSE);
174 
175         if ((y + pheight + height + FRAME_WIDTH) < max_height) {
176             gtk_window_move (GTK_WINDOW (toplevel), x,
177                              (y + height + FRAME_OFFSET + FRAME_WIDTH));
178         } else {
179             if (x > pwidth + FRAME_WIDTH + FRAME_OFFSET) {
180                 gtk_window_move (GTK_WINDOW (toplevel),
181                                  (x - pwidth - FRAME_WIDTH), y);
182             } else {
183                 if ((x + width + pwidth + FRAME_WIDTH) < max_width) {
184                     gtk_window_move (GTK_WINDOW (toplevel),
185                                      (x + width + FRAME_OFFSET +
186                                       FRAME_WIDTH), y);
187                 }
188                 // otherwise leave the UI where it is ...
189             }
190         }
191     }
192 #undef DEBUGFUNCTION
193 }
194 
195 /**
196  * \brief hides the frame dimensions display if the time scheduled for
197  *      hiding it is in the past and the widget is available
198  *
199  * This is used through g_timeout_add to schedule hiding of the frame
200  * dimensions display.
201  * @return always zero to remove the timeout function after execution
202  */
203 static int
frame_dimensions_hide()204 frame_dimensions_hide ()
205 {
206     struct timeval curr_time;
207     long current_time = 0;
208 
209     gettimeofday (&curr_time, NULL);
210     current_time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
211     if (xvc_frame_dimensions_window &&
212         GTK_IS_WIDGET (xvc_frame_dimensions_window) &&
213         current_time >= frame_dimensions_hide_time)
214         gtk_widget_hide (xvc_frame_dimensions_window);
215 
216     return 0;
217 }
218 
219 /**
220  * \brief changes frame due to user input
221  *
222  * @param x x-position to change to
223  * @param y y-position to change to
224  * @param width new frame width
225  * @param height new frame height
226  * @param reposition_control TRUE for main control should be repositioned
227  *      if frame moves, or FALSE if not
228  * @param show_dimensions should the frame dimensions display be shown or not?
229  */
230 void
xvc_change_gtk_frame(int x,int y,int width,int height,Boolean reposition_control,Boolean show_dimensions)231 xvc_change_gtk_frame (int x, int y, int width, int height,
232                       Boolean reposition_control, Boolean show_dimensions)
233 {
234 #define DEBUGFUNCTION "xvc_change_gtk_frame()"
235     extern GtkWidget *xvc_ctrl_main_window;
236     XRectangle *x_rect = xvc_get_capture_area ();
237     XVC_AppData *app = xvc_appdata_ptr ();
238     struct timeval curr_time;
239     GladeXML *xml = NULL;
240     GtkWidget *w = NULL;
241     char buf[64];
242     int wwidth, wheight;
243 
244 #ifdef USE_FFMPEG
245     //
246     // make sure we have even width and height for ffmpeg
247     //
248     if (app->current_mode > 0) {
249         Boolean changed = FALSE;
250 
251         if ((width % 2) > 0) {
252             width--;
253             changed = TRUE;
254         }
255         if ((height % 2) > 0) {
256             height--;
257             changed = TRUE;
258         }
259         if (width < 10) {
260             width = 10;
261             changed = TRUE;
262         }
263         if (height < 10) {
264             height = 10;
265             changed = TRUE;
266         }
267 
268         if (changed) {
269             if (app->flags & FLG_RUN_VERBOSE) {
270                 printf
271                     ("Modified Selection geometry: %dx%d+%d+%d\n",
272                      width, height, x, y);
273                 if (reposition_control)
274                     printf ("Need to reposition the maincontrol\n");
275             }
276         }
277     }
278 #endif     // USE_FFMPEG
279 
280     // we have to adjust it to viewable areas
281 #ifdef DEBUG
282     printf ("%s %s: screen = %dx%d selection=%dx%d\n", DEBUGFILE,
283             DEBUGFUNCTION, app->max_width, app->max_height, width, height);
284 #endif
285 
286     if (x < 0)
287         x = 0;
288     if (width > app->max_width)
289         width = app->max_width;
290     if (x + width > app->max_width)
291         x = app->max_width - width;
292 
293     if (y < 0)
294         y = 0;
295     if (height > app->max_height)
296         height = app->max_height;
297     if (y + height > app->max_height)
298         y = app->max_height - height;
299 
300     if ((app->flags & FLG_NOGUI) == 0 && (app->flags & FLG_NOFRAME) == 0) {
301         // move the frame if not running without GUI
302         if (width != app->area->width) {
303             gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_top),
304                                          (width + 2 * FRAME_WIDTH),
305                                          FRAME_WIDTH);
306             gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_bottom),
307                                          (width + 2 * FRAME_WIDTH),
308                                          FRAME_WIDTH);
309         }
310         if (height != app->area->height) {
311             gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_left),
312                                          FRAME_WIDTH, height);
313             gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_right),
314                                          FRAME_WIDTH, height);
315         }
316         if (x != app->area->x || y != app->area->y) {
317             gtk_window_move (GTK_WINDOW (gtk_frame_top), (x - FRAME_WIDTH),
318                              (y - FRAME_WIDTH));
319             gtk_window_move (GTK_WINDOW (gtk_frame_left), (x - FRAME_WIDTH), y);
320         }
321         if (x != app->area->x || y != app->area->y || width != app->area->width
322             || height != app->area->height) {
323             gtk_window_move (GTK_WINDOW (gtk_frame_bottom), (x - FRAME_WIDTH),
324                              (y + height));
325             gtk_window_move (GTK_WINDOW (gtk_frame_right), (x + width), y);
326         }
327 #ifdef HasVideo4Linux
328         // if we have a v4l blind, move it, too
329         if (gtk_frame_center != NULL)
330             gtk_window_move (GTK_WINDOW (gtk_frame_center), x, y);
331 #endif     // HasVideo4Linux
332     }
333     // store coordinates in rectangle for further reference
334     x_rect->x = x;
335     x_rect->y = y;
336     x_rect->width = width;
337     x_rect->height = height;
338 
339     // if the frame is locked, we have a GUI, and we also want to
340     // reposition the GUI (we don't want to except when repositioning the
341     // frame due too the cap_geometry cli parameter because the move of
342     // the frame would because triggered through a move of the control ...
343     // thus causing an infinite loop), move the control window, too
344     if (((app->flags & FLG_NOGUI) == 0) && reposition_control)
345         do_reposition_control (xvc_ctrl_main_window);
346 
347     if (show_dimensions && ((app->flags & FLG_NOFRAME) == 0)) {
348         xml = glade_get_widget_tree (GTK_WIDGET (xvc_frame_dimensions_window));
349         g_assert (xml);
350         w = glade_xml_get_widget (xml, "xvc_frame_size_label");
351         g_assert (w);
352         sprintf (buf, "%i x %i", width, height);
353         gtk_label_set_text (GTK_LABEL (w), buf);
354         w = glade_xml_get_widget (xml, "xvc_frame_position_label");
355         g_assert (w);
356         sprintf (buf, "%i + %i", x, y);
357         gtk_label_set_text (GTK_LABEL (w), buf);
358 
359         gtk_widget_show (GTK_WIDGET (xvc_frame_dimensions_window));
360         gtk_window_set_gravity (GTK_WINDOW (xvc_frame_dimensions_window),
361                                 GDK_GRAVITY_CENTER);
362         gtk_window_get_size (GTK_WINDOW (xvc_frame_dimensions_window),
363                              &wwidth, &wheight);
364         gtk_window_move (GTK_WINDOW (xvc_frame_dimensions_window),
365                          (x + (width >> 1) - (wwidth >> 1)),
366                          (y + (height >> 1) - (wheight >> 1)));
367         gettimeofday (&curr_time, NULL);
368         frame_dimensions_hide_time =
369             (curr_time.tv_sec + XVC_FRAME_DIM_SHOW_TIME) * 1000;
370         g_timeout_add ((guint32) (XVC_FRAME_DIM_SHOW_TIME * 1000 + 100),
371                        (GtkFunction) frame_dimensions_hide, NULL);
372     }
373 #undef DEBUGFUNCTION
374 }
375 
376 /**
377  * \brief callback for the configure event on the main control to move
378  *      the frame if the main control moves
379  */
380 static gint
on_gtk_frame_configure_event(GtkWidget * w,GdkEventConfigure * e)381 on_gtk_frame_configure_event (GtkWidget * w, GdkEventConfigure * e)
382 {
383 #define DEBUGFUNCTION "on_gtk_frame_configure_event()"
384     gint x, y, pwidth, pheight;
385     XVC_AppData *app = xvc_appdata_ptr ();
386     Job *job = xvc_job_ptr ();
387 
388     if ((app->flags & FLG_LOCK_FOLLOWS_MOUSE) == 0 && xvc_is_frame_locked ()) {
389         GdkRectangle rect;
390 
391         xvc_get_ctrl_frame_extents (GDK_WINDOW (w->window), &rect);
392 //        gdk_window_get_frame_extents (GDK_WINDOW (w->window), &rect);
393 
394         x = rect.x;
395         y = rect.y;
396         pwidth = rect.width;
397         pheight = rect.height;
398         y += pheight + FRAME_OFFSET + FRAME_WIDTH;
399 
400         // don't move the frame in the middle of capturing
401         // let the capture thread take care of that
402         if (!app->recording_thread_running) {
403             xvc_change_gtk_frame (x, y, app->area->width, app->area->height,
404                                   FALSE, FALSE);
405         } else {
406             // tell the capture job we moved the frame
407             job->frame_moved_x = x - app->area->x;
408             job->frame_moved_y = y - app->area->y;
409         }
410     }
411     return FALSE;
412 #undef DEBUGFUNCTION
413 }
414 
415 /**
416  * \brief callback to start the procedure for dragging the capture area frame
417  *      if we're not capturing and the mouse button is not pressed already
418  */
419 gint
on_gtk_frame_enter_notify_event(GtkWidget * w,GdkEventCrossing * event)420 on_gtk_frame_enter_notify_event (GtkWidget * w, GdkEventCrossing * event)
421 {
422     gint x, y;
423     GdkModifierType mt;
424     GdkCursor *cursor;
425     Job *job = xvc_job_ptr ();
426 
427     if ((job->state & VC_STOP) == 0)
428         return 0;
429 
430     if (!button_pressed) {
431         gdk_window_get_pointer (w->window, &x, &y, &mt);
432 
433         if (w == gtk_frame_right) {
434             if (y < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.height / 3)) {
435                 frame_drag_cursor = GDK_TOP_RIGHT_CORNER;
436                 cursor = gdk_cursor_new (frame_drag_cursor);
437             } else if (y > XVC_MAX (w->allocation.height - FRAME_EDGE_SIZE,
438                                     (w->allocation.height << 1) / 3)) {
439                 frame_drag_cursor = GDK_BOTTOM_RIGHT_CORNER;
440                 cursor = gdk_cursor_new (frame_drag_cursor);
441             } else {
442                 frame_drag_cursor = GDK_RIGHT_SIDE;
443                 cursor = gdk_cursor_new (frame_drag_cursor);
444             }
445             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_right)->window,
446                                    cursor);
447             gdk_cursor_destroy (cursor);
448         } else if (w == gtk_frame_top) {
449             if (x < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.width / 3)) {
450                 frame_drag_cursor = GDK_TOP_LEFT_CORNER;
451                 cursor = gdk_cursor_new (frame_drag_cursor);
452             } else if (x > XVC_MAX (w->allocation.width - FRAME_EDGE_SIZE,
453                                     (w->allocation.width << 1) / 3)) {
454                 frame_drag_cursor = GDK_TOP_RIGHT_CORNER;
455                 cursor = gdk_cursor_new (frame_drag_cursor);
456             } else {
457                 frame_drag_cursor = GDK_TOP_SIDE;
458                 cursor = gdk_cursor_new (frame_drag_cursor);
459             }
460             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_top)->window, cursor);
461             gdk_cursor_destroy (cursor);
462         } else if (w == gtk_frame_bottom) {
463             if (x < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.width / 3)) {
464                 frame_drag_cursor = GDK_BOTTOM_LEFT_CORNER;
465                 cursor = gdk_cursor_new (frame_drag_cursor);
466             } else if (x > XVC_MAX (w->allocation.width - FRAME_EDGE_SIZE,
467                                     (w->allocation.width << 1) / 3)) {
468                 frame_drag_cursor = GDK_BOTTOM_RIGHT_CORNER;
469                 cursor = gdk_cursor_new (frame_drag_cursor);
470             } else {
471                 frame_drag_cursor = GDK_BOTTOM_SIDE;
472                 cursor = gdk_cursor_new (frame_drag_cursor);
473             }
474             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_bottom)->window,
475                                    cursor);
476             gdk_cursor_destroy (cursor);
477         } else {
478             if (y < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.height / 3)) {
479                 frame_drag_cursor = GDK_TOP_LEFT_CORNER;
480                 cursor = gdk_cursor_new (frame_drag_cursor);
481             } else if (y > XVC_MAX (w->allocation.height - FRAME_EDGE_SIZE,
482                                     (w->allocation.height << 1) / 3)) {
483                 frame_drag_cursor = GDK_BOTTOM_LEFT_CORNER;
484                 cursor = gdk_cursor_new (frame_drag_cursor);
485             } else {
486                 frame_drag_cursor = GDK_LEFT_SIDE;
487                 cursor = gdk_cursor_new (frame_drag_cursor);
488             }
489             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_left)->window, cursor);
490             gdk_cursor_destroy (cursor);
491         }
492 
493     }
494     return 0;
495 }
496 
497 /**
498  * \brief resets the cursor on the capture area frame so that it will never
499  *      change as for dragging during capture.
500  */
501 gint
on_gtk_frame_leave_notify_event(GtkWidget * w,GdkEventCrossing * event)502 on_gtk_frame_leave_notify_event (GtkWidget * w, GdkEventCrossing * event)
503 {
504     if (!button_pressed) {
505         frame_drag_cursor = GDK_X_CURSOR;
506         gdk_window_set_cursor (GTK_WIDGET (gtk_frame_top)->window, NULL);
507         gdk_window_set_cursor (GTK_WIDGET (gtk_frame_bottom)->window, NULL);
508         gdk_window_set_cursor (GTK_WIDGET (gtk_frame_right)->window, NULL);
509         gdk_window_set_cursor (GTK_WIDGET (gtk_frame_left)->window, NULL);
510     }
511     return 0;
512 }
513 
514 /**
515  * \brief handle dragging or changing mouse pointer
516  */
517 gint
on_gtk_frame_motion_notify_event(GtkWidget * w,GdkEventMotion * event)518 on_gtk_frame_motion_notify_event (GtkWidget * w, GdkEventMotion * event)
519 {
520     gint x, y, x_root, y_root, twidth, theight;
521     GdkCursor *cursor;
522     XVC_AppData *app = xvc_appdata_ptr ();
523     Job *job = xvc_job_ptr ();
524 
525     if ((job->state & VC_STOP) == 0)
526         return 0;
527 
528     x = (int) event->x;
529     y = (int) event->y;
530     x_root = (int) event->x_root;
531     y_root = (int) event->y_root;
532 
533 //    printf("xr: %i - off: %i --- x: %i -- width: %i\n", x_root, button_press_rel_x, app->area->x, app->area->width);
534 //    printf("yr: %i - off: %i --- y: %i\n", y_root, button_press_rel_y, app->area->y);
535 
536     if (!button_pressed) {
537         if (w == gtk_frame_right) {
538             if (y < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.height / 3)) {
539                 frame_drag_cursor = GDK_TOP_RIGHT_CORNER;
540                 cursor = gdk_cursor_new (frame_drag_cursor);
541             } else if (y > XVC_MAX (w->allocation.height - FRAME_EDGE_SIZE,
542                                     (w->allocation.height << 1) / 3)) {
543                 frame_drag_cursor = GDK_BOTTOM_RIGHT_CORNER;
544                 cursor = gdk_cursor_new (frame_drag_cursor);
545             } else {
546                 frame_drag_cursor = GDK_RIGHT_SIDE;
547                 cursor = gdk_cursor_new (frame_drag_cursor);
548             }
549             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_right)->window,
550                                    cursor);
551             gdk_cursor_destroy (cursor);
552         } else if (w == gtk_frame_top) {
553             if (x < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.width / 3)) {
554                 frame_drag_cursor = GDK_TOP_LEFT_CORNER;
555                 cursor = gdk_cursor_new (frame_drag_cursor);
556             } else if (x > XVC_MAX (w->allocation.width - FRAME_EDGE_SIZE,
557                                     (w->allocation.width << 1) / 3)) {
558                 frame_drag_cursor = GDK_TOP_RIGHT_CORNER;
559                 cursor = gdk_cursor_new (frame_drag_cursor);
560             } else {
561                 frame_drag_cursor = GDK_TOP_SIDE;
562                 cursor = gdk_cursor_new (frame_drag_cursor);
563             }
564             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_top)->window, cursor);
565             gdk_cursor_destroy (cursor);
566         } else if (w == gtk_frame_bottom) {
567             if (x < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.width / 3)) {
568                 frame_drag_cursor = GDK_BOTTOM_LEFT_CORNER;
569                 cursor = gdk_cursor_new (frame_drag_cursor);
570             } else if (x > XVC_MAX (w->allocation.width - FRAME_EDGE_SIZE,
571                                     (w->allocation.width << 1) / 3)) {
572                 frame_drag_cursor = GDK_BOTTOM_RIGHT_CORNER;
573                 cursor = gdk_cursor_new (frame_drag_cursor);
574             } else {
575                 frame_drag_cursor = GDK_BOTTOM_SIDE;
576                 cursor = gdk_cursor_new (frame_drag_cursor);
577             }
578             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_bottom)->window,
579                                    cursor);
580             gdk_cursor_destroy (cursor);
581         } else {
582             if (y < XVC_MIN (FRAME_EDGE_SIZE, w->allocation.height / 3)) {
583                 frame_drag_cursor = GDK_TOP_LEFT_CORNER;
584                 cursor = gdk_cursor_new (frame_drag_cursor);
585             } else if (y > XVC_MAX (w->allocation.height - FRAME_EDGE_SIZE,
586                                     (w->allocation.height << 1) / 3)) {
587                 frame_drag_cursor = GDK_BOTTOM_LEFT_CORNER;
588                 cursor = gdk_cursor_new (frame_drag_cursor);
589             } else {
590                 frame_drag_cursor = GDK_LEFT_SIDE;
591                 cursor = gdk_cursor_new (frame_drag_cursor);
592             }
593             gdk_window_set_cursor (GTK_WIDGET (gtk_frame_left)->window, cursor);
594             gdk_cursor_destroy (cursor);
595         }
596     } else {
597         if (frame_drag_cursor == GDK_TOP_RIGHT_CORNER) {
598             x_root = x_root - button_press_rel_x;
599             y_root = y_root + button_press_rel_y;
600 
601             if (x_root < (app->area->x + 20))
602                 x_root = app->area->x + 20;
603             if (y_root > (app->area->y + app->area->height - 20))
604                 y_root = app->area->y + app->area->height - 20;
605             twidth = x_root - app->area->x;
606             if ((twidth % 2) > 0) {
607                 twidth--;
608                 x_root--;
609             }
610             theight = app->area->height - y_root + app->area->y;
611             if ((theight % 2) > 0) {
612                 theight--;
613                 y_root++;
614             }
615 
616             xvc_change_gtk_frame (app->area->x, y_root,
617                                   twidth, theight, FALSE, TRUE);
618         } else if (frame_drag_cursor == GDK_BOTTOM_RIGHT_CORNER) {
619             x_root = x_root - button_press_rel_x;
620             y_root = y_root - button_press_rel_y;
621 
622             if (x_root < (app->area->x + 20))
623                 x_root = app->area->x + 20;
624             if (y_root < (app->area->y + 20))
625                 y_root = app->area->y + 20;
626             twidth = x_root - app->area->x;
627             if ((twidth % 2) > 0) {
628                 twidth--;
629                 x_root--;
630             }
631             theight = y_root - app->area->y;
632             if ((theight % 2) > 0) {
633                 theight--;
634                 y_root--;
635             }
636 
637             xvc_change_gtk_frame (app->area->x, app->area->y,
638                                   twidth, theight, FALSE, TRUE);
639         } else if (frame_drag_cursor == GDK_RIGHT_SIDE) {
640             x_root = x_root - button_press_rel_x;
641 
642             if (x_root < (app->area->x + 20))
643                 x_root = app->area->x + 20;
644             twidth = x_root - app->area->x;
645             if ((twidth % 2) > 0) {
646                 twidth--;
647                 x_root--;
648             }
649 
650             xvc_change_gtk_frame (app->area->x, app->area->y,
651                                   twidth, app->area->height, FALSE, TRUE);
652         } else if (frame_drag_cursor == GDK_TOP_SIDE) {
653             y_root = y_root + button_press_rel_y;
654 
655             if (y_root > (app->area->y + app->area->height - 20))
656                 y_root = app->area->y + app->area->height - 20;
657             theight = app->area->height - y_root + app->area->y;
658             if ((theight % 2) > 0) {
659                 theight--;
660                 y_root++;
661             }
662 
663             xvc_change_gtk_frame (app->area->x, y_root,
664                                   app->area->width, theight, FALSE, TRUE);
665         } else if (frame_drag_cursor == GDK_TOP_LEFT_CORNER) {
666             x_root = x_root + button_press_rel_x;
667             y_root = y_root + button_press_rel_y;
668 
669             if (x_root > (app->area->x + app->area->width - 20))
670                 x_root = app->area->x + app->area->width - 20;
671             if (y_root > (app->area->y + app->area->height - 20))
672                 y_root = app->area->y + app->area->height - 20;
673             twidth = app->area->width - x_root + app->area->x;
674             if ((twidth % 2) > 0) {
675                 twidth--;
676                 x_root++;
677             }
678             theight = app->area->height - y_root + app->area->y;
679             if ((theight % 2) > 0) {
680                 theight--;
681                 y_root++;
682             }
683 
684             xvc_change_gtk_frame (x_root, y_root, twidth, theight, FALSE, TRUE);
685         } else if (frame_drag_cursor == GDK_LEFT_SIDE) {
686             x_root = x_root + button_press_rel_x;
687             if (x_root > (app->area->x + app->area->width - 20))
688                 x_root = app->area->x + app->area->width - 20;
689             twidth = app->area->width - (x_root - app->area->x);
690             if ((twidth % 2) > 0) {
691                 x_root++;
692                 twidth--;
693             }
694 
695             xvc_change_gtk_frame (x_root, app->area->y,
696                                   twidth, app->area->height, FALSE, TRUE);
697         } else if (frame_drag_cursor == GDK_BOTTOM_LEFT_CORNER) {
698             x_root = x_root + button_press_rel_x;
699             y_root = y_root - button_press_rel_y;
700 
701             if (x_root > (app->area->x + app->area->width - 20))
702                 x_root = app->area->x + app->area->width - 20;
703             if (y_root < (app->area->y + 20))
704                 y_root = app->area->y + 20;
705             twidth = app->area->width - x_root + app->area->x;
706             if ((twidth % 2) > 0) {
707                 twidth--;
708                 x_root++;
709             }
710             theight = y_root - app->area->y;
711             if ((theight % 2) > 0) {
712                 theight--;
713                 y_root--;
714             }
715 
716             xvc_change_gtk_frame (x_root, app->area->y,
717                                   twidth, theight, FALSE, TRUE);
718         } else {                       // GDK_BOTTOM_SIDE
719             y_root = y_root - button_press_rel_y;
720 
721             if (y_root < (app->area->y + 20))
722                 y_root = app->area->y + 20;
723             theight = y_root - app->area->y;
724             if ((theight % 2) > 0) {
725                 theight--;
726                 y_root--;
727             }
728 
729             xvc_change_gtk_frame (app->area->x, app->area->y,
730                                   app->area->width, theight, FALSE, TRUE);
731         }
732     }
733     return 0;
734 }
735 
736 /**
737  * \brief track mouse pointer presses on frame
738  */
739 gint
on_gtk_frame_button_press_event(GtkWidget * w,GdkEventButton * event)740 on_gtk_frame_button_press_event (GtkWidget * w, GdkEventButton * event)
741 {
742     XVC_AppData *app = xvc_appdata_ptr ();
743 
744     button_pressed = TRUE;
745     if (w == gtk_frame_right) {
746         button_press_rel_x = event->x + 1;
747         button_press_rel_y = 0;
748     } else if (w == gtk_frame_top) {
749         if (event->x < FRAME_WIDTH) {
750             button_press_rel_x = FRAME_WIDTH - event->x - 1;
751         } else if (event->x > app->area->width + FRAME_WIDTH) {
752             button_press_rel_x = event->x - app->area->width - FRAME_WIDTH;
753         } else {
754             button_press_rel_x = 0;
755         }
756         button_press_rel_y = FRAME_WIDTH - event->y - 1;
757     } else if (w == gtk_frame_bottom) {
758         if (event->x < FRAME_WIDTH) {
759             button_press_rel_x = FRAME_WIDTH - event->x - 1;
760         } else if (event->x > app->area->width + FRAME_WIDTH) {
761             button_press_rel_x = event->x - app->area->width - FRAME_WIDTH;
762         } else {
763             button_press_rel_x = 0;
764         }
765         button_press_rel_y = event->y + 1;
766     } else {
767         button_press_rel_x = FRAME_WIDTH - event->x - 1;
768         button_press_rel_y = 0;
769     }
770 //    printf("x %i y %i\n", button_press_rel_x, button_press_rel_y);
771     return 0;
772 }
773 
774 /**
775  * \brief track mouse pointer presses on frame
776  */
777 gint
on_gtk_frame_button_release_event(GtkWidget * w,GdkEventButton * event)778 on_gtk_frame_button_release_event (GtkWidget * w, GdkEventButton * event)
779 {
780     if (xvc_is_frame_locked ()) {
781         XVC_AppData *app = xvc_appdata_ptr ();
782 
783         xvc_change_gtk_frame (app->area->x, app->area->y,
784                               app->area->width, app->area->height, TRUE, FALSE);
785     }
786     button_pressed = FALSE;
787     return 0;
788 }
789 
790 /**
791  * \brief creates a frame around the area to capture
792  *
793  * @param toplevel a pointer to the main control
794  * @param pwidth width for the frame
795  * @param pheight height for the frame
796  * @param px x-position for the frame
797  * @param py y-position for the frame
798  */
799 void
xvc_create_gtk_frame(GtkWidget * toplevel,int pwidth,int pheight,int px,int py)800 xvc_create_gtk_frame (GtkWidget * toplevel, int pwidth, int pheight,
801                       int px, int py)
802 {
803 #define DEBUGFUNCTION "xvc_create_gtk_frame()"
804     gint x = 0, y = 0;
805     GdkColor g_col;
806     GdkColormap *colormap;
807     GdkRectangle rect;
808     XVC_AppData *app = xvc_appdata_ptr ();
809     int flags = app->flags;
810     XRectangle *x_rect = xvc_get_capture_area ();
811     GladeXML *xml = NULL;
812 
813 #ifdef DEBUG
814     printf ("%s %s: x %d y %d width %d height %d\n", DEBUGFILE,
815             DEBUGFUNCTION, px, py, pwidth, pheight);
816 #endif
817 
818 #ifdef USE_FFMPEG
819     //
820     // make sure we have even width and height for ffmpeg
821     //
822     if (app->current_mode > 0) {
823         Boolean changed = FALSE;
824 
825         if ((pwidth % 2) > 0) {
826             pwidth--;
827             changed = TRUE;
828         }
829         if ((pheight % 2) > 0) {
830             pheight--;
831             changed = TRUE;
832         }
833         if (pwidth < 10) {
834             pwidth = 10;
835             changed = TRUE;
836         }
837         if (pheight < 10) {
838             pheight = 10;
839             changed = TRUE;
840         }
841 
842         if (changed) {
843             if (app->flags & FLG_RUN_VERBOSE) {
844                 printf
845                     ("Modified Selection geometry: %dx%d+%d+%d\n",
846                      pwidth, pheight, x, y);
847             }
848         }
849     }
850 #endif     // USE_FFMPEG
851 
852     // we have to adjust it to viewable areas
853 //    max_width = WidthOfScreen (DefaultScreenOfDisplay (app->dpy));
854 //    max_height = HeightOfScreen (DefaultScreenOfDisplay (app->dpy));
855 
856 #ifdef DEBUG
857     printf ("%s %s: screen = %dx%d selection=%dx%d\n", DEBUGFILE,
858             DEBUGFUNCTION, app->max_width, app->max_height, pwidth, pheight);
859 #endif
860 
861     if (x < 0)
862         x = 0;
863     if (pwidth > app->max_width)
864         pwidth = app->max_width;
865     if (x + pwidth > app->max_width)
866         x = app->max_width - pwidth;
867 
868     if (y < 0)
869         y = 0;
870     if (pheight > app->max_height)
871         pheight = app->max_height;
872     if (y + pheight > app->max_height)
873         y = app->max_height - pheight;
874 
875     // now for the real work
876     if (!(flags & FLG_NOGUI)) {
877         g_assert (toplevel);
878 
879         if (px < 0 && py < 0) {
880             // compute position for frame
881             xvc_get_ctrl_frame_extents (GDK_WINDOW (toplevel->window), &rect);
882 //            gdk_window_get_frame_extents (GDK_WINDOW (toplevel->window), &rect);
883 
884             if (x < 0)
885                 x = 0;
886 
887             y = rect.y;
888             y += rect.height + FRAME_OFFSET;
889             if (y < 0)
890                 y = 0;
891         } else {
892             x = (px < 0 ? 0 : px);
893             y = (py < 0 ? 0 : py);
894         }
895     } else {
896         x = (px < 0 ? 0 : px);
897         y = (py < 0 ? 0 : py);
898     }
899 
900     // store rectangle properties for further reference
901     g_assert (x_rect);
902 
903     x_rect->width = pwidth;
904     x_rect->height = pheight;
905     x_rect->x = x;
906     x_rect->y = y;
907 
908     // create frame
909     if (!(flags & FLG_NOGUI) && !(flags & FLG_NOFRAME)) {
910 
911         // top of frame
912         gtk_frame_top = gtk_window_new (GTK_WINDOW_POPUP);
913         g_assert (gtk_frame_top);
914 
915         gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_top),
916                                      (pwidth + 2 * FRAME_WIDTH), FRAME_WIDTH);
917         gtk_window_set_title (GTK_WINDOW (gtk_frame_top), "gtk_frame_top");
918         gtk_window_set_resizable (GTK_WINDOW (gtk_frame_top), FALSE);
919         gtk_widget_add_events (GTK_WIDGET (gtk_frame_top),
920                                (GDK_POINTER_MOTION_MASK |
921                                 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK
922                                 | GDK_BUTTON_RELEASE_MASK));
923 
924         colormap = gtk_widget_get_colormap (GTK_WIDGET (gtk_frame_top));
925         g_assert (colormap);
926 
927         if (gdk_color_parse ("red", &g_col)) {
928             // do the following only if parsing color red succeeded ...
929             // if not, we met an error but handle it gracefully by
930             // ignoring the frame
931             // color
932             if (gdk_colormap_alloc_color
933                 (GDK_COLORMAP (colormap), &g_col, FALSE, TRUE)) {
934                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_top),
935                                       GTK_STATE_NORMAL, &g_col);
936                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_top),
937                                       GTK_STATE_ACTIVE, &g_col);
938                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_top),
939                                       GTK_STATE_PRELIGHT, &g_col);
940                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_top),
941                                       GTK_STATE_INSENSITIVE, &g_col);
942                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_top),
943                                       GTK_STATE_SELECTED, &g_col);
944 
945                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_top),
946                                       GTK_STATE_NORMAL, &g_col);
947                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_top),
948                                       GTK_STATE_ACTIVE, &g_col);
949                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_top),
950                                       GTK_STATE_PRELIGHT, &g_col);
951                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_top),
952                                       GTK_STATE_INSENSITIVE, &g_col);
953                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_top),
954                                       GTK_STATE_SELECTED, &g_col);
955             }
956         }
957         gtk_widget_show (gtk_frame_top);
958         gtk_window_move (GTK_WINDOW (gtk_frame_top), (x - FRAME_WIDTH),
959                          (y - FRAME_WIDTH));
960 
961         // left side of frame
962         gtk_frame_left = gtk_window_new (GTK_WINDOW_POPUP);
963         g_assert (gtk_frame_left);
964 
965         gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_left),
966                                      FRAME_WIDTH, pheight);
967         gtk_window_set_title (GTK_WINDOW (gtk_frame_left), "gtk_frame_left");
968         gtk_window_set_resizable (GTK_WINDOW (gtk_frame_left), FALSE);
969         gtk_widget_add_events (GTK_WIDGET (gtk_frame_left),
970                                (GDK_POINTER_MOTION_MASK |
971                                 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK
972                                 | GDK_BUTTON_RELEASE_MASK));
973 
974         colormap = gtk_widget_get_colormap (GTK_WIDGET (gtk_frame_left));
975         g_assert (colormap);
976 
977         if (gdk_color_parse ("red", &g_col)) {
978             // do the following only if parsing color red succeeded ...
979             // if not, we met an error but handle it gracefully by
980             // ignoring the frame color
981             if (gdk_colormap_alloc_color
982                 (GDK_COLORMAP (colormap), &g_col, FALSE, TRUE)) {
983                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_left),
984                                       GTK_STATE_NORMAL, &g_col);
985                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_left),
986                                       GTK_STATE_ACTIVE, &g_col);
987                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_left),
988                                       GTK_STATE_PRELIGHT, &g_col);
989                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_left),
990                                       GTK_STATE_INSENSITIVE, &g_col);
991                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_left),
992                                       GTK_STATE_SELECTED, &g_col);
993 
994                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_left),
995                                       GTK_STATE_NORMAL, &g_col);
996                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_left),
997                                       GTK_STATE_ACTIVE, &g_col);
998                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_left),
999                                       GTK_STATE_PRELIGHT, &g_col);
1000                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_left),
1001                                       GTK_STATE_INSENSITIVE, &g_col);
1002                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_left),
1003                                       GTK_STATE_SELECTED, &g_col);
1004             }
1005         }
1006         gtk_widget_show (GTK_WIDGET (gtk_frame_left));
1007         gtk_window_move (GTK_WINDOW (gtk_frame_left), (x - FRAME_WIDTH), y);
1008 
1009         // bottom of frame
1010         gtk_frame_bottom = gtk_window_new (GTK_WINDOW_POPUP);
1011         g_assert (gtk_frame_bottom);
1012 
1013         gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_bottom),
1014                                      (pwidth + 2 * FRAME_WIDTH), FRAME_WIDTH);
1015         gtk_window_set_title (GTK_WINDOW (gtk_frame_bottom),
1016                               "gtk_frame_bottom");
1017         gtk_window_set_resizable (GTK_WINDOW (gtk_frame_bottom), FALSE);
1018         gtk_widget_add_events (GTK_WIDGET (gtk_frame_bottom),
1019                                (GDK_POINTER_MOTION_MASK |
1020                                 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK
1021                                 | GDK_BUTTON_RELEASE_MASK));
1022 
1023         colormap = gtk_widget_get_colormap (gtk_frame_bottom);
1024         g_assert (colormap);
1025 
1026         if (gdk_color_parse ("red", &g_col)) {
1027             // do the following only if parsing color red succeeded ...
1028             // if not, we met an error but handle it gracefully by
1029             // ignoring the frame color
1030             if (gdk_colormap_alloc_color
1031                 (GDK_COLORMAP (colormap), &g_col, FALSE, TRUE)) {
1032                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_bottom),
1033                                       GTK_STATE_NORMAL, &g_col);
1034                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_bottom),
1035                                       GTK_STATE_ACTIVE, &g_col);
1036                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_bottom),
1037                                       GTK_STATE_PRELIGHT, &g_col);
1038                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_bottom),
1039                                       GTK_STATE_INSENSITIVE, &g_col);
1040                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_bottom),
1041                                       GTK_STATE_SELECTED, &g_col);
1042 
1043                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_bottom),
1044                                       GTK_STATE_NORMAL, &g_col);
1045                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_bottom),
1046                                       GTK_STATE_ACTIVE, &g_col);
1047                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_bottom),
1048                                       GTK_STATE_PRELIGHT, &g_col);
1049                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_bottom),
1050                                       GTK_STATE_INSENSITIVE, &g_col);
1051                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_bottom),
1052                                       GTK_STATE_SELECTED, &g_col);
1053             }
1054         }
1055         gtk_widget_show (GTK_WIDGET (gtk_frame_bottom));
1056         gtk_window_move (GTK_WINDOW (gtk_frame_bottom), (x - FRAME_WIDTH),
1057                          (y + pheight));
1058 
1059         // right side of frame
1060         gtk_frame_right = gtk_window_new (GTK_WINDOW_POPUP);
1061         g_assert (gtk_frame_right);
1062 
1063         gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_right),
1064                                      FRAME_WIDTH, pheight);
1065         gtk_window_set_title (GTK_WINDOW (gtk_frame_right), "gtk_frame_right");
1066         gtk_window_set_resizable (GTK_WINDOW (gtk_frame_right), FALSE);
1067         gtk_widget_add_events (GTK_WIDGET (gtk_frame_right),
1068                                (GDK_POINTER_MOTION_MASK |
1069                                 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK
1070                                 | GDK_BUTTON_RELEASE_MASK));
1071 
1072         colormap = gtk_widget_get_colormap (gtk_frame_right);
1073         g_assert (colormap);
1074 
1075         if (gdk_color_parse ("red", &g_col)) {
1076             // do the following only if parsing color red succeeded ...
1077             // if not, we met an error but handle it gracefully by
1078             // ignoring the frame color
1079             if (gdk_colormap_alloc_color
1080                 (GDK_COLORMAP (colormap), &g_col, FALSE, TRUE)) {
1081                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_right),
1082                                       GTK_STATE_NORMAL, &g_col);
1083                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_right),
1084                                       GTK_STATE_ACTIVE, &g_col);
1085                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_right),
1086                                       GTK_STATE_PRELIGHT, &g_col);
1087                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_right),
1088                                       GTK_STATE_INSENSITIVE, &g_col);
1089                 gtk_widget_modify_bg (GTK_WIDGET (gtk_frame_right),
1090                                       GTK_STATE_SELECTED, &g_col);
1091 
1092                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_right),
1093                                       GTK_STATE_NORMAL, &g_col);
1094                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_right),
1095                                       GTK_STATE_ACTIVE, &g_col);
1096                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_right),
1097                                       GTK_STATE_PRELIGHT, &g_col);
1098                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_right),
1099                                       GTK_STATE_INSENSITIVE, &g_col);
1100                 gtk_widget_modify_fg (GTK_WIDGET (gtk_frame_right),
1101                                       GTK_STATE_SELECTED, &g_col);
1102             }
1103         }
1104         gtk_widget_show (GTK_WIDGET (gtk_frame_right));
1105         gtk_window_move (GTK_WINDOW (gtk_frame_right), (x + pwidth), y);
1106 
1107         xml =
1108             glade_xml_new (XVC_GLADE_FILE, "xvc_frame_dimensions_window", NULL);
1109         g_assert (xml);
1110         xvc_frame_dimensions_window =
1111             glade_xml_get_widget (xml, "xvc_frame_dimensions_window");
1112 
1113 #ifdef HasVideo4Linux
1114         if (flags & FLG_USE_V4L) {
1115             gtk_frame_center = gtk_dialog_new ();
1116 
1117             g_assert (gtk_frame_center);
1118 
1119             gtk_widget_set_size_request (GTK_WIDGET (gtk_frame_center),
1120                                          pwidth, pheight);
1121             gtk_widget_set_sensitive (GTK_WIDGET (gtk_frame_center), FALSE);
1122             gtk_window_set_title (GTK_WINDOW (gtk_frame_right),
1123                                   "gtk_frame_center");
1124             GTK_WINDOW (gtk_frame_center)->type = GTK_WINDOW_POPUP;
1125             gtk_window_set_resizable (GTK_WINDOW (gtk_frame_center), FALSE);
1126             gtk_dialog_set_has_separator (GTK_DIALOG (gtk_frame_center), FALSE);
1127             gtk_widget_show (GTK_WIDGET (gtk_frame_center));
1128             gtk_window_move (GTK_WINDOW (gtk_frame_center), x, y);
1129 
1130             // FIXME: right now the label for the Video Source is missing
1131             // gtk_frame_center = XtVaCreatePopupShell ("blind",
1132             // overrideShellWidgetClass, parent,
1133             // XtNx, x+FRAME_WIDTH,
1134             // XtNy, y+FRAME_WIDTH,
1135             // XtNwidth, width,
1136             // XtNheight, height,
1137             // NULL);
1138             // XtVaCreateManagedWidget ("text", xwLabelWidgetClass, blind,
1139             // XtNlabel, "Source: Video4Linux", NULL);
1140             // XtPopup(blind, XtGrabNone);
1141         }
1142 #endif     // HasVideo4Linux
1143         g_signal_connect (G_OBJECT (gtk_frame_top), "enter_notify_event",
1144                           G_CALLBACK (on_gtk_frame_enter_notify_event), NULL);
1145         g_signal_connect (G_OBJECT (gtk_frame_left), "enter_notify_event",
1146                           G_CALLBACK (on_gtk_frame_enter_notify_event), NULL);
1147         g_signal_connect (G_OBJECT (gtk_frame_bottom), "enter_notify_event",
1148                           G_CALLBACK (on_gtk_frame_enter_notify_event), NULL);
1149         g_signal_connect (G_OBJECT (gtk_frame_right), "enter_notify_event",
1150                           G_CALLBACK (on_gtk_frame_enter_notify_event), NULL);
1151 
1152         g_signal_connect (G_OBJECT (gtk_frame_top), "leave_notify_event",
1153                           G_CALLBACK (on_gtk_frame_leave_notify_event), NULL);
1154         g_signal_connect (G_OBJECT (gtk_frame_left), "leave_notify_event",
1155                           G_CALLBACK (on_gtk_frame_leave_notify_event), NULL);
1156         g_signal_connect (G_OBJECT (gtk_frame_bottom), "leave_notify_event",
1157                           G_CALLBACK (on_gtk_frame_leave_notify_event), NULL);
1158         g_signal_connect (G_OBJECT (gtk_frame_right), "leave_notify_event",
1159                           G_CALLBACK (on_gtk_frame_leave_notify_event), NULL);
1160 
1161         g_signal_connect (G_OBJECT (gtk_frame_top), "motion_notify_event",
1162                           G_CALLBACK (on_gtk_frame_motion_notify_event), NULL);
1163         g_signal_connect (G_OBJECT (gtk_frame_left), "motion_notify_event",
1164                           G_CALLBACK (on_gtk_frame_motion_notify_event), NULL);
1165         g_signal_connect (G_OBJECT (gtk_frame_bottom), "motion_notify_event",
1166                           G_CALLBACK (on_gtk_frame_motion_notify_event), NULL);
1167         g_signal_connect (G_OBJECT (gtk_frame_right), "motion_notify_event",
1168                           G_CALLBACK (on_gtk_frame_motion_notify_event), NULL);
1169 
1170         g_signal_connect (G_OBJECT (gtk_frame_top), "button_press_event",
1171                           G_CALLBACK (on_gtk_frame_button_press_event), NULL);
1172         g_signal_connect (G_OBJECT (gtk_frame_left), "button_press_event",
1173                           G_CALLBACK (on_gtk_frame_button_press_event), NULL);
1174         g_signal_connect (G_OBJECT (gtk_frame_bottom), "button_press_event",
1175                           G_CALLBACK (on_gtk_frame_button_press_event), NULL);
1176         g_signal_connect (G_OBJECT (gtk_frame_right), "button_press_event",
1177                           G_CALLBACK (on_gtk_frame_button_press_event), NULL);
1178 
1179         g_signal_connect (G_OBJECT (gtk_frame_top), "button_release_event",
1180                           G_CALLBACK (on_gtk_frame_button_release_event), NULL);
1181         g_signal_connect (G_OBJECT (gtk_frame_left), "button_release_event",
1182                           G_CALLBACK (on_gtk_frame_button_release_event), NULL);
1183         g_signal_connect (G_OBJECT (gtk_frame_bottom), "button_release_event",
1184                           G_CALLBACK (on_gtk_frame_button_release_event), NULL);
1185         g_signal_connect (G_OBJECT (gtk_frame_right), "button_release_event",
1186                           G_CALLBACK (on_gtk_frame_button_release_event), NULL);
1187 
1188     }
1189     // connect event-handler to configure event of gtk control window
1190     // to redraw the selection frame if the control is moved and the
1191     // frame is locked
1192     // this is also required with FLG_NOFRAME
1193     if (!(flags & FLG_NOGUI)) {
1194         g_signal_connect (G_OBJECT (toplevel), "configure-event",
1195                           G_CALLBACK (on_gtk_frame_configure_event), NULL);
1196     }
1197 
1198     xvc_set_frame_locked (1);
1199 
1200     if (!(flags & FLG_NOGUI) && (px >= 0 || py >= 0))
1201         do_reposition_control (toplevel);
1202 
1203 #undef DEBUGFUNCTION
1204 }
1205 
1206 /**
1207  * \brief destroys the frame around the capture area
1208  */
1209 void
xvc_destroy_gtk_frame()1210 xvc_destroy_gtk_frame ()
1211 {
1212 #define DEBUGFUNCTION "xvc_destroy_gtk_frame()"
1213 
1214     if (gtk_frame_bottom) {
1215         gtk_widget_destroy (gtk_frame_bottom);
1216         gtk_frame_bottom = NULL;
1217     }
1218     if (gtk_frame_right) {
1219         gtk_widget_destroy (gtk_frame_right);
1220         gtk_frame_right = NULL;
1221     }
1222     if (gtk_frame_left) {
1223         gtk_widget_destroy (gtk_frame_left);
1224         gtk_frame_left = NULL;
1225     }
1226     if (gtk_frame_top) {
1227         gtk_widget_destroy (gtk_frame_top);
1228         gtk_frame_top = NULL;
1229     }
1230     if (xvc_frame_dimensions_window) {
1231         gtk_widget_destroy (xvc_frame_dimensions_window);
1232         xvc_frame_dimensions_window = NULL;
1233     }
1234     if (gtk_frame_center) {
1235         gtk_widget_destroy (gtk_frame_center);
1236         gtk_frame_center = NULL;
1237     }
1238 #undef DEBUGFUNCTION
1239 }
1240