99import com .openfin .desktop .channel .ChannelAction ;
1010import com .openfin .desktop .channel .ChannelClient ;
1111import com .openfin .desktop .win32 .ExternalWindowObserver ;
12+ import com .sun .jna .Native ;
13+ import com .sun .jna .platform .win32 .WinDef ;
14+ import org .json .JSONArray ;
1215import org .json .JSONObject ;
1316
1417import javax .swing .*;
1518import java .awt .*;
1619import java .awt .event .ActionEvent ;
1720import java .awt .event .ActionListener ;
21+ import java .awt .event .MouseAdapter ;
22+ import java .awt .event .MouseEvent ;
1823import java .awt .event .WindowAdapter ;
1924import java .awt .event .WindowEvent ;
2025import java .lang .System ;
@@ -23,52 +28,114 @@ public class LayoutFrame extends JFrame {
2328 private ExternalWindowObserver externalWindowObserver ;
2429 private JButton btnUndock ;
2530 private String windowName ;
31+ private ChannelClient channelClient ;
32+ private String appUuid ;
33+ private boolean frameless ;
2634
2735 public LayoutFrame (DesktopConnection desktopConnection , String appUuid , String windowName ) throws DesktopException {
36+ this (desktopConnection , appUuid , windowName , false );
37+ }
38+
39+ public LayoutFrame (DesktopConnection desktopConnection , String appUuid , String windowName , boolean frameless ) throws DesktopException {
2840 super ();
2941 System .out .println (windowName + " being created " );
42+ this .appUuid = appUuid ;
3043 this .windowName = windowName ;
44+ this .frameless = frameless ;
3145 this .setDefaultCloseOperation (JFrame .DO_NOTHING_ON_CLOSE );
3246 this .setPreferredSize (new Dimension (640 , 480 ));
3347 JPanel pnl = new JPanel (new FlowLayout (FlowLayout .CENTER ));
3448 this .btnUndock = new JButton ("undock" );
3549 this .btnUndock .setEnabled (false );
3650 pnl .add (btnUndock );
3751 this .getContentPane ().add (pnl );
52+
53+ if (frameless ) {
54+ this .setUndecorated (true );
55+ JPanel titleBar = new JPanel (new BorderLayout ());
56+ titleBar .setBackground (Color .DARK_GRAY );
57+ MouseAdapter myListener = new MouseAdapter () {
58+ int pressedAtX , pressedAtY ;
59+ @ Override
60+ public void mousePressed (MouseEvent e ) {
61+ pressedAtX = e .getX ();
62+ pressedAtY = e .getY ();
63+ System .out .println ("mouse pressed at x=" + pressedAtX + ", y=" + pressedAtY );
64+ }
65+
66+ @ Override
67+ public void mouseDragged (MouseEvent e ) {
68+ int distanceX = e .getX () - pressedAtX ;
69+ int distanceY = e .getY () - pressedAtY ;
70+ System .out .println ("dragged x=" + distanceX + ", y=" + distanceY );
71+ Point frameLocation = LayoutFrame .this .getLocation ();
72+ LayoutFrame .this .setLocation (frameLocation .x + distanceX , frameLocation .y + distanceY );
73+ }
74+ };
75+ titleBar .addMouseListener (myListener );
76+ titleBar .addMouseMotionListener (myListener );
77+
78+ JButton btnClose = new JButton ("X" );
79+ btnClose .addActionListener (new ActionListener () {
80+
81+ @ Override
82+ public void actionPerformed (ActionEvent e ) {
83+ LayoutFrame .this .dispose ();
84+ }});
85+ titleBar .add (btnClose , BorderLayout .EAST );
86+
87+ this .getContentPane ().add (titleBar , BorderLayout .NORTH );
88+
89+ }
90+
3891 this .pack ();
3992 this .setLocationRelativeTo (null );
4093 this .setVisible (true );
4194
42- this .externalWindowObserver = new ExternalWindowObserver (desktopConnection .getPort (), appUuid , windowName ,
43- this , new AckListener () {
44- @ Override
45- public void onSuccess (Ack ack ) {
46- ExternalWindowObserver observer = (ExternalWindowObserver ) ack .getSource ();
47- observer .getDesktopConnection ().getChannel ().connect ("of-layouts-service-v1" ).thenAccept (client ->{
48- btnUndock .addActionListener (new ActionListener () {
49- @ Override
50- public void actionPerformed (ActionEvent e ) {
51- JSONObject payload = new JSONObject ();
52- payload .put ("uuid" , appUuid );
53- payload .put ("name" , windowName );
54- client .dispatch ("UNDOCK-WINDOW" , payload );
55- }
56- });
95+ this .externalWindowObserver = new ExternalWindowObserver (desktopConnection .getPort (), appUuid , windowName , this ,
96+ new AckListener () {
97+ @ Override
98+ public void onSuccess (Ack ack ) {
99+ ExternalWindowObserver observer = (ExternalWindowObserver ) ack .getSource ();
100+ observer .getDesktopConnection ().getChannel ().connect ("of-layouts-service-v1" ).thenAccept (client -> {
101+ LayoutFrame .this .channelClient = client ;
102+ btnUndock .addActionListener (new ActionListener () {
103+ @ Override
104+ public void actionPerformed (ActionEvent e ) {
105+ JSONObject payload = new JSONObject ();
106+ payload .put ("uuid" , appUuid );
107+ payload .put ("name" , windowName );
108+ client .dispatch ("UNDOCK-WINDOW" , payload );
109+ }
110+ });
57111
58- client .register ("event" , new ChannelAction () {
59- @ Override
60- public JSONObject invoke (String action , JSONObject payload ) {
61- System .out .printf ("channel event " + action );
62- return null ;
63- }
64- });
112+ client .register ("event" , new ChannelAction () {
113+ @ Override
114+ public JSONObject invoke (String action , JSONObject payload ) {
115+ System .out .printf ("channel event " + action );
116+ return null ;
117+ }
118+ });
119+ });
120+
121+ }
122+
123+ @ Override
124+ public void onError (Ack ack ) {
125+ System .out .println (windowName + ": unable to register external window, " + ack .getReason ());
126+ }
65127 });
128+ this .externalWindowObserver .setUserGesture (!this .frameless );
129+ try {
130+ if (this .frameless ) {
131+ WindowOptions options = new WindowOptions ();
132+ options .setFrame (false );
133+ this .externalWindowObserver .setWindowOptions (options );
66134 }
67- @ Override
68- public void onError (Ack ack ) {
69- System .out .println (windowName + ": unable to register external window, " + ack .getReason ());
70- }
71- });
135+ this .externalWindowObserver .start ();
136+ } catch (Exception e ) {
137+ e .printStackTrace ();
138+ }
72139
73140 Window w = Window .wrap (appUuid , windowName , desktopConnection );
74141 w .addEventListener ("group-changed" , new EventListener () {
@@ -79,9 +146,10 @@ public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) {
79146 @ Override
80147 public void onSuccess (java .util .List <Window > result ) {
81148 if (result .size () > 0 ) {
82- LayoutFrame . this . btnUndock . setEnabled ( true );
149+ checkTabbing ( );
83150 } else {
84151 LayoutFrame .this .btnUndock .setEnabled (false );
152+ setHasFrame (LayoutFrame .this , true );
85153 }
86154 }
87155 }, null );
@@ -94,17 +162,62 @@ public void windowClosing(WindowEvent e) {
94162 try {
95163 LayoutFrame .this .cleanup ();
96164 LayoutFrame .this .dispose ();
97- } catch (Exception e1 ) {
165+ }
166+ catch (Exception e1 ) {
98167 e1 .printStackTrace ();
99168 }
100169 }
170+
101171 public void windowClosed (WindowEvent e ) {
102172 super .windowClosed (e );
103173 System .out .println (windowName + " closed " );
104174 }
105175 });
106176 }
107177
178+ private void checkTabbing () {
179+ JSONObject payload = new JSONObject ();
180+ payload .put ("uuid" , appUuid );
181+ payload .put ("name" , windowName );
182+ channelClient .dispatch ("GETTABS" , payload ).thenAccept (ack -> {
183+ if (ack .isSuccessful ()) {
184+ System .out .printf ("channel GETTABS " );
185+ JSONObject data = (JSONObject ) ack .getData ();
186+ Object result = data .get ("result" );
187+ if (result != null && result instanceof JSONArray ) {
188+ JSONArray tabs = (JSONArray ) result ;
189+ boolean enabled = !(tabs != null && tabs .length () > 0 );
190+ LayoutFrame .this .btnUndock .setEnabled (enabled );
191+ setHasFrame (LayoutFrame .this , false );
192+ } else {
193+ LayoutFrame .this .btnUndock .setEnabled (true );
194+ setHasFrame (LayoutFrame .this , true );
195+ }
196+ } else {
197+ System .out .printf ("channel GETTABS error " + ack .getReason ());
198+ }
199+ });
200+ }
201+
202+ private void setHasFrame (JFrame frame , boolean hasFrame ) {
203+ if (!this .frameless ) {
204+ SwingUtilities .invokeLater (new Runnable () {
205+ @ Override
206+ public void run () {
207+ System .out .println (windowName + " hasFrame=" + hasFrame );
208+ WinDef .HWND hWnd = new WinDef .HWND ();
209+ hWnd .setPointer (Native .getComponentPointer (frame ));
210+ LayoutFrame .this .externalWindowObserver .setHasFrame (hWnd , hasFrame );
211+ frame .setResizable (hasFrame );
212+ frame .invalidate ();
213+ frame .validate ();
214+ frame .repaint ();
215+ SwingUtilities .updateComponentTreeUI (frame );
216+ }
217+ });
218+ }
219+ }
220+
108221 public String getWindowName () {
109222 return windowName ;
110223 }
@@ -113,8 +226,53 @@ public void cleanup() {
113226 try {
114227 System .out .println (windowName + " cleaning up " );
115228 this .externalWindowObserver .dispose ();
116- } catch (Exception e ) {
229+ }
230+ catch (Exception e ) {
117231 e .printStackTrace ();
118232 }
119233 }
120- }
234+
235+
236+ public static void main (String [] args ) {
237+ final JFrame frame = new JFrame ();
238+ frame .setPreferredSize (new Dimension (640 , 480 ));
239+ JPanel pnl = new JPanel (new FlowLayout (FlowLayout .CENTER ));
240+
241+ frame .setUndecorated (true );
242+ JPanel titleBar = new JPanel (new BorderLayout ());
243+ titleBar .setBackground (Color .DARK_GRAY );
244+ MouseAdapter myListener = new MouseAdapter () {
245+ int pressedAtX , pressedAtY ;
246+ @ Override
247+ public void mousePressed (MouseEvent e ) {
248+ pressedAtX = e .getX ();
249+ pressedAtY = e .getY ();
250+ System .out .println ("mouse pressed at x=" + pressedAtX + ", y=" + pressedAtY );
251+ }
252+
253+ @ Override
254+ public void mouseDragged (MouseEvent e ) {
255+ int distanceX = e .getX () - pressedAtX ;
256+ int distanceY = e .getY () - pressedAtY ;
257+ System .out .println ("dragged x=" + distanceX + ", y=" + distanceY );
258+ Point frameLocation = frame .getLocation ();
259+ frame .setLocation (frameLocation .x + distanceX , frameLocation .y + distanceY );
260+ }
261+ };
262+ titleBar .addMouseListener (myListener );
263+ titleBar .addMouseMotionListener (myListener );
264+
265+ JButton btnClose = new JButton ("X" );
266+ btnClose .addActionListener (new ActionListener () {
267+ @ Override
268+ public void actionPerformed (ActionEvent e ) {
269+ frame .dispose ();
270+ }});
271+ titleBar .add (btnClose , BorderLayout .EAST );
272+ frame .getContentPane ().add (titleBar , BorderLayout .NORTH );
273+ frame .pack ();
274+ frame .setLocationRelativeTo (null );
275+ frame .setVisible (true );
276+ }
277+
278+ }
0 commit comments