I'm using JNA to manipulate application windows on Linux by sending Xlib messages but can't seem to move a window.
My original implementation executed wmctrl on the shell to move the windows and that successfully moved the windows. Unfortunately, there's a noticeable amount of overhead associated with calling shell programs from Java, so now I'm trying to make direct API calls using JNA. I'm using the X11 example available from the JNA website and can successfully do a few tricks, such as enumerating the window IDs and reading window properties, so I know JNA+Xlib is at least partially working.
First I tried moving the windows directly using XMoveWindow() but the window manager was apparently blocking those calls.
I ran across a thread that suggested I needed to send a client message using XSendMessage(), so I've done that below, but apparently XSendMessage() is failing because the window doesn't move and I get a return value of 0. I'm guessing I omitted something obvious, but can't quite figure it out. Any suggestions?
Note that, for the purposes of this example, the main method has a window ID hard-coded. This is the window ID of the window I'm trying to move (obtained using wmctrl -l on the console).
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.examples.unix.X11;
import com.sun.jna.examples.unix.X11.Atom;
import com.sun.jna.examples.unix.X11.AtomByReference;
import com.sun.jna.examples.unix.X11.Display;
import com.sun.jna.examples.unix.X11.Window;
import com.sun.jna.examples.unix.X11.WindowByReference;
import com.sun.jna.examples.unix.X11.XEvent;
import com.sun.jna.examples.unix.X11.XTextProperty;
import com.sun.jna.examples.unix.X11.XWindowAttributes;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.PointerByReference;
private static final int FALSE = 0; /** C-style boolean "false" */
private static final int TRUE = 1; /** C-style boolean "true" */
public static void main(String[] args) {
setWindowPos(new Window(0x01300007), 100, 100, 600, 400); // update the Window constructor with the appropriate ID given by wmctrl -l
}
public static boolean setWindowPos(Window window, int x, int y, int w, int h) {
final X11 x11 = X11.INSTANCE;
Display display = x11.XOpenDisplay(null);
NativeLong mask = new NativeLong(X11.SubstructureRedirectMask | X11.SubstructureNotifyMask | X11.ResizeRedirectMask);
XEvent event = new XEvent();
String msg = "_NET_MOVERESIZE_WINDOW"; //$NON-NLS-1$
long grflags = 0l; // use the default gravity of the window
if (x != -1) grflags |= (1 << 8);
if (y != -1) grflags |= (1 << 9);
if (w != -1) grflags |= (1 << 10);
if (h != -1) grflags |= (1 << 11);
event.xclient.type = X11.ClientMessage;
event.xclient.serial = new NativeLong(0l);
event.xclient.send_event = TRUE;
event.xclient.message_type = x11.XInternAtom(display, msg, false);
event.xclient.window = window;
event.xclient.format = 32;
event.xclient.data.l[0] = new NativeLong(grflags); // gravity flags
event.xclient.data.l[1] = new NativeLong(x);
event.xclient.data.l[2] = new NativeLong(y);
event.xclient.data.l[3] = new NativeLong(w);
event.xclient.data.l[4] = new NativeLong(h);
int status = x11.XSendEvent(display, x11.XDefaultRootWindow(display), FALSE, mask, event);
x11.XFlush(display); // need to XFlush if we're not reading X events
if (status == 0) { // 0 indicates XSendEvent failed
logger.error("setWindowPos: XSendEvent failed (" + msg + ")"); //$NON-NLS-1$
return false;
}
return true;
}
This might be a bit of a late answers but anyway...
What happens when you try to move a window is that the window (called "the client") sends an XConfigureRequest to the window manager. This happens because the window manager tells the X server that he is boss (by setting the substructure override flag on the client's parent).
The only way to bypass this is to set the override redirect flag on your client, do the move, and disable the override redirect flag (so that everything goes back to 'normal').
gl & hf.
Have you looked at XConfigureWindow?
I haven't actually tested this out yet since I just implemented it tonight and I'm developing on Windows, but it's worth a try....
public static interface X11Ext extends Library
{
public static X11Ext INSTANCE = (X11Ext)Native.loadLibrary("X11", X11Ext.class);
public int XConfigureWindow(X11.Display display, X11.Window window, int value_mask, XWindowChanges changes);
/**
* Use value_mask flags:
* CWX
* CWY
* CWWidth
* CWHeight
* CWBorderWidth
* CWSibling
* CWStackMode
*/
public class XWindowChanges extends Structure
{
public int x;
public int y;
public int width;
public int height;
public int border_width;
public X11.Window sibling;
public int stack_mode;
}
}
Related
Hi I having been trying to program an algorithm using breadth-first-search that finds the shortest path for the blue dot to exit in the game. I am new to java and having trouble running/understanding the algorithm for the class. I have a class called gameModel which stores the statuses of each dot. The algoirthm is meant to test the fastest way the blue dot can exit the board without going through an orange dot (SELECTED) and if no way out than the player wins. I keep running the program and getting compile errors which i dont know how to fix. I included the controller class where the short dot was ran.
import java.util.Random;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.*;
/**
* The class <b>GameController</b> is the controller of the game. It implements
* the interface ActionListener to be called back when the player makes a move. It computes
* the next step of the game, and then updates model and view.
*/
public class GameController implements ActionListener {
private int size;
private GameModel gameModel;
private GameView gameView;
private boolean click;
/**
* Constructor used for initializing the controller. It creates the game's view
* and the game's model instances
*
* #param size
* the size of the board on which the game will be played
*/
public GameController(int size) {
this.size = size;
this.gameModel = new GameModel(size);
this.gameView = new GameView (gameModel, this);
click = false;
}
/**
* Starts the game
*/
public void start(){
if (click){
List start = new List {gameModel.getCurrentDot().getX(), gameModel.getCurrentDot().getY()};
List<int> targets = new ArrayList<>();
List<int> blocked = nwq ArrayList<>();
for (int i = 0; i < size; i++){
targets.add(i, 0);
targets.add(i, size);
targets.add(1, size);
targets.add(1, 0);
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++)
if(gameModel.getstatus(i, j) == SELECTED){
blocked.add(i, j);
}
String path = Breadth-First-Start(start, targets, blocked);
gameView = new GameView(gameModel, this);
gameView.getBoardView().update();
}
}
public Breadth-First-Start(start, targets, blocked){ // Need help with
Queue queue = new LinkedList();
queue.add(start + "");
while(!queue.isEmpty()){
String p = queue.remove();
if (p != blocked){ //If p is not in blocked paths
if (p == targets){ //If p is in targets
return "q + {p}";
} else {
queue.add("q + {p}");
blocked.add(p);
}
}
}
You method public Breadth-First-Start(start, targets, blocked) is declared wrong. You cant have - in method name, also you need to specify the return type (only constructors dont have a return type to be defined). Also you need to specify parameter types. From what I understand targets and start look like of type String and blocked looks like a List, please try replace the method head by the following public void breadthFirstSearch(String start, String targets, List blocked) not sure what return type you want as you dont have any returns in the method. But in your case you probably want the path so maybe of type List, or a boolean to know if there is a path or not.
What you're wanting to do has to do with graph theory. If two nodes are connected, an edge between them is created. In this case the orange dots would not be connected to anything as a path cannot exist through them. Dijkstra's algorithm is very useful for doing what you want, although it's breadth first instead of depth first. I'd recommend starting there, I'm sure there are examples of that algorithm being implemented in java.
The edges of the graph have weights which are compared in order to find the shortest path between two nodes.
I see that your blocked list declaration has nwq in it instead of new. That may be your issue right there.
Hope this helps
Good Evening. I am working on a program thats similar to the old game LiteBrite, where you place colored pegs on a panel and it lights up. In my program, it works similar in that when you click on the panel, it will create a new Ellipse (which ive named ColorEllipse that has specifications for location, size, and color) and that it will store it to be saved. Currently it is as an arraylist but i need it to be in a regular array. I am told the way that would be to make a new array, and copy all the contents of the old array into the new array. Now currently i use an arraylist, but unforutnately this program has specifications where we need to use a regular Array.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.lang.reflect.Array;
import java.util.ArrayList;
public class LiteBritePanel extends javax.swing.JPanel{
private final static int OFFSET = 5;
private static int LINE_WIDTH = 2;
private static int CELL_WIDTH = 25;
public ArrayList <Colorable> _circles; // where ColorEllipses will be stored
private ButtonPanel controlpanel; // used to set the color of peg that will be placed
public LiteBritePanel() {
this.setBackground(java.awt.Color.black);
_circles = new ArrayList<Colorable>();
controlpanel = new ButtonPanel(this);
this.addMouseListener(new MyMouseListener(this));
this.add(controlpanel);
}
public void paintComponent(java.awt.Graphics aPaintBrush) {
super.paintComponent(aPaintBrush);
java.awt.Graphics2D pen = (java.awt.Graphics2D) aPaintBrush;
java.awt.Color savedColor = pen.getColor();
pen.setColor(java.awt.Color.black);
for (int ball=0;ball<_circles.size();ball++)
if(_circles.get(ball).isEmpty())
return;
else
_circles.get(ball).fill(pen);
pen.setColor(savedColor);
this.repaint();
}
public void mouseClicked(java.awt.event.MouseEvent e){
boolean foundSquare = false;
for (int ball=0; ball < _circles.size() && !foundSquare; ball++){
if (_circles.get(ball).contains(e.getPoint()) == true){
foundSquare = true;
_circles.remove(ball);
this.repaint();
}
}
}
private class MyMouseListener extends java.awt.event.MouseAdapter {
private LiteBritePanel _this;
public MyMouseListener(LiteBritePanel apanel){
_this = apanel;
}
public void mouseClicked(java.awt.event.MouseEvent e){
_circles.add(new ColorEllipse(controlpanel.getColor(), e.getPoint().x - (e.getPoint().x%CELL_WIDTH), e.getPoint().y - (e.getPoint().y%CELL_WIDTH), CELL_WIDTH-3,_this));
_this.requestFocus();
boolean foundSquare = false;
for (int ball=0; ball < _circles.size() && !foundSquare; ball++){
if (_circles.get(ball).contains(e.getPoint()) == true){
foundSquare = true;
// code for removing ball if one is placed
_this.repaint();
}
}
}
}
}`
Now currently it is set as an Arraylist, but I need it to be in a regular array per this specification. then when the panel is clicked on, it adds a new ColorEllipse into that Array at that specific location (and repaints as necessary for it to show up). A later part of the program would be when i touch a peg thats already placed, it removes it, but thats for another time. right now I need to know how to increment sizes of the array and copy its contents into it. Would anyone be able to tell me what I should change?
To copy arrays, you could use the System.arraycopy(...) method (System API):
public static void arraycopy(
Object src,
int srcPos,
Object dest,
int destPos,
int length)
where you would first create a destination array, perhaps twice as big as the the source array, and pass the old array, the starting index (0), the new array, the destination starting index (0), the length (length of old array), and it should do the rest.
Also you don't want to call repaint inside of paintComponent, trust me. Use a Swing Timer instead. There's a good tutorial on this that Google can help you find.
Depending on how big your board is you can just create an array that has the same size as your board. Alternatively you can do as Hovercraft suggested but it all depends on whether you want to trade cpu for memory.
int MAX_POSSIBLE_ELEMENTS = ...
Colorable[] _circles = new Colorable[MAX_POSSIBLE_ELEMENTS];
....rest of code...
Notice that the maximum number depends on the height and width of the board so you should know this at compiletime.
in c++ or c programming language, we know to change the cordinate we use gotoxy(x,y) and we can use looping and sleep to change the cordinate and making animation. like this;
for(x = 20; x < 25; x++){
gotoxy(x,20); cout << "*"
}
but my queston is how about in JAVAFX 2.0 programming? i'm using netbeans 7.2.
thanks for your any help.
Use the JavaFX Animation Package.
There are numerous examples in the JavaFX Animation Tutorial, as Andy pointed out in his comment.
And there is a cute example of a running horse animation loop.
The key is that you don't sleep the JavaFX application thread and you have to release control of the JavaFX thread back to the JavaFX system each time you update something and want it rendered. The JavaFX animation classes take care of these things for you so that you don't have to worry about it. If you just loop like you do in the sample code from your question, JavaFX will just render the scene once after your loop has completed and you will never see anything happen.
Here is a fairly boring example which uses a Timeline to emulate the c++ code in your question to move a dot a pixel every 400 milliseconds.
import java.util.Date;
import javafx.animation.*;
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
/** Simple JavaFX Animation Sample. */
public class AnimationSample extends Application {
private int x = 20;
private String status = "";
private final Circle dot = new Circle(20, 20, 3);
private final TimeCounter counter = new TimeCounter();
public static void main(String[] args) throws Exception { launch(args); }
#Override public void start(final Stage stage) throws Exception {
final Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new EventHandler() {
#Override public void handle(Event event) {
refreshScene();
}
}),
new KeyFrame(Duration.millis(400))
);
timeline.setCycleCount(Timeline.INDEFINITE);
stage.setScene(new Scene(new Group(dot), 50, 50));
stage.show();
counter.reset();
timeline.play();
}
private void refreshScene() {
gotoxy(x, 20);
status = "*****".equals(status) ? "*" : status + "*";
System.out.println(String.format("%7d", counter.elapsed()) + " ms " + x + " " + status);
if (x == 24) {
x = 20;
} else {
x++;
}
}
private void gotoxy(int x, int y) {
dot.setCenterX(x);
dot.setCenterY(y);
}
class TimeCounter {
private long start = new Date().getTime();
void reset() { start = new Date().getTime(); }
long elapsed() { return new Date().getTime() - start; }
}
}
There are three different options in JavaFX, depending on your needs.
The most basic one is AnimationTimer. It's equivalent to Swing's Timer. It simply contains a handle method which is called on every frame, and passed current time as argument. You probably want some internal bookkeeping so that you do not do expensive calculations every time handle is called.
Transition has an interpolate(frac) method, which gets called with values of frac between 0.0 and 1.0. It's up to you to do all UI changes you want to, based on the frac value. Both Transition and Timeline extend Animation, so you can set stuff like cycle duration, whether the Transition is reversed at end, etc.
Timeline is the most complex one. You define arbitrary amount of KeyFrames (think of states) that contain wanted properties of different Nodes, and the Timeline will do all the work for you interpolating how to animate the change between the provided values. For example, you can give a keyframe where x property of a Node is 0, and another where it's 100, and Timeline will do the animating for you.
Have look at using a Timeline Animation. It is a key component of animation in JavaFX and
is used to establish when, and in what sequence, key parts of an animation occur.
Here is an example
I'm trying to control some Java game from FireFox window. How can I send key and mouse events to that Java applet?
I'm using Windows XP if that matters.
Edit: I'm not trying to do this with Java even though i have the tag here. A c++ solution would be optimal.
You might try using Robot, but this might not work in FireFox. You can also use methods like abstractbutton.doClick()
If Robot doesn't work, key events you can synthesize by just setting text on a component, and mouse events you can use doClick() and requestFocus()
If none of that works, you might be able to accomplish your goals working with javascript and an html page.
Here is something that will work for keystrokes:
The recommended methods for both these actions are using SendInput
This website is perfect for beginning to understand sendinput
To find windows targets use Spy++, documentation
but I do have other examples below:
Example here is for Notepad using postmessage.
#include "TCHAR.h"
#include "Windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
HWND hwndWindowTarget;
HWND hwndWindowNotepad = FindWindow(NULL, L"Untitled - Notepad");
if (hwndWindowNotepad)
{
// Find the target Edit window within Notepad.
hwndWindowTarget = FindWindowEx(hwndWindowNotepad, NULL, L"Edit", NULL);
if (hwndWindowTarget) {
PostMessage(hwndWindowTarget, WM_CHAR, 'G', 0);
}
}
return 0;
}
You may also like to look at windows hooks, which can send mouse input
Or User32 mouse_event:
[DllImport("User32.Dll")]
private static extern void mouse_event(UInt32 dwFlags, int dx, int dy, UInt32 dwData, int dwExtraInfo);
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
public static void SendLeftClick(int X, int Y)
{
mouse_event((uint)MouseEventFlags.LEFTDOWN, 0, 0, 0, 0);
mouse_event((uint)MouseEventFlags.LEFTUP, 0, 0, 0, 0);
}
I have never been able to figure this one out; the usual suspects don't work.
Given:
FileDialog dlg=null;
dlg=new FileDialog(owner,"Select File to Load",FileDialog.LOAD);
dlg.setFile(null);
dlg.setVisible(true);
is there any way to get that dialog centered?
A key point is that at setVisible(), the calling thread is blocked until the dialog is dismissed; and any positioning prior to that seems to be ignored.
The below solution works for SWT, probably it can do the trick for AWT as well...
As it shows the dialog in left top corner of the current shell, a quick-and-dirty solution is to create a new, well-positioned and invisible shell and to open FileDialog from it. I got an acceptable result with the following code:
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
public class CenteredFileDialog extends Dialog {
protected Shell shell;
public FileDialog dialog;
private int width = 560; // WinXP default
private int height = 420;
public CenteredFileDialog(Shell parent, int style) {
super(parent, style);
shell = new Shell(getParent(), SWT.APPLICATION_MODAL);
dialog = new FileDialog(shell, style);
}
public Object open() {
shell.setSize(width, height);
Rectangle parentBounds = getParent().getBounds();
shell.setLocation(
parentBounds.x + (parentBounds.width - width) / 2,
parentBounds.y + (parentBounds.height - height) / 2);
Object result = dialog.open();
shell.dispose();
return result;
}
}
The class can be used this way:
CenteredFileDialog saveDialog = new CenteredFileDialog(getShell(), SWT.SAVE);
saveDialog.dialog.setFilterExtensions(new String[] { "*.txt" });
saveDialog.dialog.setFilterNames(new String[] { "Text (*.txt)" });
...
String f = (String)saveDialog.open();
if ( f != null ) {
name = f;
recentPath = saveDialog.dialog.getFilterPath();
}
The class only partially solves the problem for Windows platform (On MacOS the dialog is screen-centered anyway; on Linux I did not test) - first time the dialog appears centered relatively to the parent shell (which is what we need), and "remembers" its absolute position on the screen. By subsequent calls it always pops up in the same place, even if the main application window moved.
Despite the oddity, from my perspective the new behaviour is definitely better than the default unprofessionally looking top-left docking of the dialog.
Appears that this may still be a bug.... see last line of this (though its dated 2003)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4333836
I threw this together
FileDialog fd = new FileDialog(f, title, FileDialog.LOAD);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = fd.getSize().width;
int h = fd.getSize().height;
int x = (dim.width-w)/2;
int y = (dim.height-h)/2;
System.out.println("Dialog location: " + fd.getLocation().toString());
fd.setLocation(x, y);
System.out.println("Dialog location: " + fd.getLocation().toString());
fd.setVisible(true);
And my output was:
Dialog location: java.awt.Point[x=0,y=0]
Dialog location: java.awt.Point[x=840,y=525]
But the screen was still in the top left corner
Try this code: dlg.setLocationRelativeTo(null);
Using Java 7, Eclipse 4.4.1 and Ubuntu 14.04 I was able to find a solution for centering AWT FileDialog.
I was determined to find a solution because Apple recommends using awt.FileDialog over Swing's JFileChooser for a more native look and feel.
The trick is to give your FileDialog instance a size before setting its location.
Use the bounds of the contentPane of your main application frame to calculate the distance of the left corner Point (minX, minY) of FileDialog from the contentPane's center Point.
Then set the location of your FileDialog to this calculated Point, et voilá ... centered.
final FileDialog fileDialog = new FileDialog(applicationFrame,
"Choose a file", FileDialog.LOAD);
/* Lots of code to be able to center an awt.FileDialog on screen... */
Rectangle rect = applicationFrame.getContentPane().getBounds();
/*
* Making sure FileDialog has a size before setVisible, otherwise
* left corner's distance from contentPane center cannot be found.
*/
fileDialog.pack();
fileDialog.setSize(800, 600);
fileDialog.validate();
double width = fileDialog.getBounds().getWidth();
double height = fileDialog.getBounds().getHeight();
double x = rect.getCenterX() - (width / 2);
double y = rect.getCenterY() - (height/ 2);
/* Could be new Point(x, y) */
Point leftCorner = new Point();
leftCorner.setLocation(x, y);
fileDialog.setLocation(leftCorner);
fileDialog.setVisible(true);