1 This is a composition of these patches for Firefox 60: |
|
2 |
|
3 https://bugzilla.mozilla.org/show_bug.cgi?id=1441873 |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id=1441665 |
|
5 https://bugzilla.mozilla.org/show_bug.cgi?id=1456898 |
|
6 https://bugzilla.mozilla.org/show_bug.cgi?id=1457309 |
|
7 https://bugzilla.mozilla.org/show_bug.cgi?id=1457691 |
|
8 |
|
9 which fix popup window placement at CSD window mode. |
|
10 |
|
11 |
|
12 diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp |
|
13 --- a/widget/gtk/nsLookAndFeel.cpp |
|
14 +++ b/widget/gtk/nsLookAndFeel.cpp |
|
15 @@ -1076,19 +1076,18 @@ nsLookAndFeel::EnsureInit() |
|
16 nullptr); |
|
17 |
|
18 GetSystemFontInfo(gtk_widget_get_style_context(entry), |
|
19 &mFieldFontName, &mFieldFontStyle); |
|
20 |
|
21 gtk_widget_destroy(window); |
|
22 g_object_unref(labelWidget); |
|
23 |
|
24 - // Require GTK 3.10 for GtkHeaderBar support and compatible window manager. |
|
25 - mCSDAvailable = (gtk_check_version(3, 10, 0) == nullptr && |
|
26 - nsWindow::GetCSDSupportLevel() != nsWindow::CSD_SUPPORT_NONE); |
|
27 + mCSDAvailable = |
|
28 + nsWindow::GetSystemCSDSupportLevel() != nsWindow::CSD_SUPPORT_NONE; |
|
29 |
|
30 mCSDCloseButton = false; |
|
31 mCSDMinimizeButton = false; |
|
32 mCSDMaximizeButton = false; |
|
33 |
|
34 // We need to initialize whole CSD config explicitly because it's queried |
|
35 // as -moz-gtk* media features. |
|
36 WidgetNodeType buttonLayout[TOOLBAR_BUTTONS]; |
|
37 diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h |
|
38 --- a/widget/gtk/nsWindow.h |
|
39 +++ b/widget/gtk/nsWindow.h |
|
40 @@ -395,28 +395,26 @@ public: |
|
41 // From GDK |
|
42 int GdkCoordToDevicePixels(gint coord); |
|
43 LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point); |
|
44 LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y); |
|
45 LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect); |
|
46 |
|
47 virtual bool WidgetTypeSupportsAcceleration() override; |
|
48 |
|
49 - bool DoDrawTitlebar() const; |
|
50 - |
|
51 typedef enum { CSD_SUPPORT_SYSTEM, // CSD including shadows |
|
52 CSD_SUPPORT_CLIENT, // CSD without shadows |
|
53 CSD_SUPPORT_NONE, // WM does not support CSD at all |
|
54 CSD_SUPPORT_UNKNOWN |
|
55 } CSDSupportLevel; |
|
56 /** |
|
57 * Get the support of Client Side Decoration by checking |
|
58 * the XDG_CURRENT_DESKTOP environment variable. |
|
59 */ |
|
60 - static CSDSupportLevel GetCSDSupportLevel(); |
|
61 + static CSDSupportLevel GetSystemCSDSupportLevel(); |
|
62 |
|
63 protected: |
|
64 virtual ~nsWindow(); |
|
65 |
|
66 // event handling code |
|
67 void DispatchActivateEvent(void); |
|
68 void DispatchDeactivateEvent(void); |
|
69 void DispatchResized(); |
|
70 @@ -512,19 +510,21 @@ private: |
|
71 int mXDepth; |
|
72 mozilla::widget::WindowSurfaceProvider mSurfaceProvider; |
|
73 #endif |
|
74 |
|
75 // Upper bound on pending ConfigureNotify events to be dispatched to the |
|
76 // window. See bug 1225044. |
|
77 unsigned int mPendingConfigures; |
|
78 |
|
79 - bool mIsCSDAvailable; |
|
80 + // Window titlebar rendering mode, CSD_SUPPORT_NONE if it's disabled |
|
81 + // for this window. |
|
82 + CSDSupportLevel mCSDSupportLevel; |
|
83 // If true, draw our own window titlebar. |
|
84 - bool mIsCSDEnabled; |
|
85 + bool mDrawInTitlebar; |
|
86 // Draggable titlebar region maintained by UpdateWindowDraggingRegion |
|
87 LayoutDeviceIntRegion mDraggableRegion; |
|
88 |
|
89 #ifdef ACCESSIBILITY |
|
90 RefPtr<mozilla::a11y::Accessible> mRootAccessible; |
|
91 |
|
92 /** |
|
93 * Request to create the accessible for this window if it is top level. |
|
94 |
|
95 diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp |
|
96 --- a/widget/gtk/nsWindow.cpp |
|
97 +++ b/widget/gtk/nsWindow.cpp |
|
98 @@ -474,18 +474,18 @@ nsWindow::nsWindow() |
|
99 |
|
100 mTransparencyBitmapWidth = 0; |
|
101 mTransparencyBitmapHeight = 0; |
|
102 |
|
103 #if GTK_CHECK_VERSION(3,4,0) |
|
104 mLastScrollEventTime = GDK_CURRENT_TIME; |
|
105 #endif |
|
106 mPendingConfigures = 0; |
|
107 - mIsCSDAvailable = false; |
|
108 - mIsCSDEnabled = false; |
|
109 + mCSDSupportLevel = CSD_SUPPORT_NONE; |
|
110 + mDrawInTitlebar = false; |
|
111 } |
|
112 |
|
113 nsWindow::~nsWindow() |
|
114 { |
|
115 LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this)); |
|
116 |
|
117 delete[] mTransparencyBitmap; |
|
118 mTransparencyBitmap = nullptr; |
|
119 @@ -2814,17 +2814,17 @@ nsWindow::OnButtonReleaseEvent(GdkEventB |
|
120 LayoutDeviceIntPoint pos = event.mRefPoint; |
|
121 |
|
122 nsEventStatus eventStatus = DispatchInputEvent(&event); |
|
123 |
|
124 bool defaultPrevented = (eventStatus == nsEventStatus_eConsumeNoDefault); |
|
125 // Check if mouse position in titlebar and doubleclick happened to |
|
126 // trigger restore/maximize. |
|
127 if (!defaultPrevented |
|
128 - && mIsCSDEnabled |
|
129 + && mDrawInTitlebar |
|
130 && event.button == WidgetMouseEvent::eLeftButton |
|
131 && event.mClickCount == 2 |
|
132 && mDraggableRegion.Contains(pos.x, pos.y)) { |
|
133 |
|
134 if (mSizeState == nsSizeMode_Maximized) { |
|
135 SetSizeMode(nsSizeMode_Normal); |
|
136 } else { |
|
137 SetSizeMode(nsSizeMode_Maximized); |
|
138 @@ -3758,22 +3758,18 @@ nsWindow::Create(nsIWidget* aParent, |
|
139 gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel", |
|
140 gdk_get_program_class()); |
|
141 |
|
142 // each toplevel window gets its own window group |
|
143 GtkWindowGroup *group = gtk_window_group_new(); |
|
144 gtk_window_group_add_window(group, GTK_WINDOW(mShell)); |
|
145 g_object_unref(group); |
|
146 |
|
147 - int32_t isCSDAvailable = false; |
|
148 - nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable, |
|
149 - &isCSDAvailable); |
|
150 - if (NS_SUCCEEDED(rv)) { |
|
151 - mIsCSDAvailable = isCSDAvailable; |
|
152 - } |
|
153 + // We enable titlebar rendering for toplevel windows only. |
|
154 + mCSDSupportLevel = GetSystemCSDSupportLevel(); |
|
155 } |
|
156 |
|
157 // Create a container to hold child windows and child GtkWidgets. |
|
158 GtkWidget *container = moz_container_new(); |
|
159 mContainer = MOZ_CONTAINER(container); |
|
160 |
|
161 // "csd" style is set when widget is realized so we need to call |
|
162 // it explicitly now. |
|
163 @@ -3788,17 +3784,17 @@ nsWindow::Create(nsIWidget* aParent, |
|
164 * are drawn by Gtk+ to mShell. Content is rendered to mContainer |
|
165 * and we listen to the Gtk+ events on mContainer. |
|
166 * 3) We're running on Wayland. All gecko content is rendered |
|
167 * to mContainer and we listen to the Gtk+ events on mContainer. |
|
168 */ |
|
169 GtkStyleContext* style = gtk_widget_get_style_context(mShell); |
|
170 drawToContainer = |
|
171 !mIsX11Display || |
|
172 - (mIsCSDAvailable && GetCSDSupportLevel() == CSD_SUPPORT_CLIENT) || |
|
173 + (mCSDSupportLevel == CSD_SUPPORT_CLIENT) || |
|
174 gtk_style_context_has_class(style, "csd"); |
|
175 eventWidget = (drawToContainer) ? container : mShell; |
|
176 |
|
177 gtk_widget_add_events(eventWidget, kEvents); |
|
178 if (drawToContainer) |
|
179 gtk_widget_add_events(mShell, GDK_PROPERTY_CHANGE_MASK); |
|
180 |
|
181 // Prevent GtkWindow from painting a background to avoid flickering. |
|
182 @@ -6581,90 +6577,91 @@ nsWindow::ClearCachedResources() |
|
183 window->ClearCachedResources(); |
|
184 } |
|
185 } |
|
186 } |
|
187 |
|
188 nsresult |
|
189 nsWindow::SetNonClientMargins(LayoutDeviceIntMargin &aMargins) |
|
190 { |
|
191 - SetDrawsInTitlebar(aMargins.top == 0); |
|
192 - return NS_OK; |
|
193 + SetDrawsInTitlebar(aMargins.top == 0); |
|
194 + return NS_OK; |
|
195 } |
|
196 |
|
197 void |
|
198 nsWindow::SetDrawsInTitlebar(bool aState) |
|
199 { |
|
200 - if (!mIsCSDAvailable || aState == mIsCSDEnabled) |
|
201 - return; |
|
202 - |
|
203 - if (mShell) { |
|
204 - if (GetCSDSupportLevel() == CSD_SUPPORT_SYSTEM) { |
|
205 - SetWindowDecoration(aState ? eBorderStyle_border : mBorderStyle); |
|
206 - } |
|
207 - else { |
|
208 - /* Window manager does not support GDK_DECOR_BORDER, |
|
209 - * emulate it by CSD. |
|
210 - * |
|
211 - * gtk_window_set_titlebar() works on unrealized widgets only, |
|
212 - * we need to handle mShell carefully here. |
|
213 - * When CSD is enabled mGdkWindow is owned by mContainer which is good |
|
214 - * as we can't delete our mGdkWindow. To make mShell unrealized while |
|
215 - * mContainer is preserved we temporary reparent mContainer to an |
|
216 - * invisible GtkWindow. |
|
217 - */ |
|
218 - NativeShow(false); |
|
219 - |
|
220 - // Using GTK_WINDOW_POPUP rather than |
|
221 - // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less |
|
222 - // initialization and window manager interaction. |
|
223 - GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP); |
|
224 - gtk_widget_realize(tmpWindow); |
|
225 - |
|
226 - gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow); |
|
227 - gtk_widget_unrealize(GTK_WIDGET(mShell)); |
|
228 - |
|
229 - // Available as of GTK 3.10+ |
|
230 - static auto sGtkWindowSetTitlebar = (void (*)(GtkWindow*, GtkWidget*)) |
|
231 - dlsym(RTLD_DEFAULT, "gtk_window_set_titlebar"); |
|
232 - MOZ_ASSERT(sGtkWindowSetTitlebar, |
|
233 - "Missing gtk_window_set_titlebar(), old Gtk+ library?"); |
|
234 - |
|
235 - if (aState) { |
|
236 - // Add a hidden titlebar widget to trigger CSD, but disable the default |
|
237 - // titlebar. GtkFixed is a somewhat random choice for a simple unused |
|
238 - // widget. gtk_window_set_titlebar() takes ownership of the titlebar |
|
239 - // widget. |
|
240 - sGtkWindowSetTitlebar(GTK_WINDOW(mShell), gtk_fixed_new()); |
|
241 - } else { |
|
242 - sGtkWindowSetTitlebar(GTK_WINDOW(mShell), nullptr); |
|
243 - } |
|
244 - |
|
245 - /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=791081 |
|
246 - * gtk_widget_realize() throws: |
|
247 - * "In pixman_region32_init_rect: Invalid rectangle passed" |
|
248 - * when mShell has default 1x1 size. |
|
249 - */ |
|
250 - GtkAllocation allocation = {0, 0, 0, 0}; |
|
251 - gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr, |
|
252 - &allocation.width); |
|
253 - gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr, |
|
254 - &allocation.height); |
|
255 - gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation); |
|
256 - |
|
257 - gtk_widget_realize(GTK_WIDGET(mShell)); |
|
258 - gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell)); |
|
259 - mNeedsShow = true; |
|
260 - NativeResize(); |
|
261 - |
|
262 - gtk_widget_destroy(tmpWindow); |
|
263 - } |
|
264 - } |
|
265 - |
|
266 - mIsCSDEnabled = aState; |
|
267 + if (!mShell || |
|
268 + mCSDSupportLevel == CSD_SUPPORT_NONE || |
|
269 + aState == mDrawInTitlebar) { |
|
270 + return; |
|
271 + } |
|
272 + |
|
273 + if (mCSDSupportLevel == CSD_SUPPORT_SYSTEM) { |
|
274 + SetWindowDecoration(aState ? eBorderStyle_border : mBorderStyle); |
|
275 + } |
|
276 + else if (mCSDSupportLevel == CSD_SUPPORT_CLIENT) { |
|
277 + /* Window manager does not support GDK_DECOR_BORDER, |
|
278 + * emulate it by CSD. |
|
279 + * |
|
280 + * gtk_window_set_titlebar() works on unrealized widgets only, |
|
281 + * we need to handle mShell carefully here. |
|
282 + * When CSD is enabled mGdkWindow is owned by mContainer which is good |
|
283 + * as we can't delete our mGdkWindow. To make mShell unrealized while |
|
284 + * mContainer is preserved we temporary reparent mContainer to an |
|
285 + * invisible GtkWindow. |
|
286 + */ |
|
287 + NativeShow(false); |
|
288 + |
|
289 + // Using GTK_WINDOW_POPUP rather than |
|
290 + // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less |
|
291 + // initialization and window manager interaction. |
|
292 + GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP); |
|
293 + gtk_widget_realize(tmpWindow); |
|
294 + |
|
295 + gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow); |
|
296 + gtk_widget_unrealize(GTK_WIDGET(mShell)); |
|
297 + |
|
298 + // Available as of GTK 3.10+ |
|
299 + static auto sGtkWindowSetTitlebar = (void (*)(GtkWindow*, GtkWidget*)) |
|
300 + dlsym(RTLD_DEFAULT, "gtk_window_set_titlebar"); |
|
301 + MOZ_ASSERT(sGtkWindowSetTitlebar, |
|
302 + "Missing gtk_window_set_titlebar(), old Gtk+ library?"); |
|
303 + |
|
304 + if (aState) { |
|
305 + // Add a hidden titlebar widget to trigger CSD, but disable the default |
|
306 + // titlebar. GtkFixed is a somewhat random choice for a simple unused |
|
307 + // widget. gtk_window_set_titlebar() takes ownership of the titlebar |
|
308 + // widget. |
|
309 + sGtkWindowSetTitlebar(GTK_WINDOW(mShell), gtk_fixed_new()); |
|
310 + } else { |
|
311 + sGtkWindowSetTitlebar(GTK_WINDOW(mShell), nullptr); |
|
312 + } |
|
313 + |
|
314 + /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=791081 |
|
315 + * gtk_widget_realize() throws: |
|
316 + * "In pixman_region32_init_rect: Invalid rectangle passed" |
|
317 + * when mShell has default 1x1 size. |
|
318 + */ |
|
319 + GtkAllocation allocation = {0, 0, 0, 0}; |
|
320 + gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr, |
|
321 + &allocation.width); |
|
322 + gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr, |
|
323 + &allocation.height); |
|
324 + gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation); |
|
325 + |
|
326 + gtk_widget_realize(GTK_WIDGET(mShell)); |
|
327 + gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell)); |
|
328 + mNeedsShow = true; |
|
329 + NativeResize(); |
|
330 + |
|
331 + gtk_widget_destroy(tmpWindow); |
|
332 + } |
|
333 + |
|
334 + mDrawInTitlebar = aState; |
|
335 } |
|
336 |
|
337 gint |
|
338 nsWindow::GdkScaleFactor() |
|
339 { |
|
340 #if (MOZ_WIDGET_GTK >= 3) |
|
341 // Available as of GTK 3.10+ |
|
342 static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*)) |
|
343 @@ -6923,28 +6920,28 @@ nsWindow::SynthesizeNativeTouchPoint(uin |
|
344 event.touch.y = DevicePixelsToGdkCoordRoundDown(pointInWindow.y); |
|
345 |
|
346 gdk_event_put(&event); |
|
347 |
|
348 return NS_OK; |
|
349 } |
|
350 #endif |
|
351 |
|
352 -bool |
|
353 -nsWindow::DoDrawTitlebar() const |
|
354 -{ |
|
355 - return mIsCSDEnabled && mSizeState == nsSizeMode_Normal; |
|
356 -} |
|
357 - |
|
358 nsWindow::CSDSupportLevel |
|
359 -nsWindow::GetCSDSupportLevel() { |
|
360 +nsWindow::GetSystemCSDSupportLevel() { |
|
361 if (sCSDSupportLevel != CSD_SUPPORT_UNKNOWN) { |
|
362 return sCSDSupportLevel; |
|
363 } |
|
364 |
|
365 + // Require GTK 3.10 for GtkHeaderBar support and compatible window manager. |
|
366 + if (gtk_check_version(3, 10, 0) != nullptr) { |
|
367 + sCSDSupportLevel = CSD_SUPPORT_NONE; |
|
368 + return sCSDSupportLevel; |
|
369 + } |
|
370 + |
|
371 const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP"); |
|
372 if (currentDesktop) { |
|
373 // GNOME Flashback (fallback) |
|
374 if (strstr(currentDesktop, "GNOME-Flashback:GNOME") != nullptr) { |
|
375 sCSDSupportLevel = CSD_SUPPORT_CLIENT; |
|
376 // gnome-shell |
|
377 } else if (strstr(currentDesktop, "GNOME") != nullptr) { |
|
378 sCSDSupportLevel = CSD_SUPPORT_SYSTEM; |
|
379 diff -up firefox-60.0/widget/gtk/gtk3drawing.cpp.orig firefox-60.0/widget/gtk/gtk3drawing.cpp |
|
380 --- firefox-60.0/widget/gtk/gtk3drawing.cpp.orig 2018-04-26 22:07:36.000000000 +0200 |
|
381 +++ firefox-60.0/widget/gtk/gtk3drawing.cpp 2018-04-30 13:38:19.083949868 +0200 |
|
382 @@ -38,6 +38,16 @@ static ToolbarGTKMetrics sToolbarMetrics |
|
383 #define GTK_STATE_FLAG_CHECKED (1 << 11) |
|
384 #endif |
|
385 |
|
386 +static GtkBorder |
|
387 +operator+=(GtkBorder& first, const GtkBorder& second) |
|
388 +{ |
|
389 + first.left += second.left; |
|
390 + first.right += second.right; |
|
391 + first.top += second.top; |
|
392 + first.bottom += second.bottom; |
|
393 + return first; |
|
394 +} |
|
395 + |
|
396 static gint |
|
397 moz_gtk_get_tab_thickness(GtkStyleContext *style); |
|
398 |
|
399 @@ -3056,6 +3066,76 @@ GetScrollbarMetrics(GtkOrientation aOrie |
|
400 return metrics; |
|
401 } |
|
402 |
|
403 +/* |
|
404 + * get_shadow_width() from gtkwindow.c is not public so we need |
|
405 + * to implement it. |
|
406 + */ |
|
407 +bool |
|
408 +GetCSDDecorationSize(GtkWindow *aGtkWindow, GtkBorder* aDecorationSize) |
|
409 +{ |
|
410 + GtkStyleContext* context = gtk_widget_get_style_context(GTK_WIDGET(aGtkWindow)); |
|
411 + bool solidDecorations = gtk_style_context_has_class(context, "solid-csd"); |
|
412 + context = GetStyleContext(solidDecorations ? |
|
413 + MOZ_GTK_WINDOW_DECORATION_SOLID : |
|
414 + MOZ_GTK_WINDOW_DECORATION); |
|
415 + |
|
416 + /* Always sum border + padding */ |
|
417 + GtkBorder padding; |
|
418 + GtkStateFlags state = gtk_style_context_get_state(context); |
|
419 + gtk_style_context_get_border(context, state, aDecorationSize); |
|
420 + gtk_style_context_get_padding(context, state, &padding); |
|
421 + *aDecorationSize += padding; |
|
422 + |
|
423 + // Available on GTK 3.20+. |
|
424 + static auto sGtkRenderBackgroundGetClip = |
|
425 + (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) |
|
426 + dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); |
|
427 + |
|
428 + GtkBorder margin; |
|
429 + gtk_style_context_get_margin(context, state, &margin); |
|
430 + |
|
431 + GtkBorder extents = {0, 0, 0, 0}; |
|
432 + if (sGtkRenderBackgroundGetClip) { |
|
433 + /* Get shadow extents but combine with style margin; use the bigger value. |
|
434 + */ |
|
435 + GdkRectangle clip; |
|
436 + sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); |
|
437 + |
|
438 + extents.top = -clip.y; |
|
439 + extents.right = clip.width + clip.x; |
|
440 + extents.bottom = clip.height + clip.y; |
|
441 + extents.left = -clip.x; |
|
442 + |
|
443 + // Margin is used for resize grip size - it's not present on |
|
444 + // popup windows. |
|
445 + if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { |
|
446 + extents.top = MAX(extents.top, margin.top); |
|
447 + extents.right = MAX(extents.right, margin.right); |
|
448 + extents.bottom = MAX(extents.bottom, margin.bottom); |
|
449 + extents.left = MAX(extents.left, margin.left); |
|
450 + } |
|
451 + } else { |
|
452 + /* If we can't get shadow extents use decoration-resize-handle instead |
|
453 + * as a workaround. This is inspired by update_border_windows() |
|
454 + * from gtkwindow.c although this is not 100% accurate as we emulate |
|
455 + * the extents here. |
|
456 + */ |
|
457 + gint handle; |
|
458 + gtk_widget_style_get(GetWidget(MOZ_GTK_WINDOW), |
|
459 + "decoration-resize-handle", &handle, |
|
460 + NULL); |
|
461 + |
|
462 + extents.top = handle + margin.top; |
|
463 + extents.right = handle + margin.right; |
|
464 + extents.bottom = handle + margin.bottom; |
|
465 + extents.left = handle + margin.left; |
|
466 + } |
|
467 + |
|
468 + *aDecorationSize += extents; |
|
469 + |
|
470 + return (sGtkRenderBackgroundGetClip != nullptr); |
|
471 +} |
|
472 + |
|
473 /* cairo_t *cr argument has to be a system-cairo. */ |
|
474 gint |
|
475 moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, |
|
476 diff -up firefox-60.0/widget/gtk/gtkdrawing.h.orig firefox-60.0/widget/gtk/gtkdrawing.h |
|
477 --- firefox-60.0/widget/gtk/gtkdrawing.h.orig 2018-04-26 22:07:35.000000000 +0200 |
|
478 +++ firefox-60.0/widget/gtk/gtkdrawing.h 2018-04-30 13:38:19.083949868 +0200 |
|
479 @@ -334,6 +334,10 @@ typedef enum { |
|
480 */ |
|
481 MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE, |
|
482 |
|
483 + /* Client-side window decoration node. Available on GTK 3.20+. */ |
|
484 + MOZ_GTK_WINDOW_DECORATION, |
|
485 + MOZ_GTK_WINDOW_DECORATION_SOLID, |
|
486 + |
|
487 MOZ_GTK_WIDGET_NODE_COUNT |
|
488 } WidgetNodeType; |
|
489 |
|
490 @@ -606,4 +610,17 @@ GetToolbarButtonMetrics(WidgetNodeType a |
|
491 int |
|
492 GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout, int aMaxButtonNums); |
|
493 |
|
494 +/** |
|
495 + * Get size of CSD window extents of given GtkWindow. |
|
496 + * |
|
497 + * aGtkWindow [IN] Decorated window. |
|
498 + * aDecorationSize [OUT] Returns calculated (or estimated) decoration |
|
499 + * size of given aGtkWindow. |
|
500 + * |
|
501 + * returns: True if we have extract decoration size (for GTK 3.20+) |
|
502 + * False if we have only an estimation (for GTK+ before 3.20+) |
|
503 + */ |
|
504 +bool |
|
505 +GetCSDDecorationSize(GtkWindow *aGtkWindow, GtkBorder* aDecorationSize); |
|
506 + |
|
507 #endif |
|
508 diff -up firefox-60.0/widget/gtk/nsWindow.cpp.orig firefox-60.0/widget/gtk/nsWindow.cpp |
|
509 --- firefox-60.0/widget/gtk/nsWindow.cpp.orig 2018-04-30 13:37:32.145122854 +0200 |
|
510 +++ firefox-60.0/widget/gtk/nsWindow.cpp 2018-04-30 13:39:12.593752681 +0200 |
|
511 @@ -127,6 +127,7 @@ using namespace mozilla::widget; |
|
512 #endif |
|
513 |
|
514 #include "nsShmImage.h" |
|
515 +#include "gtkdrawing.h" |
|
516 |
|
517 #include "nsIDOMWheelEvent.h" |
|
518 |
|
519 @@ -3360,6 +3361,10 @@ nsWindow::OnWindowStateEvent(GtkWidget * |
|
520 aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN); |
|
521 } |
|
522 } |
|
523 + |
|
524 + if (mDrawInTitlebar && mCSDSupportLevel == CSD_SUPPORT_CLIENT) { |
|
525 + UpdateClientOffsetForCSDWindow(); |
|
526 + } |
|
527 } |
|
528 |
|
529 void |
|
530 @@ -6552,6 +6557,32 @@ nsWindow::ClearCachedResources() |
|
531 } |
|
532 } |
|
533 |
|
534 +/* nsWindow::UpdateClientOffsetForCSDWindow() is designed to be called from |
|
535 + * paint code to update mClientOffset any time. It also propagates |
|
536 + * the mClientOffset to child tabs. |
|
537 + * |
|
538 + * It works only for CSD decorated GtkWindow. |
|
539 + */ |
|
540 +void |
|
541 +nsWindow::UpdateClientOffsetForCSDWindow() |
|
542 +{ |
|
543 + // _NET_FRAME_EXTENTS is not set on client decorated windows, |
|
544 + // so we need to read offset between mContainer and toplevel mShell |
|
545 + // window. |
|
546 + if (mSizeState == nsSizeMode_Normal) { |
|
547 + GtkBorder decorationSize; |
|
548 + GetCSDDecorationSize(GTK_WINDOW(mShell), &decorationSize); |
|
549 + mClientOffset = nsIntPoint(decorationSize.left, decorationSize.top); |
|
550 + } else { |
|
551 + mClientOffset = nsIntPoint(0, 0); |
|
552 + } |
|
553 + |
|
554 + // Send a WindowMoved notification. This ensures that TabParent |
|
555 + // picks up the new client offset and sends it to the child process |
|
556 + // if appropriate. |
|
557 + NotifyWindowMoved(mBounds.x, mBounds.y); |
|
558 +} |
|
559 + |
|
560 nsresult |
|
561 nsWindow::SetNonClientMargins(LayoutDeviceIntMargin &aMargins) |
|
562 { |
|
563 @@ -6626,6 +6657,13 @@ nsWindow::SetDrawsInTitlebar(bool aState |
|
564 mNeedsShow = true; |
|
565 NativeResize(); |
|
566 |
|
567 + // When we use system titlebar setup managed by Gtk+ we also get |
|
568 + // _NET_FRAME_EXTENTS property for our toplevel window so we can't |
|
569 + // update the client offset it here. |
|
570 + if (aState) { |
|
571 + UpdateClientOffsetForCSDWindow(); |
|
572 + } |
|
573 + |
|
574 gtk_widget_destroy(tmpWindow); |
|
575 } |
|
576 |
|
577 diff -up firefox-60.0/widget/gtk/nsWindow.h.orig firefox-60.0/widget/gtk/nsWindow.h |
|
578 --- firefox-60.0/widget/gtk/nsWindow.h.orig 2018-04-30 13:37:32.143122861 +0200 |
|
579 +++ firefox-60.0/widget/gtk/nsWindow.h 2018-04-30 13:38:19.085949861 +0200 |
|
580 @@ -454,6 +454,8 @@ private: |
|
581 nsIWidgetListener* GetListener(); |
|
582 bool IsComposited() const; |
|
583 |
|
584 + void UpdateClientOffsetForCSDWindow(); |
|
585 + |
|
586 GtkWidget *mShell; |
|
587 MozContainer *mContainer; |
|
588 GdkWindow *mGdkWindow; |
|
589 diff -up firefox-60.0/widget/gtk/WidgetStyleCache.cpp.orig firefox-60.0/widget/gtk/WidgetStyleCache.cpp |
|
590 --- firefox-60.0/widget/gtk/WidgetStyleCache.cpp.orig 2018-04-26 22:07:35.000000000 +0200 |
|
591 +++ firefox-60.0/widget/gtk/WidgetStyleCache.cpp 2018-04-30 13:38:19.085949861 +0200 |
|
592 @@ -1285,6 +1285,22 @@ GetCssNodeStyleInternal(WidgetNodeType a |
|
593 "MOZ_GTK_HEADER_BAR_BUTTON_RESTORE is used as an icon only!"); |
|
594 return nullptr; |
|
595 } |
|
596 + case MOZ_GTK_WINDOW_DECORATION: |
|
597 + { |
|
598 + GtkStyleContext* parentStyle = |
|
599 + CreateSubStyleWithClass(MOZ_GTK_WINDOW, "csd"); |
|
600 + style = CreateCSSNode("decoration", parentStyle); |
|
601 + g_object_unref(parentStyle); |
|
602 + break; |
|
603 + } |
|
604 + case MOZ_GTK_WINDOW_DECORATION_SOLID: |
|
605 + { |
|
606 + GtkStyleContext* parentStyle = |
|
607 + CreateSubStyleWithClass(MOZ_GTK_WINDOW, "solid-csd"); |
|
608 + style = CreateCSSNode("decoration", parentStyle); |
|
609 + g_object_unref(parentStyle); |
|
610 + break; |
|
611 + } |
|
612 default: |
|
613 return GetWidgetRootStyle(aNodeType); |
|
614 } |
|