Menu

#26 Creating new NativeModalComponent

open
nobody
None
5
2012-09-23
2010-04-07
dvt
No

In order to create a new swt modal dialog with last DJ Project version, we have done some modificatons to your code:
- Inside ModalDialogUtils class: ModalDialogUtils, NativeModalComponent and showModalDialog should be public instead of package private.
- Inside MessagingInterface, method syncSend(Message): we add problems when moving a swt modal dialog over a swing interface, the swing interface display was not refreshed (the event queue is blocked), the problem is visible with a JFileDialog on Windows. So we send all events inside eventQueue (and not only the first one), then we wait only 500ms (and not 5000ms). Our code:
public Object syncSend(Message message) {
message.computeId(!isNativeSide());
if(!isUIThread()) {
return nonUISyncExec(message);
}
synchronized(LOCK) {
message.setUI(true);
message.setSyncExec(true);
if(!isAlive()) {
printFailedInvocation(message);
return null;
}
CommandResultMessage commandResultMessage = null;
try {
writeMessage(message);
List<CommandResultMessage> commandResultMessageList = new ArrayList<CommandResultMessage>();
while(true) {
commandResultMessage = processReceivedMessages();
if(commandResultMessage != null) {
if(commandResultMessage.getOriginalID() != message.getID()) {
commandResultMessageList.add(commandResultMessage);
commandResultMessage = null;
} else {
break;
}
} else {
synchronized(RECEIVER_LOCK) {
boolean isFirst = true;
while(receivedMessageList.isEmpty()) {
if(!isFirst) {
isFirst = true;
if(isNativeSide()) {
// Sometimes, AWT is synchronously waiting for the native side to pump some event.
// The native side is currently waiting, so we set a timeout and do some pumping.
NativeInterface.getDisplay().readAndDispatch();
} else {
// On Mac OS, under rare circumstances, we have a situation where SWT is waiting synchronously on AWT, while AWT is blocked here.
// We have to use a similar forced dispatching trick.
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();

                while (eventQueue.peekEvent() != null) {
                  AWTEvent nextEvent = eventQueue.getNextEvent();
                  if (nextEvent != null) {
                    Method dispatchMethod = EventQueue.class.getDeclaredMethod("dispatchEvent", AWTEvent.class);
                    dispatchMethod.setAccessible(true);
                    dispatchMethod.invoke(eventQueue, nextEvent);
                  }  
                }
              }
            }
            isFirst = false;
            isWaitingResponse = true;
            if(isNativeSide()) {
              RECEIVER_LOCK.wait(500);
            } else {
              // The Mac OS case is very rare, so we set a long timeout.
              RECEIVER_LOCK.wait(500);
            }
            isWaitingResponse = false;
          }
        }
      }
      if(!isAlive()) {
        printFailedInvocation(message);
        return null;
      }
    }
    synchronized(RECEIVER_LOCK) {
      if(!commandResultMessageList.isEmpty()) {
        receivedMessageList.addAll(0, commandResultMessageList);
      } else {
        if(!receivedMessageList.isEmpty()) {
          asyncUIExec(new Runnable() {
            public void run() {
              processReceivedMessages();
            }
          });
        }
      }
    }
  } catch(Exception e) {
    throw new IllegalStateException(e);
  }
  return processCommandResult(commandResultMessage);
}

}
We are not aware of the MAC OS case mentioned in your comments, so we don't know why we wait precisely 500ms, but waiting 5000ms is really too long when our interface needs a redraw.
We hope that you will integrate these modifications (or something similar) in your next version.

Fabien

Discussion


Log in to post a comment.