1
+
2
+ // all the code in here is taken (and maybe slightly adapted) from: XXX
3
+
4
+ #include "screen.h"
5
+
6
+ gulong monitors_changed_handler_id = 0 ;
7
+
8
+ // This callback runs when the window is first set to appear on some screen, or
9
+ // when it's moved to appear on another.
10
+ void screen_changed (GtkWidget * widget , GdkScreen * old_screen ,
11
+ gpointer user_data )
12
+ {
13
+ GdkScreen * screen = gtk_widget_get_screen (widget );
14
+
15
+ WebKitWebView * web_view = (WebKitWebView * )user_data ;
16
+
17
+ // Die unless the screen supports compositing (alpha blending)
18
+ if (!gdk_screen_is_composited (screen ))
19
+ {
20
+ fprintf (stderr , "Your screen does not support transparency.\n" );
21
+ fprintf (stderr , "Maybe your compositor isn't running?\n" );
22
+ exit (69 ); // memes
23
+ }
24
+
25
+ // Ensure the widget can take RGBA
26
+ gtk_widget_set_visual (widget , gdk_screen_get_rgba_visual (screen ));
27
+
28
+ // Switch monitors-changed subscription from the old screen (if applicable)
29
+ // to the new one
30
+ if (old_screen )
31
+ g_signal_handler_disconnect (old_screen , monitors_changed_handler_id );
32
+
33
+ size_to_screen (GTK_WINDOW (widget ));
34
+ }
35
+
36
+ int get_monitor_rects (GdkDisplay * display , GdkRectangle * * rectangles )
37
+ {
38
+ int n = gdk_display_get_n_monitors (display );
39
+ GdkRectangle * new_rectangles = (GdkRectangle * )malloc (n * sizeof (GdkRectangle ));
40
+ for (int i = 0 ; i < n ; ++ i )
41
+ {
42
+ GdkMonitor * monitor = gdk_display_get_monitor (display , i );
43
+ gdk_monitor_get_geometry (monitor , & new_rectangles [i ]);
44
+ }
45
+ * rectangles = new_rectangles ;
46
+ // Ownership of the malloc'd memory transfers out
47
+ return n ;
48
+ }
49
+
50
+ // tell GTK that the entire window should be a clickthough region
51
+ void make_entire_window_clickthrough ()
52
+ {
53
+ cairo_rectangle_int_t rect = {0 , 0 , 0 , 0 };
54
+
55
+ cairo_region_t * shape =
56
+ cairo_region_create_rectangle (& rect );
57
+
58
+ GdkWindow * gdk_window = gtk_widget_get_window (GTK_WIDGET (window ));
59
+
60
+ if (gdk_window )
61
+ gdk_window_input_shape_combine_region (gdk_window , shape , 0 , 0 );
62
+
63
+ cairo_region_destroy (shape );
64
+ }
65
+
66
+ void size_to_screen (GtkWindow * window )
67
+ {
68
+ GdkScreen * screen = gtk_widget_get_screen (GTK_WIDGET (window ));
69
+
70
+ // Get total screen size. This involves finding all physical monitors
71
+ // connected, and examining their positions and sizes. This is as complex
72
+ // as it is because monitors can be configured to have relative
73
+ // positioning, causing overlapping areas and a non-rectangular total
74
+ // desktop area.
75
+ //
76
+ // We want our window to cover the minimum axis-aligned bounding box of
77
+ // that total desktop area. This means it's too large (even large bits of
78
+ // it may be outside the accessible desktop) but it's easier to manage than
79
+ // multiple windows.
80
+
81
+ GdkDisplay * display = gdk_display_get_default ();
82
+ GdkRectangle * rectangles = NULL ;
83
+ int nRectangles = get_monitor_rects (display , & rectangles );
84
+
85
+ // I can't think of a reason why someone's monitor setup might have a
86
+ // monitor positioned origin at negative x, y coordinates, but just in case
87
+ // someone does, we'll cover for it.
88
+ int x = 0 , y = 0 , width = 0 , height = 0 ;
89
+ for (int i = 0 ; i < nRectangles ; ++ i )
90
+ {
91
+ GdkRectangle rect = rectangles [i ];
92
+ int left = rect .x ;
93
+ int top = rect .y ;
94
+ int right = rect .x + rect .width ;
95
+ int bottom = rect .y + rect .height ;
96
+ if (left < x )
97
+ x = left ;
98
+ if (top < y )
99
+ y = top ;
100
+ if (width < right )
101
+ width = right ;
102
+ if (height < bottom )
103
+ height = bottom ;
104
+ }
105
+ free (rectangles );
106
+
107
+ gtk_window_move (GTK_WINDOW (window ), x , y );
108
+ gtk_window_set_default_size (window , width , height );
109
+ gtk_window_resize (window , width , height );
110
+ gtk_window_set_resizable (window , false);
111
+ }
0 commit comments