The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

GtkWindow.vala in birdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of birdfont/GtkWindow.vala.
Merge ../birdfont-2.x
1 /* 2 Copyright (C) 2012 2013 2014 2015 Johan Mattsson 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 using Cairo; 19 using Gtk; 20 using Gdk; 21 using BirdFont; 22 using WebKit; 23 using Gdk; 24 using Notify; 25 26 namespace BirdFont { 27 28 public class GtkWindow : Gtk.Window, NativeWindow { 29 30 Box list_box; 31 Box canvas_box; 32 33 WebView html_canvas; 34 ScrolledWindow html_box; 35 36 Box tab_box; 37 38 GlyphCanvasArea glyph_canvas_area; 39 40 Clipboard clipboard; 41 string clipboard_svg = ""; 42 string inkscape_clipboard = ""; 43 44 Scrollbar scrollbar; 45 bool scrollbar_supress_signal = false; 46 47 /** Text input and callbacks. */ 48 public static bool text_input_is_active = false; 49 TextListener text_listener = new TextListener ("", "", ""); 50 Label text_input_label; 51 Entry text_entry; 52 Box text_box; 53 Gtk.Button submit_text_button; 54 55 ToolboxCanvas toolbox; 56 57 Task background_task = new Task(idle); 58 59 public GtkWindow (string title) { 60 scrollbar = new Scrollbar (Orientation.VERTICAL, new Adjustment (0, 0, 1, 1, 0.01, 0.1)); 61 ((Gtk.Window)this).set_title ("BirdFont"); 62 } 63 64 public static void idle () { 65 } 66 67 public void init () { 68 Notify.init ("Fonts have been exported."); 69 70 clipboard = Clipboard.get_for_display (get_display (), Gdk.SELECTION_CLIPBOARD); 71 72 Signal.connect(this, "notify::is-active", (GLib.Callback) window_focus, null); 73 74 scrollbar.value_changed.connect (() => { 75 double p; 76 77 if (!scrollbar_supress_signal) { 78 p = scrollbar.get_value () / (1 - scrollbar.adjustment.page_size); 79 FontDisplay display = MainWindow.get_current_display (); 80 display.scroll_to (p); 81 } 82 }); 83 84 delete_event.connect (() => { 85 MenuTab.quit (); 86 return true; 87 }); 88 89 set_size_and_position (); 90 91 glyph_canvas_area = new GlyphCanvasArea (MainWindow.glyph_canvas); 92 93 html_canvas = new WebView (); 94 WebKit.set_cache_model (CacheModel.DOCUMENT_VIEWER); 95 html_canvas.get_settings ().enable_default_context_menu = false; 96 97 html_box = new ScrolledWindow (null, null); 98 html_box.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC); 99 html_box.add (html_canvas); 100 html_canvas.set_editable (true); 101 102 MainWindow.get_tab_bar ().signal_tab_selected.connect ((f, tab) => { 103 string uri = ""; 104 string html = ""; 105 FontDisplay fd = tab.get_display (); 106 107 scrollbar.set_visible (fd.has_scrollbar ()); 108 109 if (fd.get_name () == "Preview") { 110 uri = Preview.get_uri (); 111 html = Preview.get_html_with_absolute_paths (); 112 113 html_canvas.load_html_string (html, uri); 114 115 // show the webview when loading has finished 116 html_box.set_visible (true); 117 glyph_canvas_area.set_visible (false); 118 } else { 119 html_box.set_visible (false); 120 glyph_canvas_area.set_visible (true); 121 } 122 }); 123 124 // Hide this canvas when window is realized and flip canvas 125 // visibility in tab selection signal. 126 html_canvas.draw.connect ((t, e) => { 127 glyph_canvas_area.set_visible (false); 128 return false; 129 }); 130 131 canvas_box = new Box (Orientation.HORIZONTAL, 0); 132 canvas_box.pack_start (glyph_canvas_area, true, true, 0); 133 canvas_box.pack_start (html_box, true, true, 0); 134 canvas_box.pack_start (scrollbar, false, true, 0); 135 136 submit_text_button = new Gtk.Button (); 137 submit_text_button.set_label ("Submit"); 138 text_input_label = new Label (" " + "Text"); 139 text_entry = new Entry (); 140 text_box = new Box (Orientation.HORIZONTAL, 6); 141 text_box.pack_start (text_input_label, false, false, 0); 142 text_box.pack_start (text_entry, true, true, 0); 143 text_box.pack_start (submit_text_button, false, false, 0); 144 145 text_entry.changed.connect (() => { 146 text_listener.signal_text_input (text_entry.text); 147 }); 148 149 submit_text_button.clicked.connect (() => { 150 text_listener.signal_submit (text_entry.text); 151 text_input_is_active = false; 152 }); 153 154 tab_box = new Box (Orientation.VERTICAL, 0); 155 156 tab_box.pack_start (new TabbarCanvas (MainWindow.get_tab_bar ()), false, false, 0); 157 tab_box.pack_start (text_box, false, false, 5); 158 tab_box.pack_start (canvas_box, true, true, 0); 159 160 toolbox = new ToolboxCanvas (MainWindow.get_toolbox ()); 161 list_box = new Box (Orientation.HORIZONTAL, 0); 162 list_box.pack_start (toolbox, false, false, 0); 163 list_box.pack_start (tab_box, true, true, 0); 164 165 Box vbox = new Box (Orientation.VERTICAL, 0); 166 vbox.pack_start(list_box, true, true, 0); 167 add (vbox); 168 169 try { 170 set_icon_from_file ((!) SearchPaths.find_file (null, "birdfont_window_icon.png").get_path ()); 171 } catch (GLib.Error e) { 172 warning (e.message); 173 } 174 175 key_press_event.connect ((t, event) => { 176 if (!GtkWindow.text_input_is_active) { 177 GtkWindow.reset_modifier (event.state); 178 TabContent.key_press (event.keyval); 179 } 180 181 return false; 182 }); 183 184 key_release_event.connect ((t, event) => { 185 if (!GtkWindow.text_input_is_active) { 186 TabContent.key_release (event.keyval); 187 } 188 189 return false; 190 }); 191 192 size_allocate.connect(() => { 193 GlyphCanvas.redraw (); 194 }); 195 196 show_all (); 197 198 scrollbar.set_visible (false); 199 200 hide_text_input (); 201 202 MainWindow.open_recent_files_tab (); 203 } 204 205 public void window_focus (void* data) { 206 TabContent.reset_modifier (); 207 } 208 209 public static void reset_modifier (ModifierType flags) { 210 if ((flags & ModifierType.CONTROL_MASK) == 0) { 211 TabContent.key_release (Key.CTRL_RIGHT); 212 TabContent.key_release (Key.CTRL_LEFT); 213 } 214 215 if ((flags & ModifierType.SHIFT_MASK) == 0) { 216 TabContent.key_release (Key.SHIFT_LEFT); 217 TabContent.key_release (Key.SHIFT_RIGHT); 218 } 219 220 if ((flags & ModifierType.MOD1_MASK) == 0) { 221 TabContent.key_release (Key.ALT_LEFT); 222 TabContent.key_release (Key.ALT_RIGHT); 223 } 224 225 if ((flags & ModifierType.MOD5_MASK) == 0) { 226 TabContent.key_release (Key.LOGO_LEFT); 227 TabContent.key_release (Key.LOGO_RIGHT); 228 } 229 } 230 231 public void font_loaded () { 232 Font f = BirdFont.get_current_font (); 233 set_title (@"$(f.full_name)"); 234 } 235 236 public void set_scrollbar_size (double size) { 237 scrollbar.adjustment.page_size = size; 238 scrollbar.set_visible (size != 0); 239 } 240 241 public void set_scrollbar_position (double position) { 242 scrollbar_supress_signal = true; 243 scrollbar.adjustment.value = position * (1 - scrollbar.adjustment.page_size); 244 scrollbar_supress_signal = false; 245 } 246 247 public void dump_clipboard_content (Clipboard clipboard, SelectionData selection_data) { 248 string d; 249 return_if_fail (!is_null (selection_data)); 250 d = (string) ((!) selection_data); 251 stdout.printf (d); 252 } 253 254 public void dump_clipboard_target (Clipboard clipboard, Atom[] atoms) { 255 foreach (Atom target in atoms) { 256 print ("Target: " + target.name () + "\n"); 257 clipboard.request_contents (target, dump_clipboard_content); 258 } 259 } 260 261 public void dump_clipboard () { 262 clipboard.request_targets (dump_clipboard_target); 263 } 264 265 public string get_clipboard_data () { 266 SelectionData? selection_data; 267 Atom target; 268 string? t; 269 270 target = Atom.intern_static_string ("image/x-inkscape-svg"); 271 selection_data = clipboard.wait_for_contents (target); 272 273 if (!is_null (selection_data)) { 274 return (string) (((!) selection_data).get_data ()); 275 } 276 277 t = clipboard.wait_for_text (); 278 if (t != null) { 279 return (!) t; 280 } 281 282 return ""; 283 } 284 285 public void set_inkscape_clipboard (string inkscape_clipboard_data) { 286 if (BirdFont.mac) { 287 clipboard.set_text (inkscape_clipboard_data, -1); 288 } else { 289 TargetEntry t = { "image/x-inkscape-svg", 0, 0 }; 290 TargetEntry[] targets = { t }; 291 inkscape_clipboard = inkscape_clipboard_data; 292 293 // we can not add data to this closure because the third argument 294 // is owner and not private data. 295 clipboard.set_with_owner (targets, 296 297 // obtain clipboard data 298 (clipboard, selection_data, info, owner) => { 299 Atom type; 300 uchar[] data = (uchar[])(!)((GtkWindow*)owner)->inkscape_clipboard.to_utf8 (); 301 type = Atom.intern_static_string ("image/x-inkscape-svg"); 302 selection_data.set (type, 8, data); 303 }, 304 305 // clear clipboard data 306 (clipboard, user_data) => { 307 }, 308 309 this); 310 } 311 } 312 313 public void set_clipboard_text (string text) { 314 clipboard.set_text (text, -1); 315 } 316 317 public string get_clipboard_text () { 318 string? t; 319 320 t = clipboard.wait_for_text (); 321 if (t != null) { 322 return ((!) t).dup (); 323 } 324 325 return "".dup (); 326 } 327 328 public void set_clipboard (string svg) { 329 TargetEntry t = { "image/svg+xml", 0, 0 }; 330 TargetEntry[] targets = { t }; 331 clipboard_svg = svg; 332 clipboard.set_with_owner (targets, 333 334 // obtain clipboard data 335 (clipboard, selection_data, info, owner) => { 336 Atom type; 337 uchar[] data = (uchar[])(!)((GtkWindow*)owner)->clipboard_svg.to_utf8 (); 338 type = Atom.intern_static_string ("image/svg+xml"); 339 selection_data.set (type, 0, data); 340 }, 341 342 // clear clipboard data 343 (clipboard, user_data) => { 344 }, 345 346 this); 347 } 348 349 public void update_window_size () { 350 int w, h; 351 get_size (out w, out h); 352 353 Preferences.set ("window_width", @"$w"); 354 Preferences.set ("window_height", @"$h"); 355 } 356 357 private void set_size_and_position () { 358 int w = Preferences.get_window_width (); 359 int h = Preferences.get_window_height (); 360 set_default_size (w, h); 361 } 362 363 public void quit () { 364 Gtk.main_quit (); 365 } 366 367 public void file_chooser (string title, FileChooser fc, uint flags) { 368 string? fn = null; 369 bool folder; 370 if (BirdFont.get_arguments () .has_argument ("--windows")) { 371 folder = (flags & FileChooser.DIRECTORY) > 0; 372 MenuTab.show_file_dialog_tab (title, fc, folder); 373 } else { 374 if ((flags & FileChooser.DIRECTORY) > 0) { 375 if ((flags & FileChooser.LOAD) > 0) { 376 fn = show_file_chooser (title, FileChooserAction.SELECT_FOLDER, Stock.OPEN); 377 } else if ((flags & FileChooser.SAVE) > 0) { 378 fn = show_file_chooser (title, FileChooserAction.SELECT_FOLDER, Stock.SAVE); 379 } else { 380 warning ("Open or save is not set."); 381 } 382 } else if ((flags & FileChooser.LOAD) > 0) { 383 fn = show_file_chooser (title, FileChooserAction.OPEN, Stock.OPEN); 384 } else if ((flags & FileChooser.SAVE) > 0) { 385 fn = show_file_chooser (title, FileChooserAction.SAVE, Stock.SAVE); 386 } else { 387 warning ("Unknown type"); 388 } 389 } 390 391 fc.selected (fn); 392 } 393 394 public string? show_file_chooser (string title, FileChooserAction action, string label) { 395 string? fn = null; 396 FileChooserDialog file_chooser = new FileChooserDialog (title, this, action, Stock.CANCEL, ResponseType.CANCEL, label, ResponseType.ACCEPT); 397 Font font = BirdFont.get_current_font (); 398 int i; 399 string last_folder; 400 401 last_folder = Preferences.get ("last_folder"); 402 403 try { 404 if (last_folder == "") { 405 file_chooser.set_current_folder_file (font.get_folder ()); 406 } else { 407 file_chooser.set_current_folder_file (File.new_for_path (last_folder)); 408 } 409 } catch (GLib.Error e) { 410 stderr.printf (e.message); 411 } 412 413 if (file_chooser.run () == ResponseType.ACCEPT) { 414 GlyphCanvas.redraw (); 415 fn = file_chooser.get_filename (); 416 } 417 418 file_chooser.destroy (); 419 420 if (fn != null) { 421 i = ((!) fn).last_index_of ("/"); 422 if (i > -1) { 423 last_folder = ((!) fn).substring (0, i); 424 Preferences.set ("last_folder", @"$last_folder"); 425 } 426 } 427 428 return fn; 429 } 430 431 public void hide_text_input () { 432 text_listener = new TextListener ("", "", ""); 433 text_box.hide (); 434 text_input_is_active = false; 435 } 436 437 public void set_text_listener (TextListener listener) { 438 text_listener = listener; 439 text_input_label.set_text (" " + listener.label); 440 submit_text_button.set_label (listener.button_label); 441 text_box.show (); 442 text_entry.set_text (listener.default_text); 443 text_entry.activate.connect (() => { 444 text_listener.signal_submit (text_entry.text); 445 text_input_is_active = false; 446 }); 447 text_entry.grab_focus (); 448 text_input_is_active = true; 449 } 450 451 public bool convert_to_png (string from, string to) { 452 Pixbuf pixbuf; 453 string folder; 454 int i; 455 456 try { 457 i = to.last_index_of ("/"); 458 if (i != -1) { 459 folder = to.substring (0, i); 460 DirUtils.create (folder, 0xFFFFFF); 461 } 462 463 pixbuf = new Pixbuf.from_file (from); 464 pixbuf.save (to, "png"); 465 } catch (GLib.Error e) { 466 warning (e.message); 467 return false; 468 } 469 470 return true; 471 } 472 473 public void run_background_thread (Task t) { 474 unowned Thread<void*> bg; 475 476 MenuTab.start_background_thread (); 477 background_task = t; 478 479 try { 480 bg = Thread.create<void*> (this.background_thread, true); 481 } catch (GLib.Error e) { 482 warning (e.message); 483 } 484 } 485 486 public void run_non_blocking_background_thread (Task t) { 487 unowned Thread<void*> bg; 488 489 try { 490 bg = Thread.create<void*> (t.perform_task, true); 491 } catch (GLib.Error e) { 492 warning (e.message); 493 } 494 } 495 496 public void* background_thread () { 497 background_task.run (); 498 MenuTab.stop_background_thread (); 499 return null; 500 } 501 502 /** Run export in a background thread. */ 503 public void export_font () { 504 unowned Thread<void*> export_thread; 505 506 MenuTab.start_background_thread (); 507 508 try { 509 export_thread = Thread.create<void*> (this.export_thread, true); 510 } catch (GLib.Error e) { 511 warning (e.message); 512 } 513 } 514 515 public void* export_thread () { 516 IdleSource idle = new IdleSource (); 517 518 ExportCallback.export_fonts (); 519 MenuTab.stop_background_thread (); 520 MenuTab.signal_file_exported (); 521 522 idle.set_callback (() => { 523 Notify.Notification export_notification; 524 export_notification = new Notify.Notification ("BirdFont", t_("Your fonts have been exported."), null); 525 export_notification.show (); 526 return false; 527 }); 528 idle.attach (null); 529 530 return null; 531 } 532 533 /** Load font in a background thread. */ 534 public void load () { 535 unowned Thread<void*> thread; 536 537 MenuTab.start_background_thread (); 538 539 try { 540 thread = Thread.create<void*> (this.loading_thread, true); 541 } catch (GLib.Error e) { 542 warning (e.message); 543 } 544 } 545 546 public void* loading_thread () { 547 BirdFont.get_current_font ().load (); 548 MenuTab.stop_background_thread (); 549 MenuTab.signal_file_loaded (); 550 return null; 551 } 552 553 /** Save font in a background thread. */ 554 public void save () { 555 unowned Thread<void*> thread; 556 557 MenuTab.start_background_thread (); 558 559 try { 560 thread = Thread.create<void*> (this.saving_thread, true); 561 } catch (GLib.Error e) { 562 warning (e.message); 563 } 564 } 565 566 public void* saving_thread () { 567 BirdFont.get_current_font ().save (); 568 MenuTab.stop_background_thread (); 569 MenuTab.signal_file_saved (); 570 return null; 571 } 572 573 public void load_background_image () { 574 unowned Thread<void*> thread; 575 576 MenuTab.start_background_thread (); 577 578 try { 579 thread = Thread.create<void*> (this.background_image_thread, true); 580 } catch (GLib.Error e) { 581 warning (e.message); 582 } 583 } 584 585 public void* background_image_thread () { 586 BackgroundTool.load_background_image (); 587 MenuTab.stop_background_thread (); 588 return null; 589 } 590 591 public bool can_export () { 592 return true; 593 } 594 595 public void set_cursor (int visible) { 596 if (visible != NativeWindow.VISIBLE) { 597 get_window ().set_cursor (new Cursor (CursorType.BLANK_CURSOR)); 598 } else { 599 get_window ().set_cursor (new Cursor (CursorType.ARROW)); 600 } 601 } 602 603 public double get_screen_scale () { 604 string? scale = Environment.get_variable ("GDK_SCALE"); 605 double factor; 606 607 if (scale == null) { 608 return 1; 609 } 610 611 if (double.try_parse ((!) scale, out factor)) { 612 return factor; 613 } 614 615 return 1; 616 } 617 } 618 619 class TabbarCanvas : DrawingArea { 620 TabBar tabbar; 621 622 public TabbarCanvas (TabBar tb) { 623 tabbar = tb; 624 625 add_events (EventMask.BUTTON_PRESS_MASK | EventMask.POINTER_MOTION_MASK | EventMask.LEAVE_NOTIFY_MASK); 626 627 motion_notify_event.connect ((t, e)=> { 628 Gtk.Allocation alloc; 629 tabbar.motion (e.x, e.y); 630 get_allocation (out alloc); 631 queue_draw_area (0, 0, alloc.width, alloc.height); 632 return true; 633 }); 634 635 button_press_event.connect ((t, e)=> { 636 Gtk.Allocation alloc; 637 get_allocation (out alloc); 638 GtkWindow.reset_modifier (e.state); 639 tabbar.select_tab_click (e.x, e.y, alloc.width, alloc.height); 640 queue_draw_area (0, 0, alloc.width, alloc.height); 641 return true; 642 }); 643 644 draw.connect ((t, e)=> { 645 Gtk.Allocation alloc; 646 Context cr; 647 StyleContext context; 648 Gdk.RGBA color; 649 650 cr = cairo_create (get_window ()); 651 get_allocation (out alloc); 652 653 context = get_style_context (); 654 context.add_class (STYLE_CLASS_BUTTON); 655 color = context.get_background_color (Gtk.StateFlags.NORMAL); 656 657 if (color.alpha > 0) { 658 tabbar.set_background_color (color.red, color.green, color.blue); 659 } 660 661 tabbar.draw (cr, alloc.width, alloc.height); 662 return true; 663 }); 664 665 tabbar.signal_tab_selected.connect ((t) => { 666 Gtk.Allocation alloc; 667 get_allocation (out alloc); 668 queue_draw_area (0, 0, alloc.width, alloc.height); 669 }); 670 671 tabbar.redraw_tab_bar.connect ((x, y, w, h) => { 672 queue_draw_area (x, y, w, h); 673 }); 674 675 set_size_request (20, 38); 676 } 677 678 } 679 680 class ToolboxCanvas : DrawingArea { 681 Toolbox tb; 682 683 public ToolboxCanvas (Toolbox toolbox) { 684 tb = toolbox; 685 686 realize.connect (() => { 687 Gtk.Allocation allocation; 688 get_allocation (out allocation); 689 Toolbox.allocation_width = allocation.width; 690 Toolbox.allocation_height = allocation.height; 691 Toolbox.redraw_tool_box (); 692 }); 693 694 tb.redraw.connect ((x, y, w, h) => { 695 queue_draw_area (x, y, w, h); 696 }); 697 698 button_press_event.connect ((se, e)=> { 699 if (e.type == EventType.2BUTTON_PRESS) { 700 tb.double_click (e.button, e.x, e.y); 701 } else { 702 tb.press (e.button, e.x, e.y); 703 } 704 return true; 705 }); 706 707 button_release_event.connect ((se, e)=> { 708 tb.release (e.button, e.x, e.y); 709 return true; 710 }); 711 712 motion_notify_event.connect ((sen, e)=> { 713 // FIXME: e.y is two pixels off in GTK under Gnome 714 tb.move (e.x, e.y); 715 return true; 716 }); 717 718 draw.connect ((t, e)=> { 719 Gtk.Allocation allocation; 720 get_allocation (out allocation); 721 722 Context cw = cairo_create(get_window()); 723 Toolbox.allocation_width = allocation.width; 724 Toolbox.allocation_height = allocation.height; 725 tb.draw (allocation.width, allocation.height, cw); 726 727 return true; 728 }); 729 730 scroll_event.connect ((t, e)=> { 731 if (e.direction == Gdk.ScrollDirection.UP) { 732 tb.scroll_up (e.x, e.y); 733 } else if (e.direction == Gdk.ScrollDirection.DOWN) { 734 tb.scroll_down (e.x, e.y); 735 } 736 return true; 737 }); 738 739 add_events (EventMask.BUTTON_PRESS_MASK | EventMask.BUTTON_RELEASE_MASK | EventMask.POINTER_MOTION_MASK | EventMask.LEAVE_NOTIFY_MASK | EventMask.SCROLL_MASK); 740 741 set_size_request (212, 100); 742 743 leave_notify_event.connect ((t, e)=> { 744 tb.reset_active_tool (); 745 return true; 746 }); 747 748 } 749 } 750 751 public class GlyphCanvasArea : DrawingArea { 752 GlyphCanvas glyph_canvas; 753 WidgetAllocation alloc = new WidgetAllocation (); 754 uint32 last_release = 0; 755 uint32 last_press = 0; 756 757 public GlyphCanvasArea (GlyphCanvas gc) { 758 int event_flags; 759 760 glyph_canvas = gc; 761 762 event_flags = EventMask.BUTTON_PRESS_MASK; 763 event_flags |= EventMask.BUTTON_RELEASE_MASK; 764 event_flags |= EventMask.POINTER_MOTION_MASK; 765 event_flags |= EventMask.LEAVE_NOTIFY_MASK; 766 event_flags |= EventMask.SCROLL_MASK; 767 768 add_events (event_flags); 769 770 bool button_down = false; 771 772 glyph_canvas.signal_redraw_area.connect ((x, y, w, h) => { 773 queue_draw_area ((int)x, (int)y, (int)w, (int)h); 774 }); 775 776 draw.connect ((t, e)=> { 777 Gtk.Allocation allocation; 778 get_allocation (out allocation); 779 780 alloc = new WidgetAllocation (); 781 782 alloc.width = allocation.width; 783 alloc.height = allocation.height; 784 alloc.x = allocation.x; 785 alloc.y = allocation.y; 786 787 Context cw = cairo_create (get_window()); 788 789 Surface s = new Surface.similar (cw.get_target (), Cairo.Content.COLOR_ALPHA, alloc.width, alloc.height); 790 Context c = new Context (s); 791 792 TabContent.draw (alloc, c); 793 794 cw.save (); 795 cw.set_source_surface (c.get_target (), 0, 0); 796 cw.paint (); 797 cw.restore (); 798 799 return true; 800 }); 801 802 button_press_event.connect ((t, e)=> { 803 GtkWindow.reset_modifier (e.state); 804 805 if (button_down) { 806 warning (@"Button already is down. $(e.button)"); 807 } 808 809 if (e.time < last_press) { 810 warning ("Discarding event."); 811 return true; 812 } 813 814 last_press = e.time; 815 816 if (e.type == EventType.BUTTON_PRESS) { 817 TabContent.button_press (e.button, e.x, e.y); 818 button_down = true; 819 } else if (e.type == EventType.2BUTTON_PRESS) { 820 TabContent.double_click (e.button, e.x, e.y); 821 } 822 823 return true; 824 }); 825 826 button_release_event.connect ((t, e)=> { 827 if (!button_down) { 828 warning (@"Button is not down $(e.button)"); 829 } 830 831 if (e.time < last_release) { 832 warning ("Discarding event."); 833 return true; 834 } 835 836 if (e.type == EventType.BUTTON_RELEASE) { 837 TabContent.button_release ((int) e.button, e.x, e.y); 838 last_release = e.time; 839 button_down = false; 840 } 841 842 return true; 843 }); 844 845 motion_notify_event.connect ((t, e)=> { 846 TabContent.motion_notify (e.x, e.y); 847 return true; 848 }); 849 850 scroll_event.connect ((t, e)=> { 851 if (e.direction == Gdk.ScrollDirection.UP) { 852 TabContent.scroll_wheel_up (e.x, e.y); 853 } else if (e.direction == Gdk.ScrollDirection.DOWN) { 854 TabContent.scroll_wheel_down (e.x, e.y) ; 855 } 856 857 TabContent.button_release (2, e.x, e.y); 858 return true; 859 }); 860 861 can_focus = true; 862 } 863 } 864 865 } 866