prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / canvas.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcsignals.h"
23 #include "canvas.h"
24 #include "clip.h"
25 #include "edl.h"
26 #include "edlsession.h"
27 #include "keys.h"
28 #include "language.h"
29 #include "mainsession.h"
30 #include "mwindowgui.h"
31 #include "mutex.h"
32 #include "mwindow.h"
33 #include "vframe.h"
34
35
36
37 Canvas::Canvas(MWindow *mwindow,
38         BC_WindowBase *subwindow, 
39         int x, 
40         int y, 
41         int w, 
42         int h,
43         int output_w,
44         int output_h,
45         int use_scrollbars)
46 {
47         reset();
48
49         if(w < 10) w = 10;
50         if(h < 10) h = 10;
51         this->mwindow = mwindow;
52         this->subwindow = subwindow;
53         this->x = x;
54         this->y = y;
55         this->w = w;
56         this->h = h;
57         this->output_w = output_w;
58         this->output_h = output_h;
59         this->use_scrollbars = use_scrollbars;
60         this->canvas_auxwindow = 0;
61         this->scr_w0 = subwindow->get_screen_w(0, 0);
62         this->root_w = subwindow->get_root_w(0);
63         this->root_h = subwindow->get_root_h(0);
64         canvas_lock = new Mutex("Canvas::canvas_lock", 1);
65 }
66
67 Canvas::~Canvas()
68 {
69         if(refresh_frame) delete refresh_frame;
70         delete canvas_menu;
71         if(yscroll) delete yscroll;
72         if(xscroll) delete xscroll;
73         delete canvas_subwindow;
74         delete canvas_fullscreen;
75         delete canvas_lock;
76 }
77
78 void Canvas::reset()
79 {
80         use_scrollbars = 0;
81         output_w = 0;
82         output_h = 0;
83         xscroll = 0;
84         yscroll = 0;
85         refresh_frame = 0;
86         canvas_subwindow = 0;
87         canvas_fullscreen = 0;
88         is_processing = 0;
89         cursor_inside = 0;
90 }
91
92 void Canvas::lock_canvas(const char *location)
93 {
94         canvas_lock->lock(location);
95 }
96
97 void Canvas::unlock_canvas()
98 {
99         canvas_lock->unlock();
100 }
101
102 int Canvas::is_locked()
103 {
104         return canvas_lock->is_locked();
105 }
106
107
108 BC_WindowBase* Canvas::get_canvas()
109 {
110         if(get_fullscreen() && canvas_fullscreen) 
111                 return canvas_fullscreen;
112         return canvas_auxwindow ? canvas_auxwindow : canvas_subwindow;
113 }
114
115 void Canvas::use_auxwindow(BC_WindowBase *aux)
116 {
117         canvas_auxwindow = aux;
118 }
119
120 void Canvas::use_cwindow()
121 {
122         canvas_menu->use_cwindow(); 
123         fullscreen_menu->use_cwindow();
124 }
125
126 void Canvas::use_rwindow()
127 {
128         canvas_menu->use_rwindow();
129 }
130
131 void Canvas::use_vwindow()
132 {
133         canvas_menu->use_vwindow();
134 }
135
136 // Get dimensions given a zoom
137 void Canvas::calculate_sizes(float aspect_ratio, 
138         int output_w, 
139         int output_h, 
140         float zoom, 
141         int &w, 
142         int &h)
143 {
144 // Horizontal stretch
145         if((float)output_w / output_h <= aspect_ratio)
146         {
147                 w = (int)((float)output_h * aspect_ratio * zoom);
148                 h = (int)((float)output_h * zoom);
149         }
150         else
151 // Vertical stretch
152         {
153                 h = (int)((float)output_w / aspect_ratio * zoom);
154                 w = (int)((float)output_w * zoom);
155         }
156 }
157
158 float Canvas::get_x_offset(EDL *edl, 
159         int single_channel, 
160         float zoom_x, 
161         float conformed_w,
162         float conformed_h)
163 {
164         if(use_scrollbars)
165         {
166                 if(xscroll) 
167                 {
168 // If the projection is smaller than the canvas, this forces it in the center.
169 //                      if(conformed_w < w_visible)
170 //                              return -(float)(w_visible - conformed_w) / 2;
171
172                         return (float)get_xscroll();
173                 }
174                 else
175                         return ((float)-get_canvas()->get_w() / zoom_x + 
176                                 edl->session->output_w) / 2;
177         }
178         else
179         {
180                 int out_w, out_h;
181                 int canvas_w = get_canvas()->get_w();
182                 int canvas_h = get_canvas()->get_h();
183                 out_w = canvas_w;
184                 out_h = canvas_h;
185                 
186                 if((float)out_w / out_h > conformed_w / conformed_h)
187                 {
188                         out_w = (int)(out_h * conformed_w / conformed_h + 0.5);
189                 }
190                 
191                 if(out_w < canvas_w)
192                         return -(canvas_w - out_w) / 2 / zoom_x;
193         }
194
195         return 0;
196 }
197
198 float Canvas::get_y_offset(EDL *edl, 
199         int single_channel, 
200         float zoom_y, 
201         float conformed_w,
202         float conformed_h)
203 {
204         if(use_scrollbars)
205         {
206                 if(yscroll)
207                 {
208 // If the projection is smaller than the canvas, this forces it in the center.
209 //                      if(conformed_h < h_visible)
210 //                              return -(float)(h_visible - conformed_h) / 2;
211
212                         return (float)get_yscroll();
213                 }
214                 else
215                         return ((float)-get_canvas()->get_h() / zoom_y + 
216                                 edl->session->output_h) / 2;
217         }
218         else
219         {
220                 int out_w, out_h;
221                 int canvas_w = get_canvas()->get_w();
222                 int canvas_h = get_canvas()->get_h();
223                 out_w = canvas_w;
224                 out_h = canvas_h;
225
226                 if((float)out_w / out_h <= conformed_w / conformed_h)
227                 {
228                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
229                 }
230
231 //printf("Canvas::get_y_offset 1 %d %d %f\n", out_h, canvas_h, -((float)canvas_h - out_h) / 2);
232                 if(out_h < canvas_h)
233                         return -((float)canvas_h - out_h) / 2 / zoom_y;
234         }
235
236         return 0;
237 }
238
239 // This may not be used anymore
240 void Canvas::check_boundaries(EDL *edl, int &x, int &y, float &zoom)
241 {
242         if(x + w_visible > w_needed) x = w_needed - w_visible;
243         if(y + h_visible > h_needed) y = h_needed - h_visible;
244
245         if(x < 0) x = 0;
246         if(y < 0) y = 0;
247 }
248
249 void Canvas::update_scrollbars(int flush)
250 {
251         if(use_scrollbars)
252         {
253                 if(xscroll) xscroll->update_length(w_needed, get_xscroll(), w_visible, flush);
254                 if(yscroll) yscroll->update_length(h_needed, get_yscroll(), h_visible, flush);
255         }
256 }
257
258 void Canvas::get_zooms(EDL *edl, 
259         int single_channel, 
260         float &zoom_x, 
261         float &zoom_y,
262         float &conformed_w,
263         float &conformed_h)
264 {
265         edl->calculate_conformed_dimensions(single_channel, 
266                 conformed_w, 
267                 conformed_h);
268
269         if(use_scrollbars)
270         {
271                 zoom_x = get_zoom() * 
272                         conformed_w / 
273                         edl->session->output_w;
274                 zoom_y = get_zoom() * 
275                         conformed_h / 
276                         edl->session->output_h;
277         }
278         else
279         {
280                 int out_w, out_h;
281                 int canvas_w = get_canvas()->get_w();
282                 int canvas_h = get_canvas()->get_h();
283         
284                 out_w = canvas_w;
285                 out_h = canvas_h;
286
287                 if((float)out_w / out_h > conformed_w / conformed_h)
288                 {
289                         out_w = (int)((float)out_h * conformed_w / conformed_h + 0.5);
290                 }
291                 else
292                 {
293                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
294                 }
295
296                 zoom_x = (float)out_w / edl->session->output_w;
297                 zoom_y = (float)out_h / edl->session->output_h;
298 //printf("get zooms 2 %d %d %f %f\n", canvas_w, canvas_h, conformed_w, conformed_h);
299         }
300 }
301
302 // Convert a coordinate on the canvas to a coordinate on the output
303 void Canvas::canvas_to_output(EDL *edl, int single_channel, float &x, float &y)
304 {
305         float zoom_x, zoom_y, conformed_w, conformed_h;
306         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
307
308 //printf("Canvas::canvas_to_output y=%f zoom_y=%f y_offset=%f\n", 
309 //      y, zoom_y, get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
310
311         x = (float)x / zoom_x + get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h);
312         y = (float)y / zoom_y + get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h);
313 }
314
315 void Canvas::output_to_canvas(EDL *edl, int single_channel, float &x, float &y)
316 {
317         float zoom_x, zoom_y, conformed_w, conformed_h;
318         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
319
320 //printf("Canvas::output_to_canvas x=%f zoom_x=%f x_offset=%f\n", x, zoom_x, get_x_offset(edl, single_channel, zoom_x, conformed_w));
321
322         x = (float)zoom_x * (x - get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h));
323         y = (float)zoom_y * (y - get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
324 }
325
326
327
328 void Canvas::get_transfers(EDL *edl, 
329         float &output_x1, float &output_y1, float &output_x2, float &output_y2,
330         float &canvas_x1, float &canvas_y1, float &canvas_x2, float &canvas_y2,
331         int canvas_w, int canvas_h)
332 {
333 // printf("Canvas::get_transfers %d %d\n", canvas_w, 
334 //              canvas_h);
335 // automatic canvas size detection
336         if(canvas_w < 0) canvas_w = get_canvas()->get_w();
337         if(canvas_h < 0) canvas_h = get_canvas()->get_h();
338
339 // Canvas is zoomed to a portion of the output frame
340         if(use_scrollbars)
341         {
342                 float in_x1, in_y1, in_x2, in_y2;
343                 float out_x1, out_y1, out_x2, out_y2;
344                 float zoom_x, zoom_y, conformed_w, conformed_h;
345
346                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
347                 out_x1 = 0;
348                 out_y1 = 0;
349                 out_x2 = canvas_w;
350                 out_y2 = canvas_h;
351                 in_x1 = 0;
352                 in_y1 = 0;
353                 in_x2 = canvas_w;
354                 in_y2 = canvas_h;
355
356                 canvas_to_output(edl, 0, in_x1, in_y1);
357                 canvas_to_output(edl, 0, in_x2, in_y2);
358
359 //printf("Canvas::get_transfers 1 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
360 //in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
361
362                 if(in_x1 < 0)
363                 {
364                         out_x1 += -in_x1 * zoom_x;
365                         in_x1 = 0;
366                 }
367
368                 if(in_y1 < 0)
369                 {
370                         out_y1 += -in_y1 * zoom_y;
371                         in_y1 = 0;
372                 }
373
374                 int output_w = get_output_w(edl);
375                 int output_h = get_output_h(edl);
376
377                 if(in_x2 > output_w)
378                 {
379                         out_x2 -= (in_x2 - output_w) * zoom_x;
380                         in_x2 = output_w;
381                 }
382
383                 if(in_y2 > output_h)
384                 {
385                         out_y2 -= (in_y2 - output_h) * zoom_y;
386                         in_y2 = output_h;
387                 }
388 // printf("Canvas::get_transfers 2 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
389 //                      in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
390
391                 output_x1 = in_x1;
392                 output_y1 = in_y1;
393                 output_x2 = in_x2;
394                 output_y2 = in_y2;
395                 canvas_x1 = out_x1;
396                 canvas_y1 = out_y1;
397                 canvas_x2 = out_x2;
398                 canvas_y2 = out_y2;
399
400 // Center on canvas
401 //              if(!scrollbars_exist())
402 //              {
403 //                      out_x = canvas_w / 2 - out_w / 2;
404 //                      out_y = canvas_h / 2 - out_h / 2;
405 //              }
406
407         }
408         else
409 // The output frame is normalized to the canvas
410         {
411 // Default canvas coords fill the entire canvas
412                 canvas_x1 = 0;
413                 canvas_y1 = 0;
414                 canvas_x2 = canvas_w;
415                 canvas_y2 = canvas_h;
416
417                 if(edl)
418                 {
419 // Use EDL aspect ratio to shrink one of the canvas dimensions
420                         float out_w = canvas_x2 - canvas_x1;
421                         float out_h = canvas_y2 - canvas_y1;
422                         if(out_w / out_h > edl->get_aspect_ratio())
423                         {
424                                 out_w = (int)(out_h * edl->get_aspect_ratio() + 0.5);
425                                 canvas_x1 = canvas_w / 2 - out_w / 2;
426                         }
427                         else
428                         {
429                                 out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5);
430                                 canvas_y1 = canvas_h / 2 - out_h / 2;
431                         }
432                         canvas_x2 = canvas_x1 + out_w;
433                         canvas_y2 = canvas_y1 + out_h;
434
435 // Get output frame coords from EDL
436                         output_x1 = 0;
437                         output_y1 = 0;
438                         output_x2 = get_output_w(edl);
439                         output_y2 = get_output_h(edl);
440                 }
441                 else
442 // No EDL to get aspect ratio or output frame coords from
443                 {
444                         output_x1 = 0;
445                         output_y1 = 0;
446                         output_x2 = this->output_w;
447                         output_y2 = this->output_h;
448                 }
449         }
450
451 // Clamp to minimum value
452         output_x1 = MAX(0, output_x1);
453         output_y1 = MAX(0, output_y1);
454         output_x2 = MAX(output_x1, output_x2);
455         output_y2 = MAX(output_y1, output_y2);
456         canvas_x1 = MAX(0, canvas_x1);
457         canvas_y1 = MAX(0, canvas_y1);
458         canvas_x2 = MAX(canvas_x1, canvas_x2);
459         canvas_y2 = MAX(canvas_y1, canvas_y2);
460 // printf("Canvas::get_transfers 2 %f,%f %f,%f -> %f,%f %f,%f\n",
461 // output_x1,
462 // output_y1,
463 // output_x2,
464 // output_y2,
465 // canvas_x1,
466 // canvas_y1,
467 // canvas_x2,
468 // canvas_y2);
469 }
470
471 int Canvas::scrollbars_exist()
472 {
473         return(use_scrollbars && (xscroll || yscroll));
474 }
475
476 int Canvas::get_output_w(EDL *edl)
477 {
478         return !edl ? 0 : edl->session->output_w;
479 }
480
481 int Canvas::get_output_h(EDL *edl)
482 {
483         return !edl ? 0 : edl->session->output_h;
484 }
485
486
487
488 void Canvas::get_scrollbars(EDL *edl, 
489         int &canvas_x, 
490         int &canvas_y, 
491         int &canvas_w, 
492         int &canvas_h)
493 {
494         int need_xscroll = 0;
495         int need_yscroll = 0;
496 //      int done = 0;
497         float zoom_x, zoom_y, conformed_w, conformed_h;
498
499         if(edl)
500         {
501                 w_needed = edl->session->output_w;
502                 h_needed = edl->session->output_h;
503                 w_visible = w_needed;
504                 h_visible = h_needed;
505         }
506 //printf("Canvas::get_scrollbars 1 %d %d\n", get_xscroll(), get_yscroll());
507
508         if(use_scrollbars)
509         {
510                 w_needed = edl->session->output_w;
511                 h_needed = edl->session->output_h;
512                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
513 //printf("Canvas::get_scrollbars 2 %d %d\n", get_xscroll(), get_yscroll());
514
515 //              while(!done)
516 //              {
517                         w_visible = (int)(canvas_w / zoom_x);
518                         h_visible = (int)(canvas_h / zoom_y);
519 //                      done = 1;
520
521 //                      if(w_needed > w_visible)
522                         if(1)
523                         {
524                                 if(!need_xscroll)
525                                 {
526                                         need_xscroll = 1;
527                                         canvas_h -= BC_ScrollBar::get_span(SCROLL_HORIZ);
528 //                                      done = 0;
529                                 }
530                         }
531                         else
532                                 need_xscroll = 0;
533
534 //                      if(h_needed > h_visible)
535                         if(1)
536                         {
537                                 if(!need_yscroll)
538                                 {
539                                         need_yscroll = 1;
540                                         canvas_w -= BC_ScrollBar::get_span(SCROLL_VERT);
541 //                                      done = 0;
542                                 }
543                         }
544                         else
545                                 need_yscroll = 0;
546 //              }
547 //printf("Canvas::get_scrollbars %d %d %d %d %d %d\n", canvas_w, canvas_h, w_needed, h_needed, w_visible, h_visible);
548 //printf("Canvas::get_scrollbars 3 %d %d\n", get_xscroll(), get_yscroll());
549
550                 w_visible = (int)(canvas_w / zoom_x);
551                 h_visible = (int)(canvas_h / zoom_y);
552         }
553
554         if(need_xscroll)
555         {
556                 if(!xscroll)
557                 {
558                         subwindow->add_subwindow(xscroll =
559                                 new CanvasXScroll(edl, this, canvas_x, canvas_y + canvas_h,
560                                         w_needed, get_xscroll(), w_visible, canvas_w));
561                         xscroll->show_window(0);
562                 }
563                 else
564                         xscroll->reposition_window(canvas_x, canvas_y + canvas_h, canvas_w);
565
566                 if(xscroll->get_length() != w_needed ||
567                         xscroll->get_handlelength() != w_visible)
568                         xscroll->update_length(w_needed, get_xscroll(), w_visible, 0);
569         }
570         else
571         {
572                 if( xscroll ) { delete xscroll;  xscroll = 0; }
573         }
574 //printf("Canvas::get_scrollbars 4 %d %d\n", get_xscroll(), get_yscroll());
575
576         if(need_yscroll)
577         {
578                 if(!yscroll)
579                 {
580                         subwindow->add_subwindow(yscroll =
581                                 new CanvasYScroll(edl, this, canvas_x + canvas_w, canvas_y,
582                                         h_needed, get_yscroll(), h_visible, canvas_h));
583                         yscroll->show_window(0);
584                 }
585                 else
586                         yscroll->reposition_window(canvas_x + canvas_w, canvas_y, canvas_h);
587
588                 if(yscroll->get_length() != edl->session->output_h ||
589                         yscroll->get_handlelength() != h_visible)
590                         yscroll->update_length(h_needed, get_yscroll(), h_visible, 0);
591         }
592         else
593         {
594                 if( yscroll ) { delete yscroll;  yscroll = 0; }
595         }
596 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
597 }
598
599 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
600 {
601         this->x = view_x = x;  this->y = view_y = y;
602         this->w = view_w = w;  this->h = view_h = h;
603 //printf("Canvas::reposition_window 1\n");
604         get_scrollbars(edl, view_x, view_y, view_w, view_h);
605 //printf("Canvas::reposition_window %d %d %d %d\n", view_x, view_y, view_w, view_h);
606         if(canvas_subwindow)
607         {
608                 canvas_subwindow->reposition_window(view_x, view_y, view_w, view_h);
609
610 // Need to clear out the garbage in the back
611                 if(canvas_subwindow->get_video_on())
612                 {
613                         canvas_subwindow->set_color(BLACK);
614                         canvas_subwindow->draw_box(0, 0, 
615                                 get_canvas()->get_w(), get_canvas()->get_h());
616                         canvas_subwindow->flash(0);
617                 }
618         }
619
620
621         draw_refresh(0);
622 }
623
624 void Canvas::set_cursor(int cursor)
625 {
626         get_canvas()->set_cursor(cursor, 0, 1);
627 }
628
629 int Canvas::get_cursor_x()
630 {
631         return get_canvas()->get_cursor_x();
632 }
633
634 int Canvas::get_cursor_y()
635 {
636         return get_canvas()->get_cursor_y();
637 }
638
639 int Canvas::get_buttonpress()
640 {
641         return get_canvas()->get_buttonpress();
642 }
643
644
645 void Canvas::create_objects(EDL *edl)
646 {
647         view_x = x;
648         view_y = y;
649         view_w = w;
650         view_h = h;
651         get_scrollbars(edl, view_x, view_y, view_w, view_h);
652
653         subwindow->unlock_window();
654         create_canvas();
655         subwindow->lock_window("Canvas::create_objects");
656
657         subwindow->add_subwindow(canvas_menu = new CanvasPopup(this));
658         canvas_menu->create_objects();
659
660         subwindow->add_subwindow(fullscreen_menu = new CanvasFullScreenPopup(this));
661         fullscreen_menu->create_objects();
662
663 }
664
665 int Canvas::button_press_event()
666 {
667         int result = 0;
668
669         if(get_canvas()->get_buttonpress() == 3)
670         {
671                 if(get_fullscreen())
672                         fullscreen_menu->activate_menu();
673                 else
674                         canvas_menu->activate_menu();
675                 result = 1;
676         }
677
678         return result;
679 }
680
681 void Canvas::start_single()
682 {
683         is_processing = 1;
684         status_event();
685 }
686
687 void Canvas::stop_single()
688 {
689         is_processing = 0;
690         status_event();
691 }
692
693 void Canvas::start_video()
694 {
695         if(get_canvas())
696         {
697                 get_canvas()->start_video();
698                 status_event();
699         }
700 }
701
702 void Canvas::stop_video()
703 {
704         if(get_canvas())
705         {
706                 get_canvas()->stop_video();
707                 status_event();
708         }
709 }
710
711
712 void Canvas::start_fullscreen()
713 {
714         set_fullscreen(1);
715         create_canvas();
716 }
717
718 void Canvas::stop_fullscreen()
719 {
720         set_fullscreen(0);
721         create_canvas();
722 }
723
724 void Canvas::create_canvas()
725 {
726         int video_on = 0;
727         lock_canvas("Canvas::create_canvas");
728
729
730         if(!get_fullscreen())
731 // Enter windowed
732         {
733                 if(canvas_fullscreen)
734                 {
735                         video_on = canvas_fullscreen->get_video_on();
736                         canvas_fullscreen->stop_video();
737                         canvas_fullscreen->lock_window("Canvas::create_canvas 2");
738                         canvas_fullscreen->hide_window();
739                         canvas_fullscreen->unlock_window();
740                 }
741
742                 if(!canvas_auxwindow && !canvas_subwindow)
743                 {
744                         subwindow->add_subwindow(canvas_subwindow = new CanvasOutput(this, 
745                                 view_x, 
746                                 view_y, 
747                                 view_w, 
748                                 view_h));
749                 }
750         }
751         else
752 // Enter fullscreen
753         {
754                 BC_WindowBase *wdw = canvas_auxwindow ?
755                         canvas_auxwindow : canvas_subwindow;
756                 if(wdw)
757                 {
758                         video_on = wdw->get_video_on();
759                         wdw->stop_video();
760                 }
761
762                 int x = subwindow->get_screen_x(0, -1);
763                 int y = subwindow->get_screen_y(0, -1);
764                 int w = root_w;
765                 int h = root_h;
766                 if( mwindow->screens == 1 && root_w > scr_w0 ) {
767                         // Xinerama
768                         if( subwindow->get_x() >= scr_w0 ) {
769                                 // assumes right side is the big one
770                                 w = root_w - scr_w0;
771                                 h = root_h;
772                         }
773                         else {
774                                 // use same aspect ratio to compute left height
775                                 w = scr_w0;
776                                 h = (w*root_h) / (root_w-scr_w0);
777                         }
778                 }
779
780                 if( canvas_fullscreen )
781                 {
782                         if( x != canvas_fullscreen->get_x() ||
783                             y != canvas_fullscreen->get_y() ||
784                             w != canvas_fullscreen->get_w() ||
785                             h != canvas_fullscreen->get_h() ) {
786                                 delete canvas_fullscreen;
787                                 canvas_fullscreen = 0;  
788                         }
789                 }
790                 if(!canvas_fullscreen)
791                 {
792                         canvas_fullscreen = new CanvasFullScreen(this, w, h);
793                 }
794                 else
795                 {
796                         canvas_fullscreen->reposition_window(x, y);
797                         canvas_fullscreen->show_window();
798                 }
799         }
800
801
802         if(!video_on)
803         {
804                 get_canvas()->lock_window("Canvas::create_canvas 1");
805                 draw_refresh();
806                 get_canvas()->unlock_window();
807         }
808
809         if(video_on) get_canvas()->start_video();
810
811         unlock_canvas();
812 }
813
814
815
816 int Canvas::cursor_leave_event_base(BC_WindowBase *caller)
817 {
818         int result = 0;
819         if(cursor_inside) result = cursor_leave_event();
820         cursor_inside = 0;
821         return result;
822 }
823
824 int Canvas::cursor_enter_event_base(BC_WindowBase *caller)
825 {
826         int result = 0;
827         if(caller->is_event_win() && caller->cursor_inside())
828         {
829                 cursor_inside = 1;
830                 result = cursor_enter_event();
831         }
832         return result;
833 }
834
835 int Canvas::button_press_event_base(BC_WindowBase *caller)
836 {
837         if(caller->is_event_win() && caller->cursor_inside())
838         {
839                 return button_press_event();
840         }
841         return 0;
842 }
843
844 int Canvas::keypress_event(BC_WindowBase *caller)
845 {
846         int caller_is_canvas = (caller == get_canvas());
847         int key = caller->get_keypress();
848         switch( key ) {
849         case 'f':
850                 caller->unlock_window();
851                 if(get_fullscreen())
852                         stop_fullscreen();
853                 else
854                         start_fullscreen();
855                 if(!caller_is_canvas) caller->lock_window("Canvas::keypress_event 1");
856                 break;
857         case ESC:
858                 caller->unlock_window();
859                 if(get_fullscreen())
860                         stop_fullscreen();
861                 if(!caller_is_canvas) caller->lock_window("Canvas::keypress_event 2");
862                 break;
863         default:
864                 return 0;
865         }
866         return 1;
867 }
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885 CanvasOutput::CanvasOutput(Canvas *canvas,
886     int x,
887     int y,
888     int w,
889     int h)
890  : BC_SubWindow(x, y, w, h, BLACK)
891 {
892         this->canvas = canvas;
893 }
894
895 CanvasOutput::~CanvasOutput()
896 {
897 }
898
899 int CanvasOutput::cursor_leave_event()
900 {
901         return canvas->cursor_leave_event_base(this);
902 }
903
904 int CanvasOutput::cursor_enter_event()
905 {
906         return canvas->cursor_enter_event_base(this);
907 }
908
909 int CanvasOutput::button_press_event()
910 {
911         return canvas->button_press_event_base(this);
912 }
913
914 int CanvasOutput::button_release_event()
915 {
916         return canvas->button_release_event();
917 }
918
919 int CanvasOutput::cursor_motion_event()
920 {
921         return canvas->cursor_motion_event();
922 }
923
924 int CanvasOutput::keypress_event()
925 {
926         return canvas->keypress_event(this);
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940
941 CanvasFullScreen::CanvasFullScreen(Canvas *canvas,
942     int w,
943     int h)
944  : BC_FullScreen(canvas->subwindow, 
945         w, 
946         h, 
947         BLACK,
948         0,
949         0,
950         0)
951 {
952         this->canvas = canvas;
953 }
954
955 CanvasFullScreen::~CanvasFullScreen()
956 {
957 }
958
959
960
961
962
963
964
965
966
967
968
969
970
971 CanvasXScroll::CanvasXScroll(EDL *edl, 
972         Canvas *canvas, 
973     int x, 
974     int y, 
975         int length, 
976         int position, 
977         int handle_length,
978     int pixels)
979  : BC_ScrollBar(x, 
980                 y, 
981                 SCROLL_HORIZ, 
982                 pixels, 
983                 length, 
984                 position, 
985                 handle_length)
986 {
987         this->canvas = canvas;
988 }
989
990 CanvasXScroll::~CanvasXScroll()
991 {
992 }
993
994 int CanvasXScroll::handle_event()
995 {
996 //printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength());
997         canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom());
998         canvas->draw_refresh();
999         return 1;
1000 }
1001
1002
1003
1004
1005
1006
1007 CanvasYScroll::CanvasYScroll(EDL *edl, 
1008         Canvas *canvas, 
1009     int x, 
1010     int y, 
1011         int length, 
1012         int position, 
1013         int handle_length,
1014     int pixels)
1015  : BC_ScrollBar(x, 
1016                 y, 
1017                 SCROLL_VERT, 
1018                 pixels, 
1019                 length, 
1020                 position, 
1021                 handle_length)
1022 {
1023         this->canvas = canvas;
1024 }
1025
1026 CanvasYScroll::~CanvasYScroll()
1027 {
1028 }
1029
1030 int CanvasYScroll::handle_event()
1031 {
1032 //printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length());
1033         canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom());
1034         canvas->draw_refresh();
1035         return 1;
1036 }
1037
1038
1039
1040
1041
1042
1043 CanvasFullScreenPopup::CanvasFullScreenPopup(Canvas *canvas)
1044  : BC_PopupMenu(0, 0, 0, "", 0)
1045 {
1046         this->canvas = canvas;
1047 }
1048
1049
1050 void CanvasFullScreenPopup::create_objects()
1051 {
1052         add_item(new CanvasSubWindowItem(canvas));
1053 }
1054
1055 void CanvasFullScreenPopup::use_cwindow()
1056 {
1057         add_item(new CanvasPopupAuto(canvas));
1058 }
1059
1060 CanvasSubWindowItem::CanvasSubWindowItem(Canvas *canvas)
1061  : BC_MenuItem(_("Windowed"), "f", 'f')
1062 {
1063         this->canvas = canvas;
1064 }
1065
1066 int CanvasSubWindowItem::handle_event()
1067 {
1068 // It isn't a problem to delete the canvas from in here because the event
1069 // dispatcher is the canvas subwindow.
1070         canvas->subwindow->unlock_window();
1071         canvas->stop_fullscreen();
1072         canvas->subwindow->lock_window("CanvasSubWindowItem::handle_event");
1073         return 1;
1074 }
1075
1076
1077
1078
1079
1080
1081
1082
1083 CanvasPopup::CanvasPopup(Canvas *canvas)
1084  : BC_PopupMenu(0, 0, 0, "", 0)
1085 {
1086         this->canvas = canvas;
1087 }
1088
1089 CanvasPopup::~CanvasPopup()
1090 {
1091 }
1092
1093 void CanvasPopup::create_objects()
1094 {
1095         add_item(new CanvasFullScreenItem(canvas));
1096         add_item(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
1097         add_item(new CanvasPopupSize(canvas, _("Zoom 33%"), 0.33));
1098         add_item(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
1099         add_item(new CanvasPopupSize(canvas, _("Zoom 75%"), 0.75));
1100         add_item(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
1101         add_item(new CanvasPopupSize(canvas, _("Zoom 150%"), 1.5));
1102         add_item(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
1103         add_item(new CanvasPopupSize(canvas, _("Zoom 300%"), 3.0));
1104         add_item(new CanvasPopupSize(canvas, _("Zoom 400%"), 4.0));
1105 }
1106
1107 void CanvasPopup::use_cwindow()
1108 {
1109         add_item(new CanvasPopupAuto(canvas));
1110         add_item(new CanvasPopupResetCamera(canvas));
1111         add_item(new CanvasPopupResetProjector(canvas));
1112         add_item(toggle_controls = new CanvasToggleControls(canvas));
1113 }
1114
1115 void CanvasPopup::use_rwindow()
1116 {
1117         add_item(new CanvasPopupResetTranslation(canvas));
1118 }
1119
1120 void CanvasPopup::use_vwindow()
1121 {
1122         add_item(new CanvasPopupRemoveSource(canvas));
1123 }
1124
1125
1126 CanvasPopupAuto::CanvasPopupAuto(Canvas *canvas)
1127  : BC_MenuItem(_("Zoom Auto"))
1128 {
1129         this->canvas = canvas;
1130 }
1131
1132 int CanvasPopupAuto::handle_event()
1133 {
1134         canvas->zoom_auto();
1135         return 1;
1136 }
1137
1138
1139 CanvasPopupSize::CanvasPopupSize(Canvas *canvas, char *text, float percentage)
1140  : BC_MenuItem(text)
1141 {
1142         this->canvas = canvas;
1143         this->percentage = percentage;
1144 }
1145 CanvasPopupSize::~CanvasPopupSize()
1146 {
1147 }
1148 int CanvasPopupSize::handle_event()
1149 {
1150         canvas->zoom_resize_window(percentage);
1151         return 1;
1152 }
1153
1154
1155
1156 CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas)
1157  : BC_MenuItem(_("Reset camera"))
1158 {
1159         this->canvas = canvas;
1160 }
1161 int CanvasPopupResetCamera::handle_event()
1162 {
1163         canvas->reset_camera();
1164         return 1;
1165 }
1166
1167
1168
1169 CanvasPopupResetProjector::CanvasPopupResetProjector(Canvas *canvas)
1170  : BC_MenuItem(_("Reset projector"))
1171 {
1172         this->canvas = canvas;
1173 }
1174 int CanvasPopupResetProjector::handle_event()
1175 {
1176         canvas->reset_projector();
1177         return 1;
1178 }
1179
1180
1181
1182 CanvasPopupResetTranslation::CanvasPopupResetTranslation(Canvas *canvas)
1183  : BC_MenuItem(_("Reset translation"))
1184 {
1185         this->canvas = canvas;
1186 }
1187 int CanvasPopupResetTranslation::handle_event()
1188 {
1189         canvas->reset_translation();
1190         return 1;
1191 }
1192
1193
1194
1195 CanvasToggleControls::CanvasToggleControls(Canvas *canvas)
1196  : BC_MenuItem(calculate_text(canvas->get_cwindow_controls()))
1197 {
1198         this->canvas = canvas;
1199 }
1200 int CanvasToggleControls::handle_event()
1201 {
1202         canvas->toggle_controls();
1203         set_text(calculate_text(canvas->get_cwindow_controls()));
1204         return 1;
1205 }
1206
1207 char* CanvasToggleControls::calculate_text(int cwindow_controls)
1208 {
1209         if(!cwindow_controls) 
1210                 return _("Show controls");
1211         else
1212                 return _("Hide controls");
1213 }
1214
1215
1216
1217
1218
1219
1220
1221 CanvasFullScreenItem::CanvasFullScreenItem(Canvas *canvas)
1222  : BC_MenuItem(_("Fullscreen"), "f", 'f')
1223 {
1224         this->canvas = canvas;
1225 }
1226 int CanvasFullScreenItem::handle_event()
1227 {
1228         canvas->subwindow->unlock_window();
1229         canvas->start_fullscreen();
1230         canvas->subwindow->lock_window("CanvasFullScreenItem::handle_event");
1231         return 1;
1232 }
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242 CanvasPopupRemoveSource::CanvasPopupRemoveSource(Canvas *canvas)
1243  : BC_MenuItem(_("Close source"))
1244 {
1245         this->canvas = canvas;
1246 }
1247 int CanvasPopupRemoveSource::handle_event()
1248 {
1249         canvas->close_source();
1250         return 1;
1251 }
1252
1253