diff --git a/Applications/Internet/Cyberia.app/Cyberia.HC b/Applications/Internet/Cyberia.app/Cyberia.HC index a670563..655357d 100644 --- a/Applications/Internet/Cyberia.app/Cyberia.HC +++ b/Applications/Internet/Cyberia.app/Cyberia.HC @@ -28,9 +28,10 @@ I64 prev_win_height = -1; I64 prev_mouse_z = Mouse.z; Window* hanbaga_menu = Menu.New("Cyberia"); -Menu.AddItem(hanbaga_menu, "New Tab", NULL, &Reboot, NULL, NULL); -Menu.AddItem(hanbaga_menu, "New Window", NULL, NULL, NULL, NULL); -Menu.AddItem(hanbaga_menu, "New Private Window", NULL, NULL, NULL, NULL); +Window* link_context_menu = Menu.New("Cyberia"); + +Bool close_tabs_do_not_ask = FALSE; +Bool close_tabs_toggle_do_not_ask = close_tabs_do_not_ask; class @browser { @@ -116,6 +117,9 @@ U8* @cyberia_urlencode_str(U8* str, I64* output_len) U0 @cyberia_win_really_close(Window* win) { + if (close_tabs_toggle_do_not_ask) { + // FIXME: Handle this + } // Free everything if (win == Compositor.active_win) { Gui.Window.SetFocus(Compositor.GetWindowByTitle("Wallpaper")); @@ -125,13 +129,6 @@ U0 @cyberia_win_really_close(Window* win) Kill(app_event_loop); } -U0 @cyberia_win_close(Window* win) -{ - if (KeyDown(SC_CTRL) && KeyDown(Char2ScanCode('w'))) - return; - @cyberia_win_really_close(win); -} - U8* @browser_tls_connection_state(@http_response* resp) { if (!resp || !resp->s || !resp->s->ctx) @@ -162,7 +159,17 @@ U0 @cyberia_hanbaga_show(Widget* widget) Gui.Window.Refresh(hanbaga_menu); } -U0 @cyberia_link_clicked(Widget* widget) +U0 @cyberia_link_context_show(Widget* widget) +{ + no_warn widget; + link_context_menu->x = Mouse.x; + link_context_menu->y = Mouse.y; + Gui.Window.Show(link_context_menu); + Gui.Window.SetFocus(link_context_menu); + Gui.Window.Refresh(link_context_menu); +} + +U0 @cyberia_link_left_clicked(Widget* widget) { @html_dom_node* node = @self_or_ancestor_matches_tag_name(widget->data, "a"); if (!node) @@ -178,6 +185,23 @@ U0 @cyberia_link_clicked(Widget* widget) Spawn(&@cyberia_navigate); } +U0 @cyberia_link_right_clicked(Widget* widget) +{ + @cyberia_link_context_show(widget); +} + +U0 @cyberia_link_clicked(Widget* widget) +{ + if (Compositor.mouse.left) { + @cyberia_link_left_clicked(widget); + return; + } + if (Compositor.mouse.right) { + @cyberia_link_right_clicked(widget); + return; + } +} + U0 @cyberia_collect_form_nodes(JsonArray* array, @html_dom_node* node) { if (!array || !node) @@ -430,6 +454,13 @@ U0 @cyberia_init_renderer(HtmlRenderer* renderer, U8* url_string) renderer->task = browser_task; } +U0 @cyberia_msgbox_error_wrapper(U8* msg) +{ + while (*msg) { + OutU8(0xe9, *msg++); + } +} + U0 @cyberia_navigate(Bool refresh = FALSE) { win->focused_widget = NULL; @@ -470,14 +501,14 @@ U0 @cyberia_navigate(Bool refresh = FALSE) if (!renderer->current_url) { StrCpy(err_msg_buffer, "ERROR: Could not parse URL"); - MessageBox.Error(err_msg_buffer); + Spawn(&@cyberia_msgbox_error_wrapper, err_msg_buffer); Free(url_string); return; } if (!@is_supported_url_scheme(renderer->current_url)) { StrPrint(err_msg_buffer, "ERROR: Unsupported URL scheme: %s", renderer->current_url->scheme); - MessageBox.Error(err_msg_buffer); + Spawn(&@cyberia_msgbox_error_wrapper, err_msg_buffer); Free(url_string); return; } @@ -578,10 +609,22 @@ U0 @cyberia_navigate(Bool refresh = FALSE) @cyberia_history; @fetch_images_for_page(renderer); + if (!StrCmp(&addressbar1->text, "about:newtab")) { + win->focused_widget = addressbar1; + addressbar1->selected_region_start = 0; + addressbar1->selected_region_end = StrLen(&addressbar1->text) - 1; + } } -U0 @cyberia_new_tab() +U0 @cyberia_new_tab(Bool from_link_context_menu = FALSE) { + Gui.Window.SetFocus(win); + Gui.Window.Refresh(win); + U8* new_tab_destination_url = "about:newtab"; + if (from_link_context_menu) { + new_tab_destination_url = &status2->text; + } + TabPanelTab* new_tab = CAlloc(sizeof(TabPanelTab)); new_tab->icon = DEFAULT_FAVICON; StrCpy(&new_tab->text, "New Tab"); @@ -616,7 +659,7 @@ U0 @cyberia_new_tab() tabpanel1->index = i; ++tabpanel1->count; - StrCpy(&addressbar1->text, "about:newtab"); + StrCpy(&addressbar1->text, new_tab_destination_url); Spawn(&@cyberia_navigate); win->focused_widget = addressbar1; } @@ -906,6 +949,50 @@ U0 @cyberia_init_widgets_base() } } +U0 @cyberia_confirm_close_all_tabs(U64 o) +{ + // Assign value of win depending on if callback event is on a window, or a widget + Window* dialog = @t(o(Window*)->signature == WIN_SIGNATURE, o, o(Widget*)->parent_win); + if (dialog != o) { + switch (o(Widget*)->tag) { + case TRUE: + Compositor.DestroyWindow(dialog); + @cyberia_win_really_close(win); + return; + case MESSAGEBOX_TAG_CONFIRM_NO_ASK: + close_tabs_toggle_do_not_ask = !close_tabs_toggle_do_not_ask; + return; + default: + // Fall-through to destroy the confirm dialog by default + close_tabs_toggle_do_not_ask = close_tabs_do_not_ask; + break; + } + } + Compositor.DestroyWindow(dialog); +} + +U0 @cyberia_close_tabs_confirm_no_ask() +{ + if (tabpanel1->count > 1 && !close_tabs_do_not_ask) { + close_tabs_toggle_do_not_ask = close_tabs_do_not_ask; + MessageBox.ConfirmNoAsk("Are you sure you want to close all tabs?", &@cyberia_confirm_close_all_tabs); + } else { + @cyberia_win_really_close(win); + } +} + +U0 @cyberia_win_close(Window* win) +{ + if (KeyDown(SC_CTRL) && KeyDown(Char2ScanCode('w'))) + return; + if (tabpanel1->count > 1 && !close_tabs_do_not_ask) { + close_tabs_toggle_do_not_ask = close_tabs_do_not_ask; + MessageBox.ConfirmNoAsk("Are you sure you want to close all tabs?", &@cyberia_confirm_close_all_tabs); + } else { + @cyberia_win_really_close(win); + } +} + U0 @cyberia_init() { win = Compositor.CreateWindow(24, 24, 992, 768, WIN_FLAGS_DEFAULT); @@ -985,13 +1072,64 @@ U0 @cyberia_init() @cyberia_win_repaint(win); } +U0 @cyberia_context_menu_new_tab() +{ + @cyberia_new_tab(0); +} + +U0 @cyberia_context_menu_open_link_in_new_tab() +{ + @cyberia_new_tab(1); +} + +U0 @cyberia_copy_link() +{ + Gui.Window.SetFocus(win); + Gui.Window.Refresh(win); + Clipboard.Insert(CLIP_TYPE_TEXT, &status2->text); +} + +U0 @cyberia_context_menu_null_op() +{ + Gui.Window.SetFocus(win); + Gui.Window.Refresh(win); +} + +// Initialize context menus + +Menu.AddItem(hanbaga_menu, "New Tab", NULL, &@cyberia_context_menu_new_tab, NULL, NULL); +Menu.AddItem(hanbaga_menu, "New Window", NULL, &@cyberia_context_menu_null_op, NULL, NULL)->disabled = TRUE; +Menu.AddItem(hanbaga_menu, "New Private Window", NULL, &@cyberia_context_menu_null_op, NULL, NULL)->disabled = TRUE; +Menu.AddSeparator(hanbaga_menu); +Menu.AddItem(hanbaga_menu, "Bookmarks", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddItem(hanbaga_menu, "History", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddItem(hanbaga_menu, "Downloads", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddSeparator(hanbaga_menu); +Menu.AddItem(hanbaga_menu, "Settings", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddItem(hanbaga_menu, "Help", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddItem(hanbaga_menu, "Quit", NULL, &@cyberia_close_tabs_confirm_no_ask, NULL, NULL); + +Menu.AddItem(link_context_menu, "Open Link in New Tab", NULL, &@cyberia_context_menu_open_link_in_new_tab, NULL, NULL); +Menu.AddItem(link_context_menu, "Open Link in New Window", NULL, &@cyberia_context_menu_null_op, NULL, NULL)->disabled = TRUE; +Menu.AddItem(link_context_menu, "Open Link in New Private Window", NULL, &@cyberia_context_menu_null_op, NULL, NULL)->disabled = TRUE; +Menu.AddSeparator(link_context_menu); +Menu.AddItem(link_context_menu, "Bookmark Link", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddItem(link_context_menu, "Save Link as...", NULL, &@cyberia_context_menu_null_op, NULL, NULL); +Menu.AddItem(link_context_menu, "Copy Link", NULL, &@cyberia_copy_link, NULL, NULL); + @cyberia_init; +U0 @cyberia_hide_menu_if_inactive(Window* menu) +{ + if (Compositor.active_win != menu && Gui.Window.IsVisible(menu)) + Gui.Window.Hide(menu); +} + U0 Main() { while (1) { - if (Compositor.active_win != hanbaga_menu && Gui.Window.IsVisible(hanbaga_menu)) - Gui.Window.Hide(hanbaga_menu); + @cyberia_hide_menu_if_inactive(hanbaga_menu); + @cyberia_hide_menu_if_inactive(link_context_menu); Sleep(1); } }