@@ -85,12 +85,16 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
8585 * @property {Object.<Number, Number> } map
8686 * A map of monitor id to position.
8787 * @property {Object.<Number, Object> } details
88- * Details of each monitor, including width, height, etc.
88+ * Details of each browser window, including width, height, etc.
89+ * @property {Object.<Number, Object> } rendered
90+ * Details of each rendered monitor, including width, height, etc.
91+ * This is used to display what is expected by guacd.
8992 */
9093 let monitorsInfos = {
9194 count : 1 ,
9295 map : { } ,
9396 details : { } ,
97+ rendered : { } ,
9498 } ;
9599
96100 const service = { } ;
@@ -227,21 +231,8 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
227231 client . runHandler ( message . data . handler . opcode ,
228232 message . data . handler . parameters ) ;
229233
230- if ( message . data . monitorsInfos ) {
231-
234+ if ( message . data . monitorsInfos )
232235 monitorsInfos = message . data . monitorsInfos ;
233- const monitorId = service . monitorId ;
234-
235- // Set the monitor size in the display
236- display . setMonitorSize (
237- monitorsInfos . details [ monitorId ] . width ,
238- monitorsInfos . details [ monitorId ] . height ,
239- ) ;
240-
241- client . offsetX = service . getOffsetX ( ) ;
242- client . offsetY = service . getOffsetY ( ) ;
243-
244- }
245236
246237 // Full screen mode instructions
247238 if ( message . data . fullscreen !== undefined ) {
@@ -284,6 +275,8 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
284275 client = guac_client ;
285276 display = client . getDisplay ( ) ;
286277
278+ client . onmultimonlayout = onmultimonlayout ;
279+
287280 // Close all secondary monitors on client disconnect
288281 if ( monitorType === "primary" )
289282 client . ondisconnect = service . closeAllMonitors ;
@@ -404,14 +397,6 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
404397 top : size . top ,
405398 } ) ;
406399
407- display . setMonitorSize (
408- monitorsInfos . details [ 0 ] . width ,
409- monitorsInfos . details [ 0 ] . height ,
410- ) ;
411-
412- client . offsetX = service . getOffsetX ( ) ;
413- client . offsetY = service . getOffsetY ( ) ;
414-
415400 // Monitor has been closed
416401 if ( size . width === 0 || size . height === 0 )
417402 client . sendSize ( 0 , 0 , monitorPosition , 0 ) ;
@@ -445,8 +430,8 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
445430 // are before the current monitor
446431 for ( const [ id , pos ] of Object . entries ( monitorsInfos . map ) ) {
447432 if ( pos < thisPosition ) {
448- const details = monitorsInfos . details [ id ] ;
449- if ( details ) offsetX += details . width ;
433+ const rendered = monitorsInfos . rendered [ id ] ;
434+ if ( rendered ?. width ) offsetX += rendered . width ;
450435 }
451436 }
452437
@@ -465,7 +450,7 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
465450 * The Y offset of the current monitor, in pixels.
466451 */
467452 service . getOffsetY = function getOffsetY ( ) {
468- const currentOffset = monitorsInfos . details [ service . monitorId ] ?. top ?? 0 ;
453+ const currentOffset = monitorsInfos . rendered [ service . monitorId ] ?. top ?? 0 ;
469454 return currentOffset - getLowestTopOffset ( ) ;
470455 }
471456
@@ -522,12 +507,12 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
522507 * The lowest top value of all monitors, in pixels.
523508 */
524509 function getLowestTopOffset ( ) {
525- let lowestTopValue = monitorsInfos . details [ 0 ] ?. top ?? 0 ;
510+ let lowestTopValue = monitorsInfos . rendered [ 0 ] ?. top ?? 0 ;
526511
527512 // Loop through all monitors to find the highest monitor
528- for ( const [ _ , details ] of Object . entries ( monitorsInfos . details ) ) {
529- if ( details ?. top < lowestTopValue ) {
530- lowestTopValue = details . top ;
513+ for ( const [ _ , rendered ] of Object . entries ( monitorsInfos . rendered ) ) {
514+ if ( rendered ?. top < lowestTopValue ) {
515+ lowestTopValue = rendered . top ;
531516 }
532517 }
533518
@@ -561,6 +546,7 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
561546 // If width or height is 0, remove monitor details
562547 if ( monitorDetails . width === 0 || monitorDetails . height === 0 ) {
563548 delete monitorsInfos . details [ monitorDetails . id ] ;
549+ delete monitorsInfos . rendered [ monitorDetails . id ] ;
564550 delete monitorsInfos . map [ monitorDetails . id ] ;
565551 }
566552 // Update or add monitor details
@@ -621,6 +607,54 @@ angular.module('client').factory('guacManageMonitor', ['$injector',
621607 service . pushBroadcastMessage ( 'size' , monitorDetails ) ;
622608 }
623609
610+ /**
611+ * Handle the multimonitor layout event. This is used to update the
612+ * monitorsInfos object when the layout changes.
613+ *
614+ * @param {Object } layout
615+ * An object describing the layout of monitors.
616+ */
617+ function onmultimonlayout ( layout ) {
618+ if ( ! layout )
619+ return ;
620+
621+ for ( const [ id , pos ] of Object . entries ( monitorsInfos . map ) ) {
622+
623+ // If the monitor is not in the layout, it is not known by
624+ // guacd anymore, so we close it
625+ if ( ! layout [ pos ] ) {
626+ service . closeMonitor ( id ) ;
627+ continue ;
628+ }
629+
630+ if ( ! monitorsInfos . rendered [ id ] )
631+ monitorsInfos . rendered [ id ] = { } ;
632+
633+ // Update the monitor details
634+ monitorsInfos . rendered [ id ] . width = layout [ pos ] . width ;
635+ monitorsInfos . rendered [ id ] . height = layout [ pos ] . height ;
636+ monitorsInfos . rendered [ id ] . top = layout [ pos ] . top ;
637+ monitorsInfos . rendered [ id ] . left = layout [ pos ] . left ;
638+
639+ // Set the monitor size in the display only if the id matches the
640+ // current monitor id
641+ if ( id === String ( service . monitorId ) ) {
642+ display . setMonitorSize (
643+ monitorsInfos . rendered [ id ] . width ,
644+ monitorsInfos . rendered [ id ] . height ,
645+ ) ;
646+ }
647+
648+ }
649+
650+ // Update the offset of the client when monitorInfos is fully updated
651+ // This is needed to ensure that the client knows the correct offset
652+ // of each monitor
653+ client . offsetX = service . getOffsetX ( ) ;
654+ client . offsetY = service . getOffsetY ( ) ;
655+
656+ }
657+
624658 // Close additional monitors when window is unloaded
625659 $window . addEventListener ( 'unload' , service . closeAllMonitors ) ;
626660
0 commit comments