focus on your browsing
browser
web-browser
1using Adw;
2using Gtk;
3using WebKit;
4using Application = Adw.Application;
5using Object = GObject.Object;
6using OuchBrowser.Utils;
7using OuchBrowser.UI;
8
9namespace OuchBrowser;
10
11public class Window
12{
13 private string palette_state = "new_tab";
14
15 public Window() { }
16
17 public void OnActivate(Object app, EventArgs args)
18 {
19 var application = (Application)app;
20 var window = new UI.Window(application);
21 var preferences = Preferences.New();
22 var about = About.New();
23 var view = new View(window.view!, window!);
24
25 SetupActions(window, application, preferences, about);
26
27 window.go_back!.SetSensitive(false);
28 window.go_forward!.SetSensitive(false);
29 window.refresh!.SetSensitive(false);
30 window.copy_link!.SetSensitive(false);
31 window.url_button!.SetSensitive(false);
32 window.website_settings!.SetSensitive(false);
33
34 // TODO: maybe make this a little bit less "hacky?"
35 window.content_sidebar_toggle!.OnClicked += (_, _) =>
36 {
37 window.osv!.SetShowSidebar(true);
38 window.sidebar_toggle!.SetActive(true);
39 window.frame!.SetMarginStart(0);
40 };
41 window.sidebar_toggle!.OnClicked += (_, _) =>
42 {
43 window.frame!.SetMarginStart(10);
44 };
45
46 window.url_entry!.OnActivate += (entry, _) =>
47 {
48 string query = entry.GetBuffer().GetText();
49
50 if (query == "") return;
51
52 if (palette_state == "new_tab")
53 {
54 Console.WriteLine($"url: {query}");
55 Console.WriteLine($"isURL: {Url.IsUrl(query)}");
56 Console.WriteLine($"starts with https or http: {query.StartsWith("https://") || query.StartsWith("http://")}");
57 Console.WriteLine("");
58
59 if (Url.IsUrl(query))
60 {
61 if (query.StartsWith("https://") || query.StartsWith("http://"))
62 {
63 view.AddTab(query, false);
64 }
65 else
66 {
67 view.AddTab($"https://{query}", false);
68 }
69 }
70 else
71 {
72 view.AddTab($"{window.settings!.GetString("search-engine")}{query}", false);
73 }
74 }
75 else
76 {
77 TabPage page = window.view!.GetSelectedPage()!;
78 WebView webview = (WebView)page.Child!;
79
80 Console.WriteLine($"url: {query}");
81 Console.WriteLine($"isURL: {Url.IsUrl(query)}");
82 Console.WriteLine($"starts with https or http: {query.StartsWith("https://") || query.StartsWith("http://")}");
83 Console.WriteLine("");
84
85 if (Url.IsUrl(query))
86 {
87 if (query.StartsWith("https://") || query.StartsWith("http://"))
88 {
89 webview.LoadUri(query);
90 }
91 else
92 {
93 webview.LoadUri($"https://{query}");
94 }
95 }
96 else
97 {
98 webview.LoadUri($"{window.settings!.GetString("search-engine")}{query}");
99 }
100 }
101
102 window.url_dialog!.ForceClose();
103 window.url_dialog!.SetCanClose(true);
104 window.overview!.SetOpen(false);
105 };
106
107 window.overview!.OnCreateTab += (_, _) =>
108 {
109 window.ActivateAction("palette-new", null);
110 return window.view!.GetSelectedPage()!;
111 };
112
113 window.Present();
114 window.url_dialog!.Present(window);
115 }
116
117 public void SetupActions(UI.Window window, Application application, PreferencesDialog preferences, Adw.AboutDialog about)
118 {
119 var actions = new Actions(window, application);
120
121 actions.AddAction("palette-new", ["<Ctrl>t"], (_, _) =>
122 {
123 window.overview!.SetOpen(false);
124
125 EntryBuffer buffer = EntryBuffer.New("", -1);
126 window.url_entry!.SetBuffer(buffer);
127 window.url_dialog!.Present(window);
128 window.url_entry!.GrabFocus();
129 palette_state = "new_tab";
130 });
131
132 actions.AddAction("palette", ["<Ctrl>l", "<Alt>d"], (_, _) =>
133 {
134 if (window.view!.GetNPages() == 0) return;
135
136 TabPage page = window.view!.GetSelectedPage()!;
137 WebView webview = (WebView)page.Child!;
138 EntryBuffer buffer = EntryBuffer.New(webview.GetUri(), -1);
139 window.url_entry!.SetBuffer(buffer);
140 window.url_dialog!.Present(window);
141 window.url_entry!.GrabFocus();
142 palette_state = "current_tab";
143 });
144
145 actions.AddAction("sidebar-toggle", ["<Ctrl><Shift>s"], (_, _) =>
146 {
147 if (window.view!.GetNPages() == 0) return;
148
149 if (window.osv!.GetShowSidebar())
150 {
151 window.sidebar_toggle!.Activate();
152 }
153 else
154 {
155 window.content_sidebar_toggle!.Activate();
156 }
157 });
158
159 foreach (int i in new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })
160 {
161 actions.AddAction($"tab-{i}", [$"<Ctrl>{i}"], (_, _) =>
162 {
163 if (window.view!.GetNPages() < i) return;
164 if (window.view!.GetNthPage(i - 1) == window.view!.GetSelectedPage()) return;
165
166 TabPage page = window.view!.GetNthPage(i - 1);
167 window.view!.SetSelectedPage(page);
168
169 if (!window.osv!.GetShowSidebar())
170 {
171 Toast toast = Toast.New(page.GetTitle());
172 toast.SetTimeout(1);
173 window.toast_overlay!.DismissAll();
174 window.toast_overlay!.AddToast(toast);
175 }
176 });
177 }
178
179 actions.AddAction("preferences", ["<Ctrl>comma"], (action, parameter) =>
180 {
181 preferences.Present(window);
182 });
183
184 actions.AddAction("about", [], (action, parameter) =>
185 {
186 about.Present(window);
187 });
188
189 actions.AddAction("refresh", ["<Ctrl>r"], (_, _) =>
190 {
191 TabPage page = window.view!.GetSelectedPage()!;
192 WebView webview = (WebView)page.Child!;
193
194 if (window.refresh!.GetIconName() == "cross-large-symbolic")
195 {
196 webview.StopLoading();
197 }
198 else
199 {
200 webview.Reload();
201 }
202 });
203
204 actions.AddAction("hard-refresh", ["<Ctrl><Shift>r"], (_, _) =>
205 {
206 TabPage page = window.view!.GetSelectedPage()!;
207 WebView webview = (WebView)page.Child!;
208
209 webview.ReloadBypassCache();
210 });
211
212 actions.AddAction("zoom-in", ["<Ctrl>equal"], (_, _) =>
213 {
214 TabPage page = window.view!.GetSelectedPage()!;
215 WebView webview = (WebView)page.Child!;
216 Toast toast = Toast.New("");
217
218 // these levels correspond to what would be seen in chromium
219 switch (webview.GetZoomLevel())
220 {
221 case 0.25: // 25%
222 webview.SetZoomLevel(0.33); // 33%
223 toast.SetTitle("33%");
224 toast.SetTimeout(1);
225 window.toast_overlay!.DismissAll();
226 window.toast_overlay!.AddToast(toast);
227 break;
228 case 0.33: // 33%
229 webview.SetZoomLevel(0.5); // 50%
230 toast.SetTitle("50%");
231 toast.SetTimeout(1);
232 window.toast_overlay!.DismissAll();
233 window.toast_overlay!.AddToast(toast);
234 break;
235 case 0.5: // 50%
236 webview.SetZoomLevel(0.67); // 67%
237 toast.SetTitle("67%");
238 toast.SetTimeout(1);
239 window.toast_overlay!.DismissAll();
240 window.toast_overlay!.AddToast(toast);
241 break;
242 case 0.67: // 67%
243 webview.SetZoomLevel(0.75); // 75%
244 toast.SetTitle("75%");
245 toast.SetTimeout(1);
246 window.toast_overlay!.DismissAll();
247 window.toast_overlay!.AddToast(toast);
248 break;
249 case 0.75: // 75%
250 webview.SetZoomLevel(0.8); // 80%
251 toast.SetTitle("80%");
252 toast.SetTimeout(1);
253 window.toast_overlay!.DismissAll();
254 window.toast_overlay!.AddToast(toast);
255 break;
256 case 0.8: // 80%
257 webview.SetZoomLevel(0.9); // 90%
258 toast.SetTitle("90%");
259 toast.SetTimeout(1);
260 window.toast_overlay!.DismissAll();
261 window.toast_overlay!.AddToast(toast);
262 break;
263 case 0.9: // 90%
264 webview.SetZoomLevel(1); // 100%
265 toast.SetTitle("100%");
266 toast.SetTimeout(1);
267 window.toast_overlay!.DismissAll();
268 window.toast_overlay!.AddToast(toast);
269 break;
270 case 1: // 100%
271 webview.SetZoomLevel(1.1); // 110%
272 toast.SetTitle("110%");
273 toast.SetTimeout(1);
274 window.toast_overlay!.DismissAll();
275 window.toast_overlay!.AddToast(toast);
276 break;
277 case 1.1: // 110%
278 webview.SetZoomLevel(1.25); // 125%
279 toast.SetTitle("125%");
280 toast.SetTimeout(1);
281 window.toast_overlay!.DismissAll();
282 window.toast_overlay!.AddToast(toast);
283 break;
284 case 1.25: // 125%
285 webview.SetZoomLevel(1.5); // 150%
286 toast.SetTitle("150%");
287 toast.SetTimeout(1);
288 window.toast_overlay!.DismissAll();
289 window.toast_overlay!.AddToast(toast);
290 break;
291 case 1.5: // 150%
292 webview.SetZoomLevel(1.75); // 175%
293 toast.SetTitle("175%");
294 toast.SetTimeout(1);
295 window.toast_overlay!.DismissAll();
296 window.toast_overlay!.AddToast(toast);
297 break;
298 case 1.75: // 175%
299 webview.SetZoomLevel(2); // 200%
300 toast.SetTitle("200%");
301 toast.SetTimeout(1);
302 window.toast_overlay!.DismissAll();
303 window.toast_overlay!.AddToast(toast);
304 break;
305 case 2: // 200%
306 webview.SetZoomLevel(2.5); // 250%
307 toast.SetTitle("250%");
308 toast.SetTimeout(1);
309 window.toast_overlay!.DismissAll();
310 window.toast_overlay!.AddToast(toast);
311 break;
312 case 2.5: // 250%
313 webview.SetZoomLevel(3); // 300%
314 toast.SetTitle("300%");
315 toast.SetTimeout(1);
316 window.toast_overlay!.DismissAll();
317 window.toast_overlay!.AddToast(toast);
318 break;
319 case 3: // 300%
320 webview.SetZoomLevel(4); // 400%
321 toast.SetTitle("400%");
322 toast.SetTimeout(1);
323 window.toast_overlay!.DismissAll();
324 window.toast_overlay!.AddToast(toast);
325 break;
326 case 4: // 400%
327 webview.SetZoomLevel(5); // 400%
328 toast.SetTitle("500%");
329 toast.SetTimeout(1);
330 window.toast_overlay!.DismissAll();
331 window.toast_overlay!.AddToast(toast);
332 break;
333 case 5: // 500%
334 Gdk.Display.GetDefault()!.Beep();
335 break;
336 }
337 });
338
339 actions.AddAction("zoom-out", ["<Ctrl>minus"], (_, _) =>
340 {
341 TabPage page = window.view!.GetSelectedPage()!;
342 WebView webview = (WebView)page.Child!;
343 Toast toast = Toast.New("");
344
345 // these levels correspond to what would be seen in chromium
346 switch (webview.GetZoomLevel())
347 {
348 case 5: // 500%
349 webview.SetZoomLevel(4); // 400%
350 toast.SetTitle("400%");
351 toast.SetTimeout(1);
352 window.toast_overlay!.DismissAll();
353 window.toast_overlay!.AddToast(toast);
354 break;
355 case 4: // 400%
356 webview.SetZoomLevel(3); // 300%
357 toast.SetTitle("300%");
358 toast.SetTimeout(1);
359 window.toast_overlay!.DismissAll();
360 window.toast_overlay!.AddToast(toast);
361 break;
362 case 3: // 300%
363 webview.SetZoomLevel(2.5); // 150%
364 toast.SetTitle("250%");
365 toast.SetTimeout(1);
366 window.toast_overlay!.DismissAll();
367 window.toast_overlay!.AddToast(toast);
368 break;
369 case 2.5: // 250%
370 webview.SetZoomLevel(2); // 200%
371 toast.SetTitle("200%");
372 toast.SetTimeout(1);
373 window.toast_overlay!.DismissAll();
374 window.toast_overlay!.AddToast(toast);
375 break;
376 case 2: // 200%
377 webview.SetZoomLevel(1.75); // 175%
378 toast.SetTitle("175%");
379 toast.SetTimeout(1);
380 window.toast_overlay!.DismissAll();
381 window.toast_overlay!.AddToast(toast);
382 break;
383 case 1.75: // 175%
384 webview.SetZoomLevel(1.5); // 150%
385 toast.SetTitle("150%");
386 toast.SetTimeout(1);
387 window.toast_overlay!.DismissAll();
388 window.toast_overlay!.AddToast(toast);
389 break;
390 case 1.5: // 150%
391 webview.SetZoomLevel(1.25); // 125%
392 toast.SetTitle("125%");
393 toast.SetTimeout(1);
394 window.toast_overlay!.DismissAll();
395 window.toast_overlay!.AddToast(toast);
396 break;
397 case 1.25: // 125%
398 webview.SetZoomLevel(1.1); // 400%
399 toast.SetTitle("110%");
400 toast.SetTimeout(1);
401 window.toast_overlay!.DismissAll();
402 window.toast_overlay!.AddToast(toast);
403 break;
404 case 1.1: // 110%
405 webview.SetZoomLevel(1); // 400%
406 toast.SetTitle("100%");
407 toast.SetTimeout(1);
408 window.toast_overlay!.DismissAll();
409 window.toast_overlay!.AddToast(toast);
410 break;
411 case 1: // 100%
412 webview.SetZoomLevel(0.9); // 400%
413 toast.SetTitle("90%");
414 toast.SetTimeout(1);
415 window.toast_overlay!.DismissAll();
416 window.toast_overlay!.AddToast(toast);
417 break;
418 case 0.9: // 90%
419 webview.SetZoomLevel(0.8); // 80%
420 toast.SetTitle("80%");
421 toast.SetTimeout(1);
422 window.toast_overlay!.DismissAll();
423 window.toast_overlay!.AddToast(toast);
424 break;
425 case 0.8: // 80%
426 webview.SetZoomLevel(0.75); // 75%
427 toast.SetTitle("75%");
428 toast.SetTimeout(1);
429 window.toast_overlay!.DismissAll();
430 window.toast_overlay!.AddToast(toast);
431 break;
432 case 0.75: // 75%
433 webview.SetZoomLevel(0.67); // 67%
434 toast.SetTitle("67%");
435 toast.SetTimeout(1);
436 window.toast_overlay!.DismissAll();
437 window.toast_overlay!.AddToast(toast);
438 break;
439 case 0.67: // 67%
440 webview.SetZoomLevel(0.5); // 67%
441 toast.SetTitle("50%");
442 toast.SetTimeout(1);
443 window.toast_overlay!.DismissAll();
444 window.toast_overlay!.AddToast(toast);
445 break;
446 case 0.5: // 50%
447 webview.SetZoomLevel(0.33); // 33%
448 toast.SetTitle("33%");
449 toast.SetTimeout(1);
450 window.toast_overlay!.DismissAll();
451 window.toast_overlay!.AddToast(toast);
452 break;
453 case 0.33: // 33%
454 webview.SetZoomLevel(0.25); // 25%
455 toast.SetTitle("25%");
456 toast.SetTimeout(1);
457 window.toast_overlay!.DismissAll();
458 window.toast_overlay!.AddToast(toast);
459 break;
460 case 0.25: // 25%
461 Gdk.Display.GetDefault()!.Beep();
462 break;
463 }
464 });
465
466 actions.AddAction("tab-close", ["<Ctrl>w"], (_, _) =>
467 {
468 if (window.view!.GetNPages() == 0)
469 {
470 window.Close();
471 }
472 else
473 {
474 TabPage page = window.view!.GetSelectedPage()!;
475 WebView webview = (WebView)page.Child!;
476
477 webview.TryClose();
478 window.view!.ClosePage(window.view!.GetSelectedPage()!);
479 if (window.view!.GetNPages() == 0)
480 {
481 window.refresh!.SetSensitive(false);
482 window.go_back!.SetSensitive(false);
483 window.go_forward!.SetSensitive(false);
484 window.url_button!.SetSensitive(false);
485 window.copy_link!.SetSensitive(false);
486 window.website_settings!.SetSensitive(false);
487 window.sidebar_toggle!.SetSensitive(false);
488 window.sidebar_toggle!.SetActive(true);
489 window.hostname!.SetLabel("");
490 window.osv!.SetShowSidebar(true);
491 }
492 }
493 });
494
495 actions.AddAction("go-back", ["<Ctrl>Left"], (_, _) =>
496 {
497 if (window.view!.GetNPages() == 0) return;
498
499 TabPage page = window.view!.GetSelectedPage()!;
500 WebView webview = (WebView)page.Child!;
501
502 webview.GoBack();
503 });
504
505 actions.AddAction("go-forward", ["<Ctrl>Right"], (_, _) =>
506 {
507 if (window.view!.GetNPages() == 0) return;
508
509 TabPage page = window.view!.GetSelectedPage()!;
510 WebView webview = (WebView)page.Child!;
511
512 webview.GoForward();
513 });
514
515 actions.AddAction("copy-link", ["<Ctrl><Shift>c"], (_, _) =>
516 {
517 if (window.view!.GetNPages() == 0) return;
518
519 TabPage page = window.view!.GetSelectedPage()!;
520 WebView webview = (WebView)page.Child!;
521 Toast toast = Toast.New("");
522
523 string uri = webview.GetUri();
524 Gdk.Display display = Gdk.Display.GetDefault()!;
525 Gdk.Clipboard clipboard = display!.GetClipboard();
526 clipboard.SetText(uri);
527
528 toast.SetTitle(window.gettext.GetString("Link copied"));
529 toast.SetTimeout(1);
530 window.toast_overlay!.DismissAll();
531 window.toast_overlay!.AddToast(toast);
532
533 webview.GoForward();
534 });
535 }
536}